从帮助程序获取数据或使用 Rails 中的模型



在我的 Rails 应用程序中创建新文章时,我需要一些下拉菜单的UsersCategories列表,以便我可以为文章选择类别和作者。

目前我在控制器中执行此操作:

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 会更好,因为它使用数据模型(按预期)并且控制器仍在发送数据(再次按预期)但更 DRY。

我觉得帮助程序和模型之间有时在获取数据方面存在一些重叠。

我现在会使用 (1) 您的助手方法。它简单明了。正如我在评论中所说,如果您对选项 (2) 很感兴趣,您可以在模型周围使用装饰器(例如使用 draper)来添加我认为非常特定于视图的逻辑。

关于帮助程序方法的一个说明 - 使用 pluck 而不是 collect,这样您就不会选择列或实例化一堆不需要的对象。

此外,order默认为 asc ,因此您可以将整个内容缩短为:

def users_for_select
  User.order(:email).pluck(:email, :id)
end

我会为此使用一个辅助方法:

# 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 %>

我个人会选择选项 1。

当然,你可以把它放在你的模型中。您迟早会发现这将是使模型膨胀的好方法。然后,您可能会考虑使用担忧来隐藏膨胀。混乱的趋势仍在继续。

这就是为什么我认为选项 1 更好。即使您没有创建单独的类来处理格式设置,您仍然将功能抽象到更易于扩展的较小段中。当然,作曲胜过继承。

Bryany的这篇很棒的帖子为耐火脂肪模型提供了很好的选择。

正如@damien在他的回答中已经指出的那样,您需要使用ActiveRecord的pluck而不是ruby的collectPluck查询数据库,以便它只返回您需要的对象。

最新更新