[Rails] Re: Getting data from the database only once

Ezra Zygmuntowicz
Tue, 25 Jul 2006 19:38:33 -0000

Hi~

On Jul 25, 2006, at 12:31 AM, Daniel N wrote:

>
>
> On 7/25/06, Daniel N <has.sox@gmail.com> wrote:
> Yes I did send that...  Sorry if this is confusing.
>
> What I''m specifically refering to here, is that if a select box,
all
> by itself is fragmet cached, then that select box is set, default
> value and everything.  (at least I think it is, that''s what I was
> asking Ezra)
>
> Form elements are not really good things to cache in my exp, because
> you cannot easily update their values on the server side.  (Excepting
> RJS)
>
> Take this fragment
>
> <%= text_field "user", "name" %>
>
> If this is cached, then on a new form, all well and good, but if that
> form is submitted and returns errors, then the frag cache will blank
> it out, ie return the original frag, a blank text field.
>
> Likewise if just that field were cached and the same form partial were
> used for an edit action, the field would be blank as well even if
> normally it would have something in it.
>
> Also, if the first time the frag is generated it contains data (the
> edit action), then that data will become the default value until the
> frag is expired and regenerated.
>
> At least this is my understanding of how it works.  That''s why in
your
> situation (other post) it''s good to tie it to a user.  Each user
will
> have their own frag generated and stored seperately when a :user =>
> @user.id is included in the cache call.
>
> Things like slabs of non-form markup are good for cacheing.  ie
>
> <%= @user.name -%>
> <%= @user.street -%>
> <%= @user.city -%>
>
> Could all be wrapped up in a frag cache quite nicley.  As I said in my
> other post, make sure to expire it if you change the data.
>
> Also none of these effects will be noticed in development by default.
> Caching is turned off in development.
>
> On 7/25/06, Dan Kohn <dan@dankohn.com> wrote:
> > On Jul 24, 2006, at 11:04 PM, Daniel N wrote:
> >
> > > Would this cause issues if say, different options need to be
> > > selected based on object values or different defaults for
> different
> > > views?
> > >
> > > Wouldn''t a fragment cached version be permenantly
selected on one
> > > option by default?
> >
> > Now I''m confused.  I was so impressed by a trick someone
mentioned
> > this week for fragment caching separately by user that I saved the
> > message.  But the message was from you!
> >
> > > Yes.  When you cache you should use fragment cache. Include in
the
> > > cache call a user id.  the cache method accepts a hash like url
> for
> > > but it can be anything.  You''re not restricted to real
things
> > > (controllers/actions etc).  If you don''t include
somthing to
> > > seperate it by user, each user may get the same cached fragment.
> > >
> > > an eg might be
> > >
> > > <% cache( :controller => ''bill'', :action
=> ''show_last_10'', :user
> > > => current_user.id ) do -%>
> > > <%= all your cached frag -%>
> > > <% end %>
> > >
> > > This will scope the fragment to those parameters, and you can re-
> > > use it elsewhere if you want.  Just include the same url in the
> cache.
> > >
> > > Be sure to expire the fragment if the data changes.
> expire_fragment
> > > ( same_url_hash_used_in_cache_call )
> >
> >         - dan
> > --
> > Dan Kohn <mailto: dan@dankohn.com>
> > <http://www.dankohn.com/>  <tel:+1-415-233-1000>
> >
> >
> >
>
> Looking back at this post it''s potentially more confusing than
what
> it tries to answer :(
>
> I''ll try again.
>
> my understanding of fragment cacheing is that it has a flow in the
> view processing of
>
> When the view comes to a cache( parameters_hash ) in the view
> - if a frag, uniquely identified by parameters_hash is already
> generated
> -- insert pre-generated frag without processing cache block
> -else
> -- process cache block and save the results as a frag cache
> -end
>
> If a cache exists that is identified by parameters_hash then no
> processing is done on the content, it''s just inserted into the
output.
>
> For this reason, it''s not good to cache forms or form fields,
since
> they generally need processing each time they are displayed,
> setting values, highlighting errors etc.
>
> I hope this makes sense.
>


	You are right Dan, I didn''t think about the value of the form field.
You could get around it by using javascript onload to set the correct
value for the select but now we are getting way too complicated ;)

	So you have a few other options i guess. You could put it as a
constant in environment.rb that does the lookup upon startup and
stores it for use anywhere in your app. Now if you do this, keep in
mind that you will get one database query for this data fro meach
mongrel or fcgi proc you run but then they won''t have to hit the db
after this for the data. I had forgotten about the acts_as_enumerated
plugin and I think that is a good option too. Or you could always
write a simple yaml file type of rig. Where the first time your app
demands the code you want to cache you do the query and also write
the yaml file out to disk. You will hide the way this works in a
method in your model so that when its called it will check for the
yaml file on disk and only if its not there will it do the query and
write it out again. Something like this:

class MyModel < AR::Base

   def self.select_contents
      return @select_data if @select_data
      path =  "#{RAILS_ROOT}/tmp/select_contents.yml"
      if File.exist? path
         @select_data = File.open(path) { |f| YAML::load( f ) }
      else
         @select_data = find(:all) # or whatever the query is
          File.open(path, ''w'') { |f| YAML::dump(@select_data,
f ) }
         @select_data
      end
    end

end

	And then if you need to regenerate the select_data you can just
delete the "#{RAILS_ROOT}/tmp/select_contents.yml"  file.

Cheers-
-Ezra

-------------- next part --------------
An HTML attachment was scrubbed...