2009-10-26 40 views
2

說我有一個選擇菜單中的form_for對一個belongs_to的關聯分配用戶:輔助方法或模型或控制器?

... 
form.select :user_id, @users, :prompt => "Select a User" 
... 

目前我有在控制器@users如下:

@users = User.all.map { |u| [u.full_name, u.id] } 

我覺得像這樣的邏輯應該可能轉移到幫手或甚至模型中。 但我很困惑,在哪裏處理這個和如何。

回答

5

一般的答案取決於你打算使用它的頻率:

  • 幫手:在視圖或控制器通常但只用
  • 模型:經常使用的任何地方都可以使用的模型(其他型號)
  • 控制器:爲具體的行動很少,只有使用。

但在你的情況下,答案是沒有上述,並停止嘗試重新發明輪子。人們試圖用Rails做的事情中有95%是其他人已經完成的任務。它有一個非常好的機會,無論是在Rails Core中,還是以gem或插件形式存在。

你正在做的事情已經完成了,並被內置到Rails核心中。這是一個ActionView :: Helpers :: FormOpitionsHelper方法,名爲collection_select

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 %> 
+0

從來不知道collection_select,良好的通話。刪除了我在家中釀造這個代碼的答案。 – cwninja

0

這將是一種模型方法,因爲它具有模型的邏輯。幫助者方法應該有UI級邏輯(是否顯示鏈接)和HTML助手(例如生成鏈接的方法)

+0

我想是的。但是這不能也是UI邏輯,因爲它與選擇菜單的顯示方式有關嗎? – Cameron

+0

我覺得如果你提供的代碼支持你的意見,它應該是一個模型方法,這將是有幫助的;但我同意你的看法。 –

0

我認爲將它移到幫助程序是最好的,因爲它只是幫助你爲選擇框創建選項,即UI級別。

但是,除非你再次使用這段代碼,那麼它必須去模型! :)

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]} 
+0

是的,但如果full_name是一個方法,而不是數據庫中的實際列? – Cameron

+0

只需添加一個示例以數學您的評論 – Mike

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 
0

我有一個類似的問題,結束了使用的模塊,從而儘可能保持乾爽(我的大部分款式都有名字和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 
相關問題