如何将参数发送到之前的过滤器?

时间:2009-03-23 23:11:44

标签: ruby-on-rails ruby

我想在我的应用程序控制器中创建一个before_filter方法,就像这样...

def check_role(role_name)
  unless logged_in_user.has_role? role_name
    flash[:notice] = 'Access to that area requires additional privileges.'
    redirect_to :back
  end
end

但是,在过滤器可以获取参数之前,它看起来并不像。

有没有办法参数化此调用,或者我是否想用锤子驱动螺丝?

5 个答案:

答案 0 :(得分:18)

您应该可以使用块来执行此操作:

before_filter {|controller| controller.check_role('admin') }

答案 1 :(得分:4)

您可以使用一些元编程。这样的事情(完全没有经过测试,只是为了让你知道它会如何发展):

Module RoleWithIt
  Role.all.each do |role|
    define_method("check_#{role.name}_role".to_sym) do
      check_role(role.name)
    end
  end

  def check_role(role_name)
    return if logged_in_user.has_role?(role_name)
    flash[:notice] = 'Access to that area requires additional privileges.'
    redirect_to :back
  end
end

ApplicationController.send :include, RoleWithIt

要在应用程序初始化时加载它,只需将其放在名为role_with_it.rb的文件中,并将其放在lib目录中。

答案 2 :(得分:4)

  我正试着用螺丝钉拧螺丝   锤?

呃,可能; - )

如果我正确读取此信息,您可能会遇到控制器中的操作具有不同访问级别的情况,因此您希望通过创建单个检查功能来删除重复项?

所以你想做这样的事情吗?

before_filter :check_role('admin'), :only => [:admin, :debug]
before_filter :check_role('power'), :only => [:edit, :delete]

但是parens中的参数不合法。无论如何,我仍然在这里看到一些重复!

一般情况下,如果您无法做某事,那么功能区域也会像控制器过滤器一样被访问,这可能是因为您正在以错误的方式查看某些内容。 (请记住,Rails很自豪地称自己为“自以为是的软件”!)

如果你能够在过滤方法中知道动作名称,那该怎么办?

然后我们有

before_filter :check_role

哪个很漂亮DRY

我们可以在Hash中定义权限,可能是:

Perms = { :admin => ['admin'], :edit => ['admin', 'power'], etc

......似乎封装了重复的不同元素。如果它变得复杂,那么整个事情可能会移到一个表中,尽管那时你可能会复制插件中已有的功能。

我们有

protected
def check_role
  for required_role in Perms[params[:action]]
    return if logged_in_user.has_role? required_role
  end
  flash[:notice] = 'Access to that area requires additional privileges.'
  redirect_to :back
end

或类似的东西。 params [:action]适用于我当前的Rails版本(2.1.2),虽然Rails书籍(v2)提到了action_name方法,似乎对我来说空白。

答案 3 :(得分:3)

我不相信你可以将参数传递给过滤器。所以我过去做的是做静态方法,将参数传递给需要参数的方法。

所以我会有这样的事情:

def check_role(role_name)
  unless logged_in_user.has_role? role_name
    flash[:notice] = 'Access to that area requires additional privileges.'
    redirect_to :back
  end
end

def check_admin_role
   check_role('admin')
end

def check_blah_role
   check_role('blah')
end

然后在你的控制器中你只需要打电话

before_filter :check_admin_role

可能有一些方法可以通过元编程实现这一点,但我仍然是一个n00b并且尚未想出那个部分;)

答案 4 :(得分:0)

这是一个老问题,但如果有人仍然想知道,可以找到有关rails 4的好答案here