将实例变量从Controller移出到Service Class

时间:2017-02-01 10:15:16

标签: ruby-on-rails ruby ruby-on-rails-5

我的Rails 5应用程序的控制器开始变得拥挤,所以我正在考虑尽可能多地移动到服务类。这适用于大多数业务逻辑,但我似乎无法将任何实例变量移出方法。我想要做的是遵循这种模式:

# users_controller.rb
class UsersController < ApplicationController
  def show
    UserService.new.set_user_detail_variables(params[:id])

    respond_to do |format|
      format.html
      format.json { render json: @user }
    end
  end
end

# user_service.rb
class UserService

  def set_user_detail_variables(user_id)
    @user = User.find(user_id)
    @cars = Car.where(brand: 'Volvo')
  end

end

是否可以将实例变量移出控制器?

2 个答案:

答案 0 :(得分:1)

如果你想在一个单独的方法中做一些计算并在那里分配一些实例变量,然后在你的视图中使用它们,你可以将这些方法移动到mixin并在控制器中包含mixin。

# mixins/user_helper.rb
module UserHelper
  def set_user_detail_variables(user_id)
    @user = User.includes(:comments, :addresses, :posts).find(user_id)

    @user_comments  = @user.comments
    @user_addresses = @user.addresses
    @user_posts     = @user.posts
  end
end

# controllers/users_controller.rb
class UsersController < ApplicationController
  include UserHelper

  def show
    set_user_detail_variables(params[:id])

    respond_to do |format|
      format.html
      format.json { render json: @user }
    end
  end
end

这样你的控制器就不会变得冗长,而且你也可以使用你的变量。

答案 1 :(得分:1)

根据您更新的问题更新

我认为您必须在控制器操作中至少有一个实例变量来呈现其数据或将其作为json发送。并且服务对象不是那样做的事情。旨在执行单个巨大或复杂操作的服务对象。

您可以做的是使用Presenter对象(Presenter模式作为Rails社区看到它)。 Rails中的这种模式对于隐藏&#34;单个实例中的几个实例变量。因此,将实例变量放在单个Presenter变量中。然后将演示者传递给视图或将其数据呈现​​为json

示例

在:

class UsersController < ApplicationController
  def show
    @user = User.find(user_id)
    @cars = Car.where(brand: 'Volvo')

    respond_to do |format|
      format.html
      format.json { render json: @user, @car }
    end
  end
end

后:

class UsersController < ApplicationController
  def show
    user = User.find(user_id)
    cars = Car.where(brand: 'Volvo')
    @show_presenter = ShowPresenter.new(user, cars)

    respond_to do |format|
      format.html
      format.json { render json: @show_presenter }
    end
  end
end

class ShowPresenter
  def initialize(user, cars)
    @user = user
    @cars = cars
  end
end