Rails 如何根据用户类型呈现不同的操作和视图?

Bri*_*ong 4 ruby-on-rails ruby-on-rails-3

我有几种不同的用户类型(买家、卖家、管理员)。

我希望它们都具有相同的 account_path URL,但使用不同的操作和视图。

我正在尝试这样的事情......

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
Run Code Online (Sandbox Code Playgroud)

这就是我在 ApplicationController 中定义 render_by_user 的方式...

  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
Run Code Online (Sandbox Code Playgroud)

它在控制器中调用正确的 *_show 方法。但仍然尝试渲染“show.html.erb”并且不查找我在那里名为“admin_show.html.erb”“buyer_show.html.erb”等的正确模板。

我知道我可以手动调用render "admin_show"每个操作,但我认为可能有一种更干净的方法可以在之前的过滤器中完成这一切。

或者有其他人看到过插件或更优雅的方式来按用户类型分解操作和视图吗?谢谢!

顺便说一句,我正在使用 Rails 3(以防有所不同)。

And*_*Vit 5

根据视图模板的不同程度,将部分逻辑移至模板中show并在其中进行切换可能会有所帮助:

<% if current_user.is_a? Admin %>
<h1> Show Admin Stuff! </h1>
<% end %>
Run Code Online (Sandbox Code Playgroud)

但要回答您的问题,您需要指定要渲染的模板。如果您设置了控制器的@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
Run Code Online (Sandbox Code Playgroud)