避免重复操作new和create中相关对象的最佳方法

时间:2013-06-13 14:02:06

标签: ruby-on-rails

要在下面的示例中创建用户,我必须加载@projects@companies,因为它们是创建用户所必需的。

class UsersController < ApplicationController
  def new
    @user = User.new
    # duplication here
    @projects = Project.all
    @companies = Company.all
  end

  def create
   @user = User.new(params[:user])
    if @user.save
      redirect_to @user
    else
      # and here
      @projects = Project.all
      @companies = Company.all
      render :action => "new"
    end
  end
end

我必须在两个(复制)情况下加载这些依赖项,以便在用户无效时为new和create操作加载。

我可以通过在方法load_user_dependencies中封装这些依赖项来重构。

class UsersController < ApplicationController
  def new
    @user = User.new
    load_user_dependencies
  end

  def create
   @user = User.new(params[:user])
    if @user.save
      redirect_to @user
    else
      load_user_dependencies
      render :action => "new"
    end
  end

  private

  def load_user_dependencies
      @projects = Project.all
      @companies = Company.all
  end
end

或者将它们添加为helper_methods。

 class UsersController < ApplicationController
  helper_method :projects, :companies

  def new
    @user = User.new
  end

  def create
   @user = User.new(params[:user])
    if @user.save
      redirect_to @user
    else
      render :action => "new"
    end
  end

  def projects
    @projects ||= Project.all
  end

  def companies
    @companies ||= Company.all
  end
end

我还可以创建View Object

class UserView
  def products
    @products ||= Product.all
  end

  def companies
    @companies ||= Company.all
  end
end

class UsersController < ApplicationController
   def new
     @user = User.new
     @user_view = UserView.new
   end

   def create
    @user = User.new(params[:user])
     if @user.save
       redirect_to @user
     else
       @user_view = UserView.new
       render :action => "new"
     end
   end
 end

其他选项是使用Presenter

class UserPresenter < SimpleDelegator
  def products
     @products ||= Product.all
  end

  def companies
    @companies ||= Company.all
  end
end

class UsersController < ApplicationController
   def new
     @user = UserPresenter.new User.new
   end

   def create
    @user = UserPresenter.new User.new(params[:user])
     if @user.save
       redirect_to @user
     else
       render :action => "new"
     end
   end
 end

你们通常如何处理情景?

1 个答案:

答案 0 :(得分:1)

这有点个人品味问题,但在我们的项目中,如果它适合我​​们在视图中进行,如果它很复杂,我们在before_filter中进行。

查看 - 如果它没有任何逻辑,则无需为此创建变量。如果您的表单包含在部分中,则非常有用,因为它只能轻松维护一次。

<%= form.select :project_id, Project.all, :id, :name %>

如果它可以根据任何因素而改变,那么控制器中的before_filter:

MyController
  before_filter :find_projects, :except => [:destroy, :some_method] # Will load the values but not for the destroy or some_method actions

  def find_projects
    @projects = Project.where(:some conditions => true)
  end