7

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

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”的东西来呈现不同的布局。

如果可以在两个完全不同的布局中显示执行单个控制器的结果,这取决于它的操作模式,那么有什么好的方法来实现呢?

在此先感谢斯特凡

4

5 回答 5

10

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

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选项是,呃,可选的,指的是视图/布局中的布局。您可以在 render 的文档中找到 render 调用的各种其他选项。

于 2009-08-24T13:08:19.137 回答
7

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

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 Finding Layouts下

希望这会有所帮助=)

于 2009-08-24T14:03:28.700 回答
4

您可以简单地在控制器操作结束时手动调用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选项为渲染方法提供显式模板文件。

于 2009-08-24T13:05:57.047 回答
2

如果这是您的应用程序中唯一的控制器,您可以在整个地方执行 if/else 操作,那可能没问题。如果你开始到处做这种类型的逻辑,那应该会告诉你你一次做的太多了。

您接受的答案(很好并且有效!)具有不同的布局和不同的视图,对我来说说控制器做得太多 - 我会将其拆分为管理控制器。

于 2009-08-24T18:16:09.257 回答
1

您应该将管理操作放在管理名称空间中并将其限制在那里。在您的控制器目录中创建一个名为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

于 2009-08-24T19:18:19.070 回答