一个控制器,普通用户和管理员的不同视图

时间:2009-08-24 12:47:10

标签: ruby-on-rails actionview actioncontroller

在我的应用程序中,我有一个“用户”模型。每个用户可以拥有多个(电子邮件)地址,这些地址在“地址”模型中定义:

Class User < ActiveRecord::Base
  has_many :addresses


  def is_authorized(op)
     # returns true or false
  end

  def is_owned_by(user)
     # returns true or false
  end
end

Class Address < ActiveRecord::Base
  belongs_to :user
end

在AddressController类中,当前登录的用户在“@user”实例变量中可用。控制器阻止普通用户编辑,删除,查看等不属于他们的地址 - 但他允许管理用户编辑这些地址。如果当前登录的用户正在执行正常或超级用户操作,则AddressController类可以询问AddressModel。

这一切都运行良好,数据库更新按预期进行,但是,我真的希望根据操作模式使用不同的HTML视图。我只能想到两种方法来实现这一目标:

  1. 在AddressController类中使用已知的操作模式(正常/特权)(使用实例变量,例如@privileged)并在视图中使用“if”语句。
  2. 在地址控制器中使用类似“after_filter”的内容来呈现不同的布局。
  3. 如果可以在两个完全不同的布局中显示执行单个控制器的结果,取决于它的操作模式,有什么好的方法来实现它?

    提前致谢 斯蒂芬

5 个答案:

答案 0 :(得分:9)

您可以指定用于在操作本身中显示操作结果的视图。您还可以指定要使用的布局。所以,例如:

def my_action
  if @user.is_authorised(...)
    render :action => 'admin_action', :layout => 'admin'
  else
    render :action => 'non_admin_action', :layout => 'non_admin'
  end
end

这将呈现admin_action.html.erbnon_admin_action.html.erb,具体取决于is_authorised的返回值。 :layout选项是,er,是可选的,并且是视图/布局中的布局。您可以在documentation for render中找到渲染调用的各种其他选项。

答案 1 :(得分:6)

您可以通过以下方式为该特定控制器或应用程序控制器中的整个应用程序指定视图的布局:

class SomeController < ApplicationController
  layout :set_layout

  def set_layout
    @user.is_authorized(...) ? "privileged_layout" : "normal_layout"
  end

  ...
end

您可以尝试在此处查明:http://guides.rubyonrails.org/layouts_and_rendering.html#using-render 2.2.12查找布局

希望这有助于=)

答案 2 :(得分:3)

您可以在控制器操作结束时手动调用render方法:

if @privileged
    render :action => 'show_privileged'
else
    render :action => 'show'
end

这将呈现app/views/myview/show_privileged.html.erbapp/views/myview/show.html.erb。或者,您可以使用:template选项为render方法提供显式模板文件。

答案 3 :(得分:2)

如果这是你应用程序中唯一的控制器,那么你可能在其他所有地方都可以正常使用。如果你开始在任何地方开始做这种类型的逻辑,应该告诉你,你一次做得太多了。

你接受的答案(这很好并且有效!)有不同的布局和不同的视图,对我说控制器做得太多了 - 我把它拆分成管理控制器。

答案 4 :(得分:0)

您应该将管理操作放在管理命名空间中并将其限制在那里。在您的controllers目录中创建一个名为admin的目录,并在其中添加一个_application_controller.rb_:

class Admin::ApplicationController < ApplicationController
  before_filter :check_authorized

  private
    def check_authorized?
      if !logged_in? || !current_user.admin?
        flash[:notice] = "You've been very bad. Go away.
        redirect_to root_path
      end
    end
 end

现在您可以将控制器放入此命名空间,并使它们也从Admin::ApplicationController继承。