Rails способ визуализации различных действий и представлений на основе типа пользователя?

У меня есть несколько разных типов пользователей (покупателей, продавцов, администраторов).

Я хочу, чтобы все они имели один и тот же URL-адрес account_path, но использовали другое действие и представление.

Я пытаюсь что-то вроде этого...

class AccountsController < ApplicationController
 before_filter :render_by_user, :only => [:show]
 def show
 # see *_show below
 end
 def admin_show
 ...
 end
 def buyer_show
 ...
 end
 def client_show
 ...
 end
end

Вот как я определил render_by_user в ApplicationController...

def render_by_user
 action = "#{current_user.class.to_s.downcase}_#{action_name}"
 if self.respond_to?(action) 
 instance_variable_set("@#{current_user.class.to_s.downcase}", current_user) # e.g. set @model to current_user
 self.send(action)
 else
 flash[:error] ||= "You're not authorized to do that."
 redirect_to root_path
 end
 end

Он вызывает правильный * _show метод в контроллере. Но по-прежнему пытается отобразить "show.html.erb" и не ищет правильный шаблон, который у меня там есть, "admin_show.html.erb" "buyer_show.html.erb" и т.д.

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

Или кто-нибудь еще видел плагин или более элегантный способ разбить действия и представления по типу пользователя? Спасибо!

Btw, я использую Rails 3 (в случае, если это имеет значение).

1 ответ

В зависимости от того, насколько различны шаблоны представлений, может быть полезно переместить часть этой логики в шаблон show и переключиться туда:

<% if current_user.is_a? Admin %>
<h1> Show Admin Stuff! </h1>
<% end %>

Но чтобы ответить на ваш вопрос, вам нужно указать, какой шаблон отображать. Это должно работать, если вы настроили контроллер @action_name. Вы можете сделать это в своем методе render_by_user вместо локальной переменной action:

def render_by_user
 self.action_name = "#{current_user.class.to_s.downcase}_#{self.action_name}"
 if self.respond_to?(self.action_name) 
 instance_variable_set("@#{current_user.class.to_s.downcase}", current_user) # e.g. set @model to current_user
 self.send(self.action_name)
 else
 flash[:error] ||= "You're not authorized to do that."
 redirect_to root_path
 end
end

licensed under cc by-sa 3.0 with attribution.