Fragment caching and not accessing model from view

I am using fragment caching to render a select box where the contents
of the select box comes from a lengthy db query. A simplified example
showing the problem is
<% cache ‘select_box’ do %>
<%= f.collection_select :variety_id, @varieties, :id, :name %>
<% end %>
where @varieties is setup in the controller. Unfortunately this does
not achieve the desired result as the query is run even when the
select is picked up from the cache.

To get the full benefit I have to remove @varieties = Variety.all from
the controller and use
<% cache ‘select_box’ do %>
<%= f.collection_select :variety_id, Variety.all, :id, :name %>
<% end %>
but this breaks the rule that one should not access the model from the
view. Is there a good solution to this problem?

Colin

On 8 Mar 2011, at 16:06, Colin L. [email protected] wrote:

To get the full benefit I have to remove @varieties = Variety.all from
the controller and use
<% cache ‘select_box’ do %>
<%= f.collection_select :variety_id, Variety.all, :id, :name %>
<% end %>
but this breaks the rule that one should not access the model from the
view. Is there a good solution to this problem?

In the controller, you can check for the presence of the cached fragment
using the read_fragment method. Then, only run the database query if the
fragment isn’t cached yet.

Chris

On 8 March 2011 18:22, Chris M. [email protected] wrote:

select is picked up from the cache.

To get the full benefit I have to remove @varieties = Variety.all from
the controller and use
<% cache ‘select_box’ do %>
<%= f.collection_select :variety_id, Variety.all, :id, :name %>
<% end %>
but this breaks the rule that one should not access the model from the
view. Is there a good solution to this problem?

In the controller, you can check for the presence of the cached fragment using
the read_fragment method. Then, only run the database query if the fragment isn’t
cached yet.

That’s a great idea, in fact it is probably
fragment_exists?(‘select_box’) that I want to use. I will give it a
go.

Thanks

Colin

On Wed, Mar 9, 2011 at 12:06 AM, Colin L. [email protected]
wrote:

are you just using .all or a complex query? Because if you’re using a
complex
query and you’re using rails3, then just remove the .all in the complex
query
in the controller so that it won’t run the query. I think it just saves
the
relation to the @varieties variable and won’t run the query until a
method
is
called on the variable such .each or .collect.


You received this message because you are subscribed to the Google G.
“Ruby on Rails: Talk” group.
To post to this group, send email to [email protected].
To unsubscribe from this group, send email to
[email protected].
For more options, visit this group at
http://groups.google.com/group/rubyonrails-talk?hl=en.

On Tue, Mar 8, 2011 at 4:06 PM, Colin L. [email protected]
wrote:

To get the full benefit I have to remove @varieties = Variety.all from
the controller and use
<% cache ‘select_box’ do %>
<%= f.collection_select :variety_id, Variety.all, :id, :name %>
<% end %>
but this breaks the rule that one should not access the model from the
view. Is there a good solution to this problem?

Yes, you are right. One should not access the model from the view.

Create a method in the model, say

       def self.your_method_name
           your_query
       end

and then you can access the model in your view, using the method you
just
defined in the model.

On 9 March 2011 09:19, Jatin kumar [email protected] wrote:

and then you can access the model in your view, using the method you just
defined in the model.

I don’t see how:

<%= f.collection_select :variety_id, Variety.all, :id, :name %>

is different from :

<%= f.collection_select :variety_id, Variety.your_method_name, :id,
:name %>

?:-/

If you say in one breath “don’t access models from the view” and then
in the next create a model class method… how’s that different from
using the “.all” class method?

(btw I agree that one shouldn’t access the model from the view - I’m
just querying that your suggestion may not remove this MVC-breaking
practice in this instance)

On Mar 8, 4:06pm, Colin L. [email protected] wrote:

I am using fragment caching to render a select box where the contents
of the select box comes from a lengthy db query. A simplified example
showing the problem is
<% cache ‘select_box’ do %>
<%= f.collection_select :variety_id, @varieties, :id, :name %>
<% end %>
where @varieties is setup in the controller. Unfortunately this does
not achieve the desired result as the query is run even when the
select is picked up from the cache.

