before_filter with parameters
Solution 1
I'd do it like this:
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
Where correct_id_here
is the relevant id to access a Project
.
Solution 2
With some syntactic sugar:
before_filter -> { find_campaign params[:id] }, only: [:show, :edit, :update, :destroy]
Or if you decide to get even more fancy:
before_filter ->(param=params[:id]) { find_campaign param }, only: %i|show edit update destroy|
And since Rails 4 before_action
, a synonym to before_filter
, was introduced, so it can be written as:
before_action ->(param=params[:id]) { find_campaign param }, only: %i|show edit update destroy|
NB
->
stands for lambda
, called lambda literal, introduce in Ruby 1.9
%i
will create an array of symbols
Solution 3
To continue @alex' answer, if you want to :except
or :only
some methods, here is the syntax:
before_filter :only => [:edit, :update, :destroy] do |c| c.authenticate_rights params[:id] end
Found here.
Solution 4
I find the block method using curly braces instead of do...end
to be the clearest option
before_action(only: [:show]) { authenticate_rights(id) }
before_action
is just the newer preferred syntax for before_filter
Related videos on Youtube
choise
Updated on May 18, 2020Comments
-
choise almost 4 years
I have a method that does something like this:
before_filter :authenticate_rights, :only => [:show] def authenticate_rights project = Project.find(params[:id]) redirect_to signin_path unless project.hidden end
I also want to use this method in some other Controllers, so i copied the method to a helper that is included in the application_controller.
the problem is, that in some controllers, the id for the project isn't the
:id
symbol but f.e.:project_id
(and also a:id
is present (for another model)How would you solve this problem? is there an option to add a parameter to the before_filter action (to pass the right param)?
-
choise about 13 yearsthe problem is, sometimes both are present (nested) and it finds a project that isn't the right one.
-
choise about 13 yearsis there a way to add a
,:only => [:show]
symbol? i'm getting an error tryingbefore_filter { |c| c.authenticate_rights correct_id_here }, :only => [:show]
-
fguillen over 12 yearsTry the other way around:
before_filter(:only => [:show]) { <block_code_here> }
. More examples here: apidock.com/rails/ActionController/Filters/ClassMethods/… -
Richard Michael about 12 yearsIf you secure this by making the
before_filter
a private method, then perhaps re-factor (e.g. move it to a parent controller, ApplicationController, etc.), you'll need to usec.send(:filter_name, ...)
as the filter will not run in the controller context. guides.rubyonrails.org/… -
oreoshake about 11 yearsDoing this makes it so the before_filter cannot be overridden/skipped due to it's lack of a name (proc). The values I want to pass in are class level. Is that possible?
-
Ola Tuvesson about 11 years@choise: That should not happen: if
project_id
is present theor
clause will ensure this is used - only if aproject_id
is not supplied will theid
param be selected. In other words: when both parameters are supplied, theor
clause ensures the correct value is used, as it will always preferproject_id
. Naturally, you would not want to call this method when neither is present, or when there is noproject_id
but there is anid
which does not reference a project. -
marcus3006 over 10 years@oreoshake: i have the same problem. Did you found a solution?
-
Augustin Riedinger over 10 yearsHow can I do this with a
:only
or a:except
rule, likebefore_filter { |c| c.authenticate_admin! params[:id] }, :only => [:edit, :update, :destroy]
? -
David Pelaez about 10 yearsThis answer is more elegant because the lambda defaults to the execution context of the class, hence private methods can be called without using '.send'
-
David Pelaez about 10 yearsThe fact that passing the block requires using
send
means it's better to use a lambda as suggested in the answer of @vadym-tyemirov -
ahnbizcad over 9 years@Vadym Tyemirov Is
find_campaign
the private method name? Inparam=params[:id]
, isparam
the name of the new local variable that will be passed as an argument tofind_campaign
? Meaning, that within thefind_campaign
private method itself, we useparam
not,params{:id]
? -
Vadym Tyemirov over 9 years
find_campaign
could be either, but I'd make it private to be sure we don't expose what is not consumed.params
is a hash variable available to our methods,param
is any variable that you'd need to pass to find_campaign method, e.g.before_action ->(campaign_id=params[:id]) { find_campaign(campaign_id) }, only: %i| show edit update destroy |
-
ahnbizcad about 9 yearsFYI to beginners:
c
in this case is the controller, and you're calling an instance method you define in this controller.