Hi, I''m wondering if there is a simple solution to call a method once per page request. I tried to place my call in a before_filter in ApplicationController but it''d called a second time if I use render_component from a view. Seems to me that a hook should be added in Dispatcher#prepare_application. Context: working on i18n, I''m trying to check lang either from uri, or session, or against default lang or browser prefs. This is close to routing, but I''d prefer not to interfere with routing, would be simpler. -- Jean-Christophe Michel
* Jean-Christophe Michel (jc.michel@symetrie.com) [051230 17:33]:> I''m wondering if there is a simple solution to call a method once per > page request. > > I tried to place my call in a before_filter in ApplicationController but > it''d called a second time if I use render_component from a view. > Seems to me that a hook should be added in Dispatcher#prepare_application.Seems like a before_filter should be sufficient, simply def my_method return true if @@my_method_called @@my_method_called = true # do something end Perhaps if this is a common idiom, there''s a call for a :once modifier to before_filter / after_filter (which would do essentially the above) instead of defining a new hook? Rick -- http://www.rickbradley.com MUPRN: 850 | could forbid lock()ing random email haiku | readonly packages. Not | sure which was better.
Rick Bradley a écrit :>>I''m wondering if there is a simple solution to call a method once per >>page request. >> > Seems like a before_filter should be sufficient, simply > > def my_method > return true if @@my_method_called > @@my_method_called = true > # do something > endSure it would work. Is it a good practice to use a global for such a problem ? Seems like a smart hack to me ;-) -- Jean-Christophe Michel
On 2-jan-2006, at 10:48, Jean-Christophe Michel wrote:>> def my_method >> return true if @@my_method_called >> @@my_method_called = true >> # do something >> end > > Sure it would work. Is it a good practice to use a global for such a > problem ?@@class_var. -- Regards, Charles.
Jean-Christophe Michel
2006-Jan-12 10:25 UTC
call a method once per page request,confirmed problem
Hi all, My problem is to try to call a method once per page request. (Context: I want to detect the current lang for localization, and this has to be done on each request, so lang passed through uri can have priority over session, browser prefs or default app lang). The way I followed is to have an independant class, Locale, which method init is called through an ApplicationController before_filter. Fine. But when I use a render_component in my layout, to render a menu for instance, a second controller is called, and the negociation for the lang is done once more. To avoid this, I''d like to be sure this method is called only once (it wastes ressources, and more, I need to be sure that the lang is consistent through my components on the same page). Rick Bradley suggested :> Seems like a before_filter should be sufficient, simply > > def my_method > return true if @@my_method_called > @@my_method_called = true > # do something > endRick, your solution is not working, at least here with scgi+apache2 in dev mode. The class vars are not reinited on each request, so once my_method was called, it''s not run any more until the server is restarted. In my case this mean you cannot change the lang :p I just tried with webrick and get the same result. That''s why I concluded that there should be a hook to call some methods once per page request. Digging in core code, I think it could be around Dispatcher#prepare_application in trunk/railties/lib/dispatcher.rb Opinions ? -- Jean-Christophe Michel
Stefan Kaes
2006-Jan-12 10:56 UTC
Re: call a method once per page request, confirmed problem
Jean-Christophe Michel wrote:> Hi all, > > My problem is to try to call a method once per page request. > (Context: I want to detect the current lang for localization, and this > has to be done on each request, so lang passed through uri can have > priority over session, browser prefs or default app lang). > > The way I followed is to have an independant class, Locale, which method > init is called through an ApplicationController before_filter. > Fine. > > But when I use a render_component in my layout, to render a menu for > instance, a second controller is called, and the negociation for the > lang is done once more. To avoid this, I''d like to be sure this method > is called only once (it wastes ressources, and more, I need to be sure > that the lang is consistent through my components on the same page). > > Rick Bradley suggested : > >> Seems like a before_filter should be sufficient, simply >> >> def my_method >> return true if @@my_method_called >> @@my_method_called = true >> # do something >> end >> > > Rick, your solution is not working, at least here with scgi+apache2 in > dev mode. The class vars are not reinited on each request, so once > my_method was called, it''s not run any more until the server is > restarted. In my case this mean you cannot change the lang :p > I just tried with webrick and get the same result. > > > That''s why I concluded that there should be a hook to call some methods > once per page request. Digging in core code, I think it could be around > Dispatcher#prepare_application > in trunk/railties/lib/dispatcher.rb > > Opinions ? >I suggest to place language information on the request object. Add an attr_accessor to class AbstractRequest class ActionController::AbstractRequest attr_accessor :language end and set this in your controller class ApplicationController < ActionController::Base def language request.language ||= your_expensive_language_computation end helper_method :language end Another option would be to install a filter that sets language on the request object and store it in @language on the controller for direct access. From there it will be propagated to your views automatically. class ApplicationController < ActionController::Base before_filter :set_language private def set_language @language = (request.language ||= your_expensive_language_computation) end end and use @language directly (similar to the method described in http://railsexpress.de/blog/articles/2005/11/18/components-may-not-be-evil-but-they-sure-can-be-slow) -- stefan -- For rails performance tuning, see: http://railsexpress.de/blog Subscription: http://railsexpress.de/blog/xml/rss20/feed.xml
Trevor Squires
2006-Jan-12 15:40 UTC
Re: call a method once per page request, confirmed problem
On 12-Jan-06, at 2:56 AM, Stefan Kaes wrote:> I suggest to place language information on the request object. Add > an attr_accessor to class AbstractRequest > > class ActionController::AbstractRequest > attr_accessor :language > endMy preference has always been to add an "attributes" method to the request. It saves having to go back and define accessors for every ''expensive'' item being tracked. in vendor/plugins/request_attributes/init.rb ActionController::AbstractRequest.class_eval do def attributes @request_attributes ||= Hash.new() end end Regards, Trevor -- Trevor Squires http://somethinglearned.com