从Helper获取数据或在Rails中使用Model

时间:2017-01-03 11:40:39

标签: ruby-on-rails ruby

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

我觉得Helpers和Models之间有时会有一些重叠来获取数据。

3 个答案:

答案 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的collectPluck查询数据库,使其只返回您需要的对象。