2009-08-24 76 views
6

在我的应用程序中,我有一个“用户”模型。每个用户都可以拥有其在模型“地址”定义了多个(电子邮件)地址:一个控制器,针对普通用户和管理员的不同视图

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),并在使用“如果”的声明风景。
  2. 在地址控制器中使用类似“after_filter”的东西来渲染不同的布局。

如果可以在两种完全不同的布局中显示执行单个控制器的结果(取决于它的操作模式),那么实现该目标的好方法是什么?

在此先感谢 斯特凡

回答

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选项是呃,可选的,并在视图/布局中引用布局。在documentation for render中可以找到渲染调用的其他各种选项。

+0

谢谢。但是,似乎如果我这样做,我会离开“约定优先配置”的路径。我有点担心 - 这是我的第一个Rails应用程序 - 我是否应该已经偏离其他人似乎做的事情? – cite 2009-08-24 15:16:03

+0

好吧,可以说是惯例是为一个动作渲染一个视图,但我可以看到你在看什么。如果你只是寻找不同的布局,那么Staelen的解决方案是一个很好的解决方案。如果你真的想要根据动作中的逻辑渲染不同的视图,那么我不确定它是否足够接近基本约定,以避免不指定要呈现哪个视图。 – Shadwell 2009-08-24 15:59:23

+0

我想我会尝试使用Staelen的布局解决方案,以及您要为模板渲染的解决方案。再次感谢。 – cite 2009-08-24 16:10:02

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方法。

+0

谢谢,戴夫。 – cite 2009-08-24 15:16:40

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-render2.2.12下查找布局

希望这有助于=)

+0

哦,这是个好主意。非常感谢你! – cite 2009-08-24 15:17:52

2

如果这是你的应用程序的唯一控制器在那里你如果/ else'ing遍布这可能是罚款的地方。如果你开始在任何地方开始这样的逻辑,那么应该告诉你,你一次做得太多了。(!这是罚款和作品)

你接受的答案有不同的布局和不同的看法,对我说,说的控制器做得太多 - 我会分裂这一点到管理控制器。

+0

这个。你是对的。我试图一次做太多事情 - 让所有这些行动在两种操作模式下安然无恙的想法太过耐人寻味。 我写了一个专门的管理控制器。谢谢。 – cite 2009-08-25 13:55:28

0

你应该把在行政命名的行政行为,并限制它。在你的控制器目录中创建一个名为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继承了。

相关问题