要在下面的示例中创建用户,我必须加载@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
你们通常如何处理情景?
答案 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