Before_filter question

If one places a before_filter in class ApplicationController, when is
the before filter called and for which methods.

I believe it gets called before any “action” … but how does rails know
that the method is an action?

Ralph S. wrote:

If one places a before_filter in class ApplicationController, when is
the before filter called and for which methods.

Does
http://www.railsapi.com/doc/rails-v2.3.8/classes/ActionController/Filters/ClassMethods.html
answer your question?

I believe it gets called before any “action” … but how does rails know
that the method is an action?

All (public) controller methods are in principle actions in Rails. If
you have ones that aren’t, get them out of the controller or make them
private.

Best,

Marnen Laibow-Koser
http://www.marnen.org
[email protected]

On Jul 6, 3:10 pm, Ralph S. [email protected] wrote:

If one places a before_filter in class ApplicationController, when is
the before filter called and for which methods.

I believe it gets called before any “action” … but how does rails know
that the method is an action?

Posted viahttp://www.ruby-forum.com/.

Hi Ralph,

Good question. Methods in controllers are considered actions only if
they’re connected to a url. Urls are connected to controller methods
by using routes. The routes.rb file lists all of the routes that will
connect urls to controllers and actions.

In your routes, when you use map.connect (in Rails 1.x, 2.x) you
directly connect a url to an action method. In Rails 3.0, this is
done with match() instead of connect, but the idea is the same.

If you use map.resources then you’re connecting a whole slew of urls
to a certain actions in your controller. Check the docs for details,
but this is the “restful” style of URL handling, and means that these
methods in your controller will become actions:

index
new
create
edit
update
show
destroy

Finally, be warned that in Rails 1.x and 2.x, when you generate a new
Rails app, by default a pattern-match connector is written for you,
exposing ALL of your methods as actions, which is probably not what
you want. You should remove or comment those out.

Jeff

purpleworkshops.com

Jeff C. wrote:
[…]

Good question. Methods in controllers are considered actions only if
they’re connected to a url.

That’s not true at all. For example, if you have

class PlaysController < ApplicationController
def write_shakespeare

end
end

then (unless I’m badly mistaken) you can get to the write_shakespeare
method by (say) calling

redirect_to :controller => ‘plays’, :action => ‘write_shakespeare’

regardless of what’s in your routes file. There may not be a direct URL
to that action, but that doesn’t prevent it from being an action.

Best,

Marnen Laibow-Koser
http://www.marnen.org
[email protected]

On 6 July 2010 21:38, Marnen Laibow-Koser [email protected] wrote:

end
end

then (unless I’m badly mistaken) you can get to the write_shakespeare
method by (say) calling

redirect_to :controller => ‘plays’, :action => ‘write_shakespeare’

regardless of what’s in your routes file. There may not be a direct URL
to that action, but that doesn’t prevent it from being an action.

In fact would it be true to say that no method of a controller is
inherently an action or not an action? An action is a verb not a noun
so it is not correct to say that a method is or is not an action. An
action (initiated via a url or redirect_to for example) results in
calling a method of a controller and it is under these circumstances
that the filters are called. Calling a method directly from code will
not result in filters being called.

Colin

Ralph S. wrote:
[…]

Here’s another question:
Is the before_filter ever called before methods in
ApplicationController?

Yes. (Try it and find out!) Most authentication libraries work this
way. Doesn’t Devise?

Best,
–Â
Marnen Laibow-Koser
http://www.marnen.org
[email protected]

Sent from my iPhone

Marnen Laibow-Koser wrote:

Ralph S. wrote:

If one places a before_filter in class ApplicationController, when is
the before filter called and for which methods.

Does
http://www.railsapi.com/doc/rails-v2.3.8/classes/ActionController/Filters/ClassMethods.html
answer your question?

It certainly helps but it did not address my question directly.

Here’s another question:
Is the before_filter ever called before methods in
ApplicationController?

Colin L. wrote:

On 6 July 2010 21:38, Marnen Laibow-Koser [email protected] wrote:

�end
end

then (unless I’m badly mistaken) you can get to the write_shakespeare
method by (say) calling

redirect_to :controller => ‘plays’, :action => ‘write_shakespeare’

regardless of what’s in your routes file. �There may not be a direct URL
to that action, but that doesn’t prevent it from being an action.

In fact would it be true to say that no method of a controller is
inherently an action or not an action?

No. In Rails, every public controller method is, by definition, an
action. Period. That’s all.

Marnen Laibow-Koser wrote:

Ralph S. wrote:
[…]

Here’s another question:
Is the before_filter ever called before methods in
ApplicationController?

Yes. (Try it and find out!) Most authentication libraries work this
way. Doesn’t Devise?

Best,
–Â
Marnen Laibow-Koser
http://www.marnen.org
[email protected]

Sent from my iPhone

What prevents infinite recursion?


class ApplicationController < ActionController::Base
before_filter :fetch_logged_user
before_filter :authenticate, :except => :login

Filters added to this controller apply to all controllers in the

application.

Likewise, all the methods added will be available for all controllers.

class ApplicationController < ActionController::Base
before_filter :fetch_logged_user
before_filter :authenticate, :except => :login

helper :all # include all helpers, all the time
protect_from_forgery

def fetch_logged_user
unless session[:user_id].blank?
@logged_user = User.find(session[:user_id])
end

rescue ActiveRecord::RecordNotFound
end

def is_logged_in_user?
!@logged_user.nil?
end

protected
def authenticate
debugger
unless @logged_user
#unauthorized access
redirect_to :controller => :welcome, :status => 401
return false
end
end
end

class ExplanationController < ApplicationController
def whatIsThisGameAbout
x = is_logged_in_user?
debugger
x
end

protected
def authenticate
debugger
x=1
end

end


I am pretty sure that when Rails calls the action whatIsThisGameAbout
that when is_logged_in_user? is invoked that the before_filters are NOT
invoked again before is_logged_in_user? is invoked.

Ralph S. wrote:
[…]

What prevents infinite recursion?

What would cause infinite recursion?


class ApplicationController < ActionController::Base
before_filter :fetch_logged_user
before_filter :authenticate, :except => :login

Filters added to this controller apply to all controllers in the

application.

Likewise, all the methods added will be available for all controllers.

class ApplicationController < ActionController::Base
before_filter :fetch_logged_user
before_filter :authenticate, :except => :login

helper :all # include all helpers, all the time
protect_from_forgery

def fetch_logged_user
unless session[:user_id].blank?
@logged_user = User.find(session[:user_id])
end

rescue ActiveRecord::RecordNotFound
end

def is_logged_in_user?
!@logged_user.nil?
end

protected
def authenticate
debugger
unless @logged_user
#unauthorized access
redirect_to :controller => :welcome, :status => 401
return false
end
end
end

class ExplanationController < ApplicationController
def whatIsThisGameAbout

Hey! Watch the camelCase! That should be what_is_this_game_about .
Actually, it should probably game_info or something.

x = is_logged_in_user?
debugger
x

end

protected
def authenticate
debugger
x=1
end

end


I am pretty sure that when Rails calls the action whatIsThisGameAbout
that when is_logged_in_user? is invoked that the before_filters are NOT
invoked again before is_logged_in_user? is invoked.

You’re quite right. When you do a straight method call, the filter
chain is not invoked – after all, it’s just a straight method call, and
it works just like it does anywhere else in Ruby. It’s only invoked
when you call a controller method as an action – that is, when you go
through the whole Rails stack, as with a Web request or with render
:controller, :action – that the filter chain is invoked.

Best,

Marnen Laibow-Koser
http://www.marnen.org
[email protected]

Marnen Laibow-Koser wrote:

Colin L. wrote:

On 6 July 2010 21:38, Marnen Laibow-Koser [email protected] wrote:

�end
end

then (unless I’m badly mistaken) you can get to the write_shakespeare
method by (say) calling

redirect_to :controller => ‘plays’, :action => ‘write_shakespeare’

regardless of what’s in your routes file. �There may not be a direct URL
to that action, but that doesn’t prevent it from being an action.

In fact would it be true to say that no method of a controller is
inherently an action or not an action?

No. In Rails, every public controller method is, by definition, an
action. Period. That’s all.

OK, I now have to modify my answer. With Ralph’s latest question, I see
what you’re getting at. So, here’s the modified answer:

In Rails, every public controller method can, by definition, behave as
an action – that is, it can be called with suitable use of render
:controller, :action. It can also be called with a regular Ruby-style
method call, in which case it does not behave as an action.

Whether a public controller method behaves as an action depends not on
the method itself but on how it’s called.

That said, if you have a controller method (such as Ralph’s
fetch_logged_user) that is not meant to be called as an action, it is an
extremely good idea to make it non-public (that is, private or
protected) so that it cannot be called as an action accidentally (or
maliciously).

Best,

Marnen Laibow-Koser
http://www.marnen.org
[email protected]

Marnen Laibow-Koser wrote:

That said, if you have a controller method (such as Ralph’s
fetch_logged_user) that is not meant to be called as an action, it is an
extremely good idea to make it non-public (that is, private or
protected) so that it cannot be called as an action accidentally (or
maliciously).

Ok … that sent up alarm bells.

So … how can I prevent Rails from calling, say,
def fetch_logged_user
# black blah blah
end
or
def is_logged_in_user?
!@logged_user.nil?
end
and yet allow all other controllers access to those two functions?

Ralph S. wrote:

 def fetch_logged_user
   # black blah blah
 end

or
def is_logged_in_user?
!@logged_user.nil?
end
and yet allow all other controllers access to those two functions?

As Marnen said, make it private or protected. Like this:

protected
def fetch_logged_user

end

Bob