假设我有一个带有选择菜单的form_for,用于在belongs_to关联上分配用户:
...
form.select :user_id, @users, :prompt => "Select a User"
...
目前我在控制器中有@users如下:
@users = User.all.map { |u| [u.full_name, u.id] }
我觉得这个逻辑可能会转移到帮助者甚至模型中。 但我很困惑在哪里处理这个以及如何处理。
答案 0 :(得分:5)
一般答案取决于您使用它的频率:
但是在你的情况下,答案不是上述情况,而是停止尝试重新发明轮子。人们尝试使用Rails的事情中,大约95%是其他人已经完成的任务。它很可能是在Rails Core中,或者以gem或plugin形式存在。
您尝试做的事情已经完成,并且内置于Rails核心。它是一个名为collection_select
的ActionView :: Helpers :: FormOpitionsHelper方法collection_select正是你想要做的,它也比单一目的方法更强大。
它具有
的形式collection_select(object, method, collection, value_method,
text_method, select_options = {}, html_options)
将value_method和text_method发送到集合中的每个项目,以获取每个选择选项的选择值和显示文本。不要求列名都是。
像这样使用:
<% form_for @whatever do |form| %>
<%= form.collection_select :user_id, User.all, :id,
:full_name, :prompt => "Select a User" %>
<% end %>
答案 1 :(得分:1)
你应该把它放在一个模型中,因为它是面向逻辑的,你应该永远不会这样做
@users = User.all.map { |u| [u.full_name, u.id] }
但是
@users = User.all(:select => "full_name, id")
如果full_name是一个方法,那就是:
@users = User.all(:select => "last_name, first_name, id").map{|u| [User.full_name(u.first_name, u.last_name), u.id]}
答案 2 :(得分:0)
这将是一种模型方法,因为它具有模型的逻辑。 Helper方法应该具有UI级逻辑(是否显示链接)和HTML帮助程序(例如,生成链接的方法)
答案 3 :(得分:0)
我认为将其转移到助手是最好的事情,因为它只是帮助您为选择框创建选项,这是UI级别。
但除非你再次使用那段代码,否则它必须去模型! :)
答案 4 :(得分:0)
模特:
def self.select_display
all(:select => "id, first_name, last_name").map { |u| [u.name, u.id] }
end
观点:
select :user_id, User.select_display
答案 5 :(得分:0)
我遇到了类似的问题并最终使用了一个模块,以便尽可能保持DRY(我的大多数模特都有一个名字和一个id)
模块看起来像这样:
#lib/all_for_select.rb
module AllForSelect
def all_for_select(permission = :read)
#used declarative authorization for checking permissions
#replace first line with self.find(:all, if not using it
with_permissions_to(permission).find( :all,
:select =>"#{table_name}.id, #{table_name}.name",
:order => "#{table_name}.name ASC"
)
end
end
在您的模型上,您只需扩展模块:
class Client < ActiveRecord::Base
extend AllForSelect
...
end
在您的控制器上,您可以调用Client.all_for_select。我通常在before_filter上执行此操作
class SalesController < ApplicationController
before_filter :fill_selects, :only => [:new, :edit, :update, :create]
...
private
def fill_selects
@clients = Client.all_for_select
end