what is the best way to cache database data that doesn''t change? I was caching it in a constant that I set in a file in config/initializers/ . More concretely, I have a file config/initializers/db_cache_constants.rb that contains the following line: CATEGORIES = Category.find :all But I have 2 problems: - If I do a rake db:drop, then rake db:create doesn''t work because it tries to run that file, and it fails because there''s no database. - when from a template I try to get the number of products of one of the cached categories (a category :has_many products), <% for category in CATEGORIES %> <%= category.name %> (<%= category.products.size %>) <% end %> it works the first time, but when I reload the page, a NoMethodError occurs... undefined method ''products'' for #<Category id: 1, name: "category 1"> Why is this happening? Both problems are solved if I move the definition of the constant to the beginning of the app/controllers/application.rb file, just before the definition of the ApplicationController class, but... is there a better place to do this type of caching? Thanks in advance. xavi -- Posted via http://www.ruby-forum.com/. --~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "Ruby on Rails: Talk" group. To post to this group, send email to rubyonrails-talk-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org To unsubscribe from this group, send email to rubyonrails-talk-unsubscribe-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org For more options, visit this group at http://groups.google.com/group/rubyonrails-talk?hl=en -~----------~----~----~----~------~----~------~--~---
Since the definition of a ''class'' in Ruby is actually a method that runs in the context of that class, you can declare the constant on the class. It will already have inherited the :find method from ActiveRecord. class Category CATEGORIES = self.find(:all) ... end Any time you need CATEGORIES after that you simply ''prefix'' it through the class (Category::CATEGORIES). AndyV On Feb 16, 11:59 am, Xavi Caballe <rails-mailing-l...-ARtvInVfO7ksV2N9l4h3zg@public.gmane.org> wrote:> what is the best way to cache database data that doesn''t change? > I was caching it in a constant that I set in a file in > config/initializers/ . More concretely, I have a file > config/initializers/db_cache_constants.rb that contains the following > line: > > CATEGORIES = Category.find :all > > But I have 2 problems: > > - If I do a rake db:drop, then rake db:create doesn''t work because it > tries to run that file, and it fails because there''s no database. > > - when from a template I try to get the number of products of one of the > cached categories (a category :has_many products), > > <% for category in CATEGORIES %> > <%= category.name %> (<%= category.products.size %>) > <% end %> > > it works the first time, but when I reload the page, a NoMethodError > occurs... > undefined method ''products'' for #<Category id: 1, name: "category 1"> > > Why is this happening? > > Both problems are solved if I move the definition of the constant to the > beginning of the app/controllers/application.rb file, just before the > definition of the ApplicationController class, but... > > is there a better place to do this type of caching? > > Thanks in advance. > > xavi > -- > Posted viahttp://www.ruby-forum.com/.--~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "Ruby on Rails: Talk" group. To post to this group, send email to rubyonrails-talk-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org To unsubscribe from this group, send email to rubyonrails-talk-unsubscribe-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org For more options, visit this group at http://groups.google.com/group/rubyonrails-talk?hl=en -~----------~----~----~----~------~----~------~--~---
Thanks for your answer, but... I tried defining the constant in the Category class like you said, but then for some reason caching doesn''t work: each time I reload the page that loops through the Category::CATEGORIES array I can see in the logs that the database is hit. Category Load (0.000365) SELECT * FROM `categories` Category Columns (0.002079) SHOW FIELDS FROM `categories` The app is running in the development environment. xavi -- Posted via http://www.ruby-forum.com/. --~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "Ruby on Rails: Talk" group. To post to this group, send email to rubyonrails-talk-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org To unsubscribe from this group, send email to rubyonrails-talk-unsubscribe-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org For more options, visit this group at http://groups.google.com/group/rubyonrails-talk?hl=en -~----------~----~----~----~------~----~------~--~---
have you tried running in production mode? in development mode all your models are reloaded with each request, so it will of course reload the categories. See what happens in production. On Feb 18, 10:25 am, Xavi Caballe <rails-mailing-l...-ARtvInVfO7ksV2N9l4h3zg@public.gmane.org> wrote:> Thanks for your answer, but... > I tried defining the constant in the Category class like you said, but > then for some reason caching doesn''t work: each time I reload the page > that loops through the Category::CATEGORIES array I can see in the logs > that the database is hit. > > Category Load (0.000365) SELECT * FROM `categories` > Category Columns (0.002079) SHOW FIELDS FROM `categories` > > The app is running in the development environment. > > xavi > -- > Posted viahttp://www.ruby-forum.com/.--~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "Ruby on Rails: Talk" group. To post to this group, send email to rubyonrails-talk-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org To unsubscribe from this group, send email to rubyonrails-talk-unsubscribe-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org For more options, visit this group at http://groups.google.com/group/rubyonrails-talk?hl=en -~----------~----~----~----~------~----~------~--~---
On 16 Feb 2008, at 16:59, Xavi Caballe wrote:> > > what is the best way to cache database data that doesn''t change? > I was caching it in a constant that I set in a file in > config/initializers/ . More concretely, I have a file > config/initializers/db_cache_constants.rb that contains the following > line: > > CATEGORIES = Category.find :all > > But I have 2 problems: > > - If I do a rake db:drop, then rake db:create doesn''t work because it > tries to run that file, and it fails because there''s no database. > > - when from a template I try to get the number of products of one of > the > cached categories (a category :has_many products), > > <% for category in CATEGORIES %> > <%= category.name %> (<%= category.products.size %>) > <% end %> > > it works the first time, but when I reload the page, a NoMethodError > occurs... > undefined method ''products'' for #<Category id: 1, name: "category 1"> > > > Why is this happening?My hunch is that this is because of class reloading in development mode: after the first request, rails will unload all of your models (so that changes you make take effect immediately). It will basically remove all the methods, constants etc... from for example the Category model. Via your CATEGORIES constant you are still holding onto instances of that old class, that no longer has any methods. You could get round this if it was defined in your category.rb file Personally I''d probably have a Category.all_categories method which would return cached data Fred> > > Both problems are solved if I move the definition of the constant to > the > beginning of the app/controllers/application.rb file, just before the > definition of the ApplicationController class, but... > > is there a better place to do this type of caching? > > Thanks in advance. > > xavi > -- > Posted via http://www.ruby-forum.com/. > > >--~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "Ruby on Rails: Talk" group. To post to this group, send email to rubyonrails-talk-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org To unsubscribe from this group, send email to rubyonrails-talk-unsubscribe-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org For more options, visit this group at http://groups.google.com/group/rubyonrails-talk?hl=en -~----------~----~----~----~------~----~------~--~---
Thank you all for your answers. I changed the config.cache_classes option to true in the development environment (it''s set to false by default) and now the cache works, so you''re right that the cache didn''t work because of the default class reloading in development mode. Fred, using a Category.all_categories method, how would you store the cached data? in a class variable? in a constant? Thanks again. xavi Frederick Cheung wrote:> On 16 Feb 2008, at 16:59, Xavi Caballe wrote: > >> But I have 2 problems: >> <% end %> >> >> it works the first time, but when I reload the page, a NoMethodError >> occurs... >> undefined method ''products'' for #<Category id: 1, name: "category 1"> >> >> >> Why is this happening? > > My hunch is that this is because of class reloading in development > mode: after the first request, rails will unload all of your models > (so that changes you make take effect immediately). It will basically > remove all the methods, constants etc... from for example the Category > model. Via your CATEGORIES constant you are still holding onto > instances of that old class, that no longer has any methods. You could > get round this if it was defined in your category.rb file > > Personally I''d probably have a Category.all_categories method which > would return cached data > > Fred-- Posted via http://www.ruby-forum.com/. --~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "Ruby on Rails: Talk" group. To post to this group, send email to rubyonrails-talk-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org To unsubscribe from this group, send email to rubyonrails-talk-unsubscribe-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org For more options, visit this group at http://groups.google.com/group/rubyonrails-talk?hl=en -~----------~----~----~----~------~----~------~--~---
On Feb 18, 2008, at 16:27 , Xavi Caballe wrote:> I changed the config.cache_classes option to true in the development > environment (it''s set to false by default) and now the cache works, so > you''re right that the cache didn''t work because of the default class > reloading in development mode. > > Fred, using a Category.all_categories method, how would you store the > cached data? in a class variable? in a constant?(Salut! :-) Just in case you are waiting for this, an idiom I normally use something like: def self.all_categories @@all_categories ||= find(:all, :order => ''name ASC'') end So, you always use the class method in client code, and the method caches the result in a class variable via de ||= trick. Written this way category loading is delayed until needed (just a remark, it does not imply it is better). -- fxn --~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "Ruby on Rails: Talk" group. To post to this group, send email to rubyonrails-talk-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org To unsubscribe from this group, send email to rubyonrails-talk-unsubscribe-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org For more options, visit this group at http://groups.google.com/group/rubyonrails-talk?hl=en -~----------~----~----~----~------~----~------~--~---
On 18 Feb 2008, at 15:27, Xavi Caballe wrote:> > Thank you all for your answers. > > I changed the config.cache_classes option to true in the development > environment (it''s set to false by default) and now the cache works, so > you''re right that the cache didn''t work because of the default class > reloading in development mode. > > Fred, using a Category.all_categories method, how would you store the > cached data? in a class variable? in a constant? >I would do what Xavier said.> Thanks again. > > xavi > > Frederick Cheung wrote: >> On 16 Feb 2008, at 16:59, Xavi Caballe wrote: >> >>> But I have 2 problems: >>> <% end %> >>> >>> it works the first time, but when I reload the page, a NoMethodError >>> occurs... >>> undefined method ''products'' for #<Category id: 1, name: "category >>> 1"> >>> >>> >>> Why is this happening? >> >> My hunch is that this is because of class reloading in development >> mode: after the first request, rails will unload all of your models >> (so that changes you make take effect immediately). It will basically >> remove all the methods, constants etc... from for example the >> Category >> model. Via your CATEGORIES constant you are still holding onto >> instances of that old class, that no longer has any methods. You >> could >> get round this if it was defined in your category.rb file >> >> Personally I''d probably have a Category.all_categories method which >> would return cached data >> >> Fred > > -- > Posted via http://www.ruby-forum.com/. > > --~--~---------~--~----~------------~-------~--~----~ > You received this message because you are subscribed to the Google > Groups "Ruby on Rails: Talk" group. > To post to this group, send email to rubyonrails-talk-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org > To unsubscribe from this group, send email to rubyonrails-talk-unsubscribe-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org > For more options, visit this group at http://groups.google.com/group/rubyonrails-talk?hl=en > -~----------~----~----~----~------~----~------~--~--- >