Hi, i just wanted to say my sorries in advance (sorrie/sorry/sorri)...i have just started learning about the subject of caching, but unfortunately haven''t effictively managed to implement what i had learned. obviously it''s possible to cache a whole page, or action with the caches_page :x or caches_action :y methods, but for some reason it hasn''t really worked with what i had been doing. (i was trying to cache Time.now to no avail) either way, the issue at hand (not Time.now) is trying to cache an object that i will usually pull out of the database once per session...say i have a table database.groups and i want to get all of the records out of the table, and keep them in my application, without pulling them out every other action (unless i specify otherwise)... i was hoping there was something as simple as MyController #here caches_action :get_groups def index get_groups end... def another_action get_groups end .. .. private #and here def get_groups @groups = Group.find(:all) end but i can''t get it to work! ..i''m in production mode, with the ActionController::Base.perform_caching = true and it still isn''t working! ...any ideas to what i am doing wrong? oh, and also how do i ''abort'' the caching for ''get_groups'' and overide that in order to look for the groups in a new db-query? (something like expire_get_groups) much thanks in advance, s -- Posted via http://www.ruby-forum.com/.
Wrong kind of caching :) Action, page, and fragment caching are for the views. There isn''t any built-in support for doing database result caching. Building your own isn''t that hard, but first decide if it''s really necessary. If you use page caching correctly, you can dramatically reduce your backend overhead because Rails never gets invoked. Rails makes static pages from your dynamic content and places those in your public folder. Subsequent hits are served from the static pages and Rails doesn''t even notice. (The web server is usually configured to only invoke Rails if the request is a 404 Page Not Found.) If you use fragment caching, you can reduce a lot of database hits for things like dropdown boxes, etc. I know that there are a couple of folks out there experimenting with database result caching. I am not familiar with it because I''ve been content with page and action caching. On 6/28/06, newbie <newbie@newbies.com> wrote:> > Hi, > > i just wanted to say my sorries in advance (sorrie/sorry/sorri)...i have > just started learning about the subject of caching, but unfortunately > haven''t effictively managed to implement what i had learned. > obviously it''s possible to cache a whole page, or action with the > caches_page :x or caches_action :y methods, but for some reason it > hasn''t really worked with what i had been doing. (i was trying to cache > Time.now to no avail) > either way, the issue at hand (not Time.now) is trying to cache an > object that i will usually pull out of the database once per > session...say i have a table database.groups and i want to get all of > the records out of the table, and keep them in my application, without > pulling them out every other action (unless i specify otherwise)... > > i was hoping there was something as simple as > > MyController > #here > caches_action :get_groups > > def index > get_groups > end... > > def another_action > get_groups > end > .. > .. > private > > #and here > def get_groups > @groups = Group.find(:all) > end > > > > but i can''t get it to work! ..i''m in production mode, with the > ActionController::Base.perform_caching = true > and it still isn''t working! ...any ideas to what i am doing wrong? oh, > and also how do i ''abort'' the caching for ''get_groups'' and overide that > in order to look for the groups in a new db-query? (something like > expire_get_groups) > > much thanks in advance, > s > > -- > Posted via http://www.ruby-forum.com/. > _______________________________________________ > Rails mailing list > Rails@lists.rubyonrails.org > http://lists.rubyonrails.org/mailman/listinfo/rails >-------------- next part -------------- An HTML attachment was scrubbed... URL: http://wrath.rubyonrails.org/pipermail/rails/attachments/20060628/daa3c180/attachment.html
Brian Hogan wrote:> Building your own isn''t that hard, but first decide if it''s really > necessary....i was kind of hoping to release the tension off of the db hits seeing that the ''groups'' table will hardly be used, and so it would be unneccerary to look for all of the groups all the time (unless the admin would enter a new group which would happen rarely, and then i would envoke something simillar to expire__...) so where would i start if i wanted to build my own method for this? where do i store it?> If you use fragment caching, you can reduce a lot of database hits for > things like dropdown boxes, etc.and if the fragment caching doesn''t involve db queries, how would i save the time? ...i happen to be fairly new to this subject, so thanks for the patience and time(and at this time i could possibly throw in a general thanks for the reply) s -- Posted via http://www.ruby-forum.com/.
Fragment caching works well for things like select boxes.... say for example you have ''locations'' in your database. When you create a new inventory item, you might specify the location by picking it from a dropdown box. You can build that select box of ''locations'' using fragment caching. The DB gets hit once, the list is built, and then the fragment is used next time instead of the db. You need to expire the fragment when you add, modify, or delete a location. You do that manually, either directly or by using a sweeper. (See Agile Web Development for a good example of sweepers.) As for how to cache your own results, first be sure you''re not doing any premature optimizing. Databases are meant to handle queries. Depending on how often the table is used, you can do tuning on the db side too, such as applying proper indexes. I would write the app first and see how it performs under your expected load. If it performs poorly, then come back and ask for some specific options. If you absolutely feel that you *have* to do this functionality right now, I think that the BackgroundDRB plugin might help you ( http://backgroundrb.rubyforge.org/). On 6/28/06, newbie <newbie@newbies.com> wrote:> > Brian Hogan wrote: > > > Building your own isn''t that hard, but first decide if it''s really > > necessary. > > > > ...i was kind of hoping to release the tension off of the db hits seeing > that the ''groups'' table will hardly be used, and so it would be > unneccerary to look for all of the groups all the time (unless the admin > would enter a new group which would happen rarely, and then i would > envoke something simillar to expire__...) > so where would i start if i wanted to build my own method for this? > where do i store it? > > > > > > If you use fragment caching, you can reduce a lot of database hits for > > things like dropdown boxes, etc. > > > and if the fragment caching doesn''t involve db queries, how would i save > the time? ...i happen to be fairly new to this subject, so thanks for > the patience and time(and at this time i could possibly throw in a > general thanks for the reply) > > > s > > -- > Posted via http://www.ruby-forum.com/. > _______________________________________________ > Rails mailing list > Rails@lists.rubyonrails.org > http://lists.rubyonrails.org/mailman/listinfo/rails >-------------- next part -------------- An HTML attachment was scrubbed... URL: http://wrath.rubyonrails.org/pipermail/rails/attachments/20060628/52d327ab/attachment.html
On Jun 28, 2006, at 10:16 AM, newbie wrote:> Brian Hogan wrote: > >> Building your own isn''t that hard, but first decide if it''s really >> necessary. > > ...i was kind of hoping to release the tension off of the db hits > seeing > that the ''groups'' table will hardly be used, and so it would be > unneccerary to look for all of the groups all the time (unless the > admin > would enter a new group which would happen rarely, and then i would > envoke something simillar to expire__...) > so where would i start if i wanted to build my own method for this? > where do i store it?This is generally done with a class variable. To use your earlier example, write code that looks similar to this: def get_groups @@groups ||= Group.find(:all) end If @@groups isn''t set yet it will execute the Group.find call. If @@groups is set, it just returns itself. If the code looks strange, it is functionally equivalent to: def get_groups if @@groups.nil? @@groups = Group.find(:all) end return @@groups end>> If you use fragment caching, you can reduce a lot of database hits >> for >> things like dropdown boxes, etc. > > > and if the fragment caching doesn''t involve db queries, how would i > save > the time?I haven''t really experimented with fragment caching yet, so I''ll let someone else answer this one... cr
>> Brian Hogan wrote: >> >>> Building your own isn''t that hard, but first decide if it''s really >>> necessary. >> >> ...i was kind of hoping to release the tension off of the db hits seeing >> that the ''groups'' table will hardly be used, and so it would be >> unneccerary to look for all of the groups all the time (unless the admin >> would enter a new group which would happen rarely, and then i would >> envoke something simillar to expire__...) >> so where would i start if i wanted to build my own method for this? >> where do i store it? > > This is generally done with a class variable. To use your earlier example, > write code that looks similar to this: > > def get_groups > @@groups ||= Group.find(:all) > end > > If @@groups isn''t set yet it will execute the Group.find call. If @@groups is > set, it just returns itself. If the code looks strange, it is functionally > equivalent to:Just keep in mind that this is *per* rails process... so if you''re not careful about updating this when the database changes, you could have an instance where from "request to request" you would see different output for @@groups depending on what rails process your request was processed by. -p
newbie wrote:> i was hoping there was something as simple as > > MyController > #here > caches_action :get_groups > > def index > get_groups > end... > > def another_action > get_groups > end > .. > .. > private > > #and here > def get_groups > @groups = Group.find(:all) > endGet rid of caches_action, since that won''t do what you want. Try something more like: #view <% cache do %> <%= #bunch of complicated stuff to build groups page %> <% end %> #controller def get_groups unless read_fragment(params) #uses the url_for helper to read the #cached fragment for this page. @groups = Group.find(:all) end end So the action gets called the first time, read_fragment does not find any cached fragment, so it sets @groups to the DB result. Then, the view kicks in and the cache method doesn''t find the fragment, so it executed the code, and caches the result using the params of whatever page it''s on. The next time the action gets called, read_fragment finds the cached framgent, and skips the db call, and skips assigning the @groups variable. This is fine because as long as all the view data that uses the @groups variable is cached, the object will never be used. Lastly, use "expire_fragment(url_params_for_fragment)" after any controller action that changes the groups table. This way you always have the speed of caching, but as soon as anything changes you wipe the cache and let the next request generate the up to date content. Summary: Use "cache do" or "cache(some_url_params) do" in your view, and check to see if you can read that fragment from your controller before you do any DB calls. Then after any change that would alter what was cached use expire_fragment to clear it. -- Posted via http://www.ruby-forum.com/.
> Lastly, use "expire_fragment(url_params_for_fragment)" after any > controller action that changes the groups table. This way you always > have the speed of caching, but as soon as anything changes you wipe the > cache and let the next request generate the up to date content.Thanks! ...u''v been really helpful. last and may be least question; where do i put the expire_fragment? in a helper? appcontoller? -- Posted via http://www.ruby-forum.com/.