Rails - 流量控制问题,还有更好的方法吗?

时间:2009-02-06 03:52:22

标签: ruby-on-rails ruby

我试图根据角色和“帖子”控制器锁定一些控制器,无论他们是否分配了任何权限。这似乎有效,但我想知道是否有一个干净的方法来处理这个问题。这就是我在应用程序控制器中所拥有的,我称之为前置过滤器......

if controller_name == 'users' || 'accounts'
  unless @current_user.master? || @current_user.power?
    render :template => "layouts/no_content"
  end
elsif controller_name == 'posts'
  unless @current_user.permissions.count > 0
    render :template => "layouts/no_content"
  end
end

提前致谢。

6 个答案:

答案 0 :(得分:7)

您不应该创建一个代码片段来检查控制器名称,以便在application.rb中执行特定操作。您应该在仅在需要它们的控制器中的过滤器之前定义

在ApplicationController中创建2个方法:

private
def require_master_or_power_user
  unless @current_user.master? || @current_user.power?
    render :template => "layouts/no_content"
  end
end

def require_some_permisions
  unless @current_user.permissions.count > 0
    render :template => "layouts/no_content"
  end
end

现在将其添加为您需要的前置过滤器:

class UsersController < ApplicationController
  before_filter :require_master_or_power_user
  ...
end

class AccountsController < ApplicationController
  before_filter :require_master_or_power_user
  ...
end

class PostsController < ApplicationController
  before_filter :require_some_permisions
  ...
end

因此ApplicationController定义了过滤器,但是它是否适用于其他控制器是否实际使用这些过滤器。像ApplicationController这样的超类应该永远不会根据其子类有条件地分支执行。选择何时使用提供的行为是您想要首先进行子类化的原因之一。

从代码可读性的角度来看,它也更加清晰。在查看UsersController时,很明显当你看到一个名为“require_something”之类的过滤器时会发生一些权限。根据您的方法,您无法通过查看用户控制器代码本身来判断这一点。

答案 1 :(得分:1)

我强烈建议您遵守MVC和OOP,并将尽可能多的用户相关逻辑移回用户模型,如下所示:

class User < ActiveRecord::Base

def has_permission?
  true if self.master? || self.power? || (self.permissions.count > 1)
end

然后你可以在application.rb中使用一个过滤器:

protected

def check_template 
  render :template => "layouts/no_content" if current_user.has_permission? == true
end

并使用Squeegy建议的before_filter调用它,在相应的控制器中,或者在application_controller.rb中的站点范围内

before_filter :check_template

如果你决定改变给予人们许可的范围,这种方法显然有点清洁,而且不那么脆弱,你只需要在应用程序范围内进行一次更改。

答案 2 :(得分:0)

我建议您使用ACL系统:http://github.com/ezmobius/acl_system2

答案 3 :(得分:0)

一个简短的小手写DSL。甚至没有检查代码的语法错误,但你会得到图片。在您的应用程序控制器中:

before_filter :handle_requirements

def self.requirement(*controllers, &block)
  @_requirements ||= {}
  @_requirements[controllers] = block
end

def handle_requirements
  return unless @_requirements
  @_requirements.each do |controllers, proc|
    if controllers.include?(controller.controller_name)
      restrict_access unless instance_eval(&block)
    end
  end
end

def restrict_access
  render :template => "layouts/no_content"
end

用法(也在您的应用程序控制器中)

requirement('users', 'accounts') do
  @current_user.master? || @current_user.power?
end

或者,只需使用ACL系统Radar提及。

答案 4 :(得分:0)

值得一看的另一个插件是role requirement,我一直在使用它。我认为他们都可以做大致相同的事情。

答案 5 :(得分:0)

这是RESTful_ACL的插件;我开发的ACL插件/ gem,并且被广泛使用。它让您可以自由地按照自己的意愿设计角色,而且非常透明。