Использование того же действия для отображения всех (индексных) объектов, но также для отображения списка, ограниченного параметром URL - PullRequest
2 голосов
/ 07 мая 2009

У меня возникла проблема с хорошим способом сделать следующее. У меня очень общая модель Org и модель User. Орг has_many :users и User belongs_to :org.

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

map.resources :users
map.resources :orgs, :has_many => :users

Проблема в том, что они оба возвращаются к одним и тем же действиям в пользовательском контроллере. Код контроллера начинает сильно запутываться, потому что мне приходится проверять наличие параметра: org_id. Затем я должен решить, возвращать ли нормальные результаты вызова поиска для Пользователя или поиск, находящийся в области видимости для организации. Я не уверен, что лучшее решение здесь, или какова лучшая практика. Если бы кто-то, обладающий некоторыми знаниями об этом, мог бы просветить меня, это было бы здорово.

Ответы [ 4 ]

1 голос
/ 07 мая 2009

Я использую плагин resource_controller для большинства случаев. С ним вы просто положите:

class UsersController < ApplicationController
  resource_controller
  belongs_to :org
end

Работает с вложенными и не вложенными ресурсами.

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

class UsersController < ApplicationController
  def index
    @org = Org.find(params[:org_id]) unless params[:org_id].blank?
    @users = params[:org_id].blank? ? User.all : @org.users
    ...
  end
end
1 голос
/ 08 мая 2009

Другой способ сделать это без плагина - использовать named_scope . Вы можете создать именованную область в User, которая фильтрует по org_id, если она не пуста.

class User < ActiveRecord::Base
  belongs_to :org
  named_scope :by_org, lambda{|org| org.blank? ? {} : { :conditions => ['org_id = ?', org] }}
end

А в контроллере просто используйте вашу именованную область видимости. Таким образом, если вы в конечном итоге добавите дополнительные параметры фильтра в контроллер, вам не нужно дублировать их:

class UsersController < ApplicationController
  def index
    @users = User.by_org(params[:org_id]).all
    ...
  end
end
1 голос
/ 07 мая 2009

Не совсем тот ответ, который вы, вероятно, искали на техническом уровне, но я использую плагин для своих проектов, который позаботится обо мне. Взгляните на make_resourceful .

make_resourceful do
 actions :all
 belongs_to :org
end

Он определит для вас все остальное, не нужно определять стандартное действие. Он даже обнаружит область видимости и определит ее для вас. (если это не другой плагин, который я использую, о котором я забыл)

0 голосов
/ 08 мая 2009

Что я обычно делаю, это:

class UsersController < ApplicationController
  def index
    root = Org.find(params[:org_id]) if params[:org_id]
    root = User if root.nil?
    @users = root.all(:conditions => {...}, :order => "...")
  end
end

Я в основном хожу по деревьям. По мере добавления условий я просто меняю корень вызова #find. Когда я закончу оценивать условия, я вызываю последний метод #find / #first / #all, и все готово.

Это также работает, если у вас есть несколько именованных областей:

class UsersController < ApplicationController
  def index
    root = Org.find(params[:org_id]) if params[:org_id]
    root = User if root.nil?
    root = root.named(params[:name]) if params[:name]
    root = root.registered_after(params[:registered_at]) if params[:registered_at]
    # more conditions, as required
    @users = root.all(:conditions => {...}, :order => "...")
  end
end
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...