One take on this was interlock ( https://github.com/fauna/interlock )
although i haven’t used it personally (and looks like it hasn’t been
touched in a while)

Fred

On 9 March 2011 00:37, Jim Ruther N. [email protected] wrote:

where @varieties is setup in the controller. Unfortunately this does
relation to the @varieties variable and won’t run the query until a method
is
called on the variable such .each or .collect.

I had noticed that some queries don’t get run till the collection is
used, whereas others seem to run immediately. I did not find
documented exactly how to tell in advance which will get run and which
won’t. I wonder whether using a named scope would guarantee delayed
operation.

Colin

On Mar 9, 11:25am, Colin L. [email protected] wrote:

I had noticed that some queries don’t get run till the collection is
used, whereas others seem to run immediately. I did not find
documented exactly how to tell in advance which will get run and which
won’t. I wonder whether using a named scope would guarantee delayed
operation.

(named) scopes are lazily evaluated.

Fred

On 8 March 2011 20:04, Colin L. [email protected] wrote:

not achieve the desired result as the query is run even when the
In the controller, you can check for the presence of the cached fragment using
the read_fragment method. Then, only run the database query if the fragment isn’t
cached yet.

That’s a great idea, in fact it is probably
fragment_exists?(‘select_box’) that I want to use. I will give it a
go.

Just to confirm that, in the controller,

@varieties = Variety.all if !fragment_exist?( 'select_box' )

does the job.

Colin

On 9 March 2011 11:54, Frederick C. [email protected]
wrote:

On Mar 9, 11:25am, Colin L. [email protected] wrote:

I had noticed that some queries don’t get run till the collection is
used, whereas others seem to run immediately. I did not find
documented exactly how to tell in advance which will get run and which
won’t. I wonder whether using a named scope would guarantee delayed
operation.

(named) scopes are lazily evaluated.

OK, I provided a scope
scope :all_varieties
with no parameters.

Then in the controller
@varieties = Variety.all_varieties
and have confirmed that if the fragment is already cached so
@varieties is not used in the view, then the query is not run, so no
need test whether the fragment exists when setting up @varieties.

This is the best solution I think.

Thanks again

Colin

Colin L. wrote in post #986452:

On 9 March 2011 11:54, Frederick C. [email protected]
wrote:

OK, I provided a scope
scope :all_varieties
with no parameters.

Then in the controller
@varieties = Variety.all_varieties
and have confirmed that if the fragment is already cached so
@varieties is not used in the view, then the query is not run, so no
need test whether the fragment exists when setting up @varieties.

This is the best solution I think.

Thanks again

Colin

Ack… obfuscated logic. If you are trying to not make the call when
the cache fragment already exists, then don’t do so.

@varieties = Variety.all unless fragment_exist?( ‘select_box’ )

Don’t squirrel it away behind a scope which does nothing except let you
defer the decision about executing the DB read and depend on a behavior
of AR which is determined when the view is being rendered…

Just a personal opinion. What works for you, works for you.

hi fred,

Ya i can get your point,but in rails we will use scope instead of
named_scope.If i try rake task separately means its working.

On Wed, Mar 9, 2011 at 5:24 PM, Frederick C.
<[email protected]

On Wed, Mar 9, 2011 at 11:08 PM, Ar Chron [email protected] wrote:

Ack… obfuscated logic. If you are trying to not make the call when
the cache fragment already exists, then don’t do so.

@varieties = Variety.all unless fragment_exist?( ‘select_box’ )

Don’t squirrel it away behind a scope which does nothing except let you
defer the decision about executing the DB read and depend on a behavior
of AR which is determined when the view is being rendered…

+1

On 9 March 2011 22:08, Ar Chron [email protected] wrote:

and have confirmed that if the fragment is already cached so
the cache fragment already exists, then don’t do so.
Sorry I am not sure what you are saying is best, are you suggesting I
should use fragment_exist? or I should not?

Colin

hi,
I also have a query how to integrate rake task with cronjobs any idea
how
to use with example.

Anu

On 9 March 2011 11:59, anu priya [email protected] wrote:

hi,
I also have a query how to integrate rake task with cronjobs any idea how
to use with example.

What has that got to do with the subject of this thread (fragment
caching)?