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?
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 Shnelvar 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,
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 Cohen 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 wrote:
Ralph Shnelvar 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?
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 Shnelvar 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,
Colin Law wrote:
Marnen Laibow-Koser wrote:
Ralph Shnelvar 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 marnen@marnen.org
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 Shnelvar 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 wrote:
Colin Law 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 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 Shnelvar wrote:
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?
As Marnen said, make it private or protected. Like this:
protected def fetch_logged_user ... end
Bob