在我的Rails应用中,在创建新文章时,我需要一个Users
和Categories
的列表来显示某些下拉菜单,以便我可以选择文章的类别和作者。
目前我在控制器中执行此操作:
def new
@article = Article.new
@categories = Category.order('title asc').collect { |t| [t.title, t.id] }
@users = User.order('email asc').collect { |t| [t.email, t.id] }
end
然后在视图中:
<%= f.select :category_id, options_for_select(@categories), :prompt => '-- Please Select --', :required => true %>
但是根据RubyDocs的说法,这是不好的做法,并且它不是很干,因为我必须为编辑方法做这个。为了防止这种情况,我有两种可能的选择:
1。)使用这样的助手:
def users_for_select
User.order('email asc').collect { |t| [t.email, t.id] }
end
def categories_for_select
Category.order('title asc').collect { |t| [t.title, t.id] }
end
然后在视图中:
<%= f.select :category_id, options_for_select(categories_for_select), :prompt => '-- Please Select --', :required => true %>
2.)将其移至模型:
def self.categories_for_select
Category.order('title asc').collect { |t| [t.title, t.id] }
end
def self.users_for_select
User.order('email asc').collect { |t| [t.email, t.id] }
end
然后在控制器中执行此操作:
def new
@article = Article.new
@categories = Category.categories_for_select
@users = User.users_for_select
end
选项1感觉更干净,因为它从控制器中删除了代码,但我认为选项2会更好,因为它使用数据模型(按预期)并且控制器仍在发送数据(再次作为意图)但更干。
我觉得Helpers和Models之间有时会有一些重叠来获取数据。
答案 0 :(得分:2)
我现在会使用(1)你的助手方法。它简单明了。正如我在评论中所说,你可以在你的模型周围使用一个装饰器(例如使用draper)来添加我认为特定于视图的逻辑,如果你想要选项(2)。
关于助手方法的一个注意事项 - 使用pluck
而不是collect
,这样就不会选择列或实例化一堆你不需要的对象。
另外,order
defaults to asc
,所以你可以缩短整个事情:
def users_for_select
User.order(:email).pluck(:email, :id)
end
答案 1 :(得分:1)
我会使用辅助方法:
# in a helper
def category_options_for_select
options_for_select(Category.order(:title).pluck(:title, :id))
end
# in the view
<%= f.select :category_id, category_options_for_select, prompt: '-- Please Select --', required: true %>
答案 2 :(得分:1)
我个人会选择选项1。
当然,你可以把它放在你的模型中。你会发现,这将是一个让模型膨胀的好方法。然后你可能会考虑使用关注来隐藏膨胀。而且这种混乱的趋势仍在继续。
这就是为什么我认为选项1更好。即使您没有创建单独的类来处理格式化,您仍然将功能抽象为更小的段,这更容易扩展。当然,组合还要继承。
Bryany的这个awesome post为折射脂肪模型提供了很好的选择。
正如@damien在他的回答中已经指出的那样,你想要使用ActiveRecord的pluck
而不是ruby的collect
。 Pluck
查询数据库,使其只返回您需要的对象。