带有参数的before_filter


84

我有一种方法可以执行以下操作:

before_filter :authenticate_rights, :only => [:show]

def authenticate_rights
  project = Project.find(params[:id])
  redirect_to signin_path unless project.hidden
end

我也想在其他一些Controller中使用此方法,因此我将该方法复制到了application_controller中包含的帮助器中。

问题是,在某些控制器中,项目的ID不是:id符号,而是fe :project_id(也:id存在fe (对于另一个模型)

您将如何解决这个问题?是否有一个选项可以向before_filter操作添加参数(以传递正确的参数)?

Answers:


86

我会这样:

before_filter { |c| c.authenticate_rights correct_id_here }

def authenticate_rights(project_id)
  project = Project.find(project_id)
  redirect_to signin_path unless project.hidden
end

correct_id_here访问的相关ID在哪里Project


2
有没有添加,:only => [:show]符号的方法?我在尝试时遇到错误before_filter { |c| c.authenticate_rights correct_id_here }, :only => [:show]
选择

27
尝试另一种方法:before_filter(:only => [:show]) { <block_code_here> }。更多的例子在这里:apidock.com/rails/ActionController/Filters/ClassMethods/...
fguillen

1
如果通过before_filter将其设为私有方法来保护此方法,然后可能进行重构(例如将其移至父控制器,ApplicationController等),则需要使用c.send(:filter_name, ...)该过滤器,因为过滤器不会在控制器上下文中运行。 guides.rubyonrails.org/…–
理查德·迈克尔

2
这样做可以使before_filter由于缺少名称(proc)而不能被覆盖/跳过。我要传递的值是类级别的。那可能吗?
oreoshake

1
@ore​​oshake:我有同样的问题。您找到解决方案了吗?
marcus3006 2013年

67

用一些语法糖:

before_filter -> { find_campaign params[:id] }, only: [:show, :edit, :update, :destroy]

或者,如果您决定变得更加幻想:

before_filter ->(param=params[:id]) { find_campaign param }, only: %i|show edit update destroy|

而且由于引入before_action了Rails 4 (与的同义词)的关系before_filter,因此可以这样写:

before_action ->(param=params[:id]) { find_campaign param }, only: %i|show edit update destroy|

NB

->代表lambda,被称为拉姆达文字,介绍Ruby 1.9的

%i 将创建一个符号数组


5
这个答案是更优雅,因为拉姆达默认为类的执行上下文,因此私有方法可以称为不使用“发送”
大卫·佩莱斯

@Vadym Tyemirovfind_campaign私有方法名称吗?在中param=params[:id],是param将作为参数传递给的新局部变量的名称find_campaign吗?意思是,在find_campaign私有方法本身中,我们param不使用params{:id]
ahnbizcad 2014年

1
find_campaign可能是两者之一,但我将其设为私有,以确保我们不暴露未消费的东西。params是可用于我们的方法的哈希变量,param是您需要传递给find_campaign方法的任何变量,例如before_action ->(campaign_id=params[:id]) { find_campaign(campaign_id) }, only: %i| show edit update destroy |
Vadym Tyemirov

14

要继续@alex的回答,如果你想:except:only一些方法,这里是语法:

before_filter :only => [:edit, :update, :destroy] do |c| c.authenticate_rights params[:id] end 

这里找到。


5

我发现使用花括号而不是do...end最清楚的选择的块方法

before_action(only: [:show]) { authenticate_rights(id) }

before_action 只是更新的首选语法 before_filter


-1

这应该工作:

project = Project.find(params[:project_id] || params[:id])

params[:project_id]如果它在params哈希中存在,则应返回;否则,则应返回params[:id]


问题是,有时两者同时存在(嵌套),并且找到了不合适的项目。
选择

@choise:这不应该发生:如果project_id存在,该or子句将确保使用它-仅当project_id未提供a时,id才会选择该参数。换句话说:当同时提供两个参数时,该or子句将确保始终使用正确的值project_id。自然地,当两者都不存在或不存在project_idid没有引用项目的项目时,您将不想调用此方法。
奥拉·图维森
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.