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

发布于 2024-08-02 06:37:21 字数 786 浏览 8 评论 0原文

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

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

如果可以根据操作模式以两种完全不同的布局显示执行单个控制器的结果,那么实现这一目标的好方法是什么?

提前致谢 斯特凡

in my application, I have a "User" model. Each user can have multiple (email) addresses which are defined in the model "Address":

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

Inside the AddressController class, the currently logged in user is available in the "@user" instance variable. The controller prevents ordinary users from editing, deleting, viewing etc. addresses which don't belong to them - but he does allow an administrative user to edit those. The AddressController class can ask the AddressModel if the user currently logged in is performing normal or superuser operations.

This all works nicely and database updates are made as expected, however, I'd really like to have different HTML views depending on the mode of operation. I can only think of two ways to achieve that:

  1. Make the mode of operation (normal/privileged) known in the AddressController class (using an instance variable, e.g. @privileged) and use an "if" statement in the view.
  2. Use something like an "after_filter" in the address controller to render a different layout.

If it is possible to display the results of executing a single controller in two completely different layouts, depending on it's mode of operation, what is a good way to achieve that?

Thanks in advance
Stefan

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

陈甜 2024-08-09 06:37:21

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

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

这将根据 is_authorized 返回的值呈现 admin_action.html.erbnon_admin_action.html.erb:layout 选项是,呃,可选的,引用视图/布局中的布局。您可以在渲染文档。

You can specify which view to use to display the result of an action in the action itself. You can also specify which layout to use too. So, for example:

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

This will render either admin_action.html.erb or non_admin_action.html.erb depending on the returned value from is_authorised. The :layout option is, er, optional and refers a layout in views/layouts. There are various other options the render call which you can find in the documentation for render.

诗笺 2024-08-09 06:37:21

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

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 查找布局

希望这有帮助 = )

You can specify the layout of the view for that particular controller, or the whole application in the application controller by:

class SomeController < ApplicationController
  layout :set_layout

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

  ...
end

You can try to figure it out here: http://guides.rubyonrails.org/layouts_and_rendering.html#using-render, under 2.2.12 Finding Layouts

Hope this helps =)

回首观望 2024-08-09 06:37:21

您只需在控制器末尾手动调用 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 方法提供显式模板文件。

You can simply call the render method manually at the end of your controller action:

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

This will render app/views/myview/show_privileged.html.erb or app/views/myview/show.html.erb. Alternatively, you can use the :template option to give an explicit template file to the render method.

会傲 2024-08-09 06:37:21

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

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

If this is the only controller in your app where you're if/else'ing all over the place that's probably fine. If you start doing this type of logic everywhere that should tell you that you're doing too much at once.

The answer you accepted (which is fine and works!) has a different layout and a different view, to me that says the controller is doing too much - I'd split this out into an admin controller.

樱桃奶球 2024-08-09 06:37:21

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

You should put administrative actions in an an administrative namespace and restrict it there. Create a directory called admin in your controllers directory and add an _application_controller.rb_ in there:

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

Now you can put controllers into this namespace and make them inherit from Admin::ApplicationController too.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文