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

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

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

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

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


person ohdeargod    schedule 07.05.2009    source источник


Ответы (4)


Другой способ сделать это без плагина — использовать 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
person ry.    schedule 07.05.2009
comment
самые чистые решения на сегодняшний день. Благодарю вас! - person ohdeargod; 08.05.2009

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

make_resourceful do
 actions :all
 belongs_to :org
end

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

person Maran    schedule 07.05.2009
comment
Это выглядит действительно полезно, и у него есть решение моей проблемы. Большое спасибо! Я надеюсь, что кто-то может дать ответ, которому не понадобится плагин. - person ohdeargod; 07.05.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
person klew    schedule 07.05.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
person François Beausoleil    schedule 07.05.2009