Вспомогательный метод или модель или контроллер? - PullRequest
2 голосов
/ 27 октября 2009

Скажем, у меня есть form_for с меню выбора, чтобы назначить пользователя для связи с принадлежащим:

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

В настоящее время у меня @users в контроллере:

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

Я чувствую, что эта логика может быть перенесена в помощника или даже в модель. Но я не совсем понимаю, где и как с этим бороться.

Ответы [ 6 ]

5 голосов
/ 27 октября 2009

Общий ответ зависит от того, как часто вы собираетесь его использовать:

  • помощник: часто используется, но только в представлениях или контроллерах
  • контроллер: используется редко и только для определенных действий.

Однако в вашем случае ответ не один из вышеперечисленных, и прекратите пытаться заново изобрести колесо. Около 95% того, что люди пытаются делать с Rails, - это задачи, которые уже сделали другие. Есть очень хороший шанс, что он либо находится в Rails Core, либо существует в виде гема или плагина.

То, что вы пытаетесь сделать, уже сделано и встроено в ядро ​​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 %>
1 голос
/ 27 октября 2009

Вы должны поместить это в модель, так как она ориентирована на логику, и, кстати, вы никогда не должны делать

@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 голосов
/ 27 октября 2009

У меня была похожая проблема, и в итоге я использовал модуль, чтобы оставаться максимально сухим (большинство моих моделей имели имя и идентификатор)

Модуль выглядел так:

#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
0 голосов
/ 27 октября 2009

Модель:

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 голосов
/ 27 октября 2009

Я думаю, что лучше всего передать его помощнику, поскольку он просто помогает вам создать опции для поля выбора, то есть уровня пользовательского интерфейса.

Но если вы не будете использовать этот кусок кода снова, то к модели он должен идти! :)

0 голосов
/ 27 октября 2009

Это был бы модельный метод, так как он имеет логику для модели. Вспомогательные методы должны иметь логику уровня пользовательского интерфейса (отображать ссылку или нет) и HTML-помощники (например, методы для создания ссылок)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...