Forum: Ruby on Rails Fragment caching and not accessing model from view

5f94b9b346c2aa648a80bc259978e5bc?d=identicon&s=25 Colin Law (Guest)
on 2011-03-08 17:08
(Received via mailing list)
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
38a91d5029a6e2a12ec7a083234bd7db?d=identicon&s=25 Chris Mear (Guest)
on 2011-03-08 19:24
(Received via mailing list)
On 8 Mar 2011, at 16:06, Colin Law <clanlaw@googlemail.com> 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
5f94b9b346c2aa648a80bc259978e5bc?d=identicon&s=25 Colin Law (Guest)
on 2011-03-08 21:06
(Received via mailing list)
On 8 March 2011 18:22, Chris Mear <chrismear@gmail.com> 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
19fad8b2f5f9948322c3fe0441265298?d=identicon&s=25 Jim ruther Nill (jimboker)
on 2011-03-09 01:38
(Received via mailing list)
On Wed, Mar 9, 2011 at 12:06 AM, Colin Law <clanlaw@googlemail.com>
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 Groups
> "Ruby on Rails: Talk" group.
> To post to this group, send email to rubyonrails-talk@googlegroups.com.
> To unsubscribe from this group, send email to
> rubyonrails-talk+unsubscribe@googlegroups.com.
> For more options, visit this group at
> http://groups.google.com/group/rubyonrails-talk?hl=en.
>
>


--
334ce47b13120799a35dd17914426323?d=identicon&s=25 Jatin Kumar (silver-spoon)
on 2011-03-09 10:21
(Received via mailing list)
On Tue, Mar 8, 2011 at 4:06 PM, Colin Law <clanlaw@googlemail.com>
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.
56b7e1808013614acdb73cbaaa6938a1?d=identicon&s=25 Michael Pavling (Guest)
on 2011-03-09 10:34
(Received via mailing list)
On 9 March 2011 09:19, Jatin kumar <jatinkumar.nitk@gmail.com> 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)
81b61875e41eaa58887543635d556fca?d=identicon&s=25 Frederick Cheung (Guest)
on 2011-03-09 11:28
(Received via mailing list)
On Mar 8, 4:06pm, Colin Law <clan...@googlemail.com> 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
5f94b9b346c2aa648a80bc259978e5bc?d=identicon&s=25 Colin Law (Guest)
on 2011-03-09 12:26
(Received via mailing list)
On 8 March 2011 20:04, Colin Law <clanlaw@googlemail.com> 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
5f94b9b346c2aa648a80bc259978e5bc?d=identicon&s=25 Colin Law (Guest)
on 2011-03-09 12:29
(Received via mailing list)
On 9 March 2011 00:37, Jim Ruther Nill <jvnill@gmail.com> 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
81b61875e41eaa58887543635d556fca?d=identicon&s=25 Frederick Cheung (Guest)
on 2011-03-09 12:55
(Received via mailing list)
On Mar 9, 11:25am, Colin Law <clan...@googlemail.com> 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
5f94b9b346c2aa648a80bc259978e5bc?d=identicon&s=25 Colin Law (Guest)
on 2011-03-09 13:27
(Received via mailing list)
On 9 March 2011 11:54, Frederick Cheung <frederick.cheung@gmail.com>
wrote:
>
>
> On Mar 9, 11:25am, Colin Law <clan...@googlemail.com> 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
D188e591eac11021329b8821a5f954c7?d=identicon&s=25 Ar Chron (railsdog)
on 2011-03-09 23:08
Colin Law wrote in post #986452:
> On 9 March 2011 11:54, Frederick Cheung <frederick.cheung@gmail.com>
> 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.
7223c62b7310e164eb79c740188abbda?d=identicon&s=25 Xavier Noria (fxn)
on 2011-03-09 23:20
(Received via mailing list)
On Wed, Mar 9, 2011 at 11:08 PM, Ar Chron <lists@ruby-forum.com> 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
E4d1624d683b098c254fbc97203c7111?d=identicon&s=25 anu priya (Guest)
on 2011-03-09 23:43
(Received via mailing list)
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 Cheung
<frederick.cheung@gmail.com
E4d1624d683b098c254fbc97203c7111?d=identicon&s=25 anu priya (Guest)
on 2011-03-09 23:43
(Received via mailing list)
hi,
   I also have a query how to integrate rake task with cronjobs any idea
how
to use with example.

Anu
5f94b9b346c2aa648a80bc259978e5bc?d=identicon&s=25 Colin Law (Guest)
on 2011-03-10 08:26
(Received via mailing list)
On 9 March 2011 22:08, Ar Chron <lists@ruby-forum.com> 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
5f94b9b346c2aa648a80bc259978e5bc?d=identicon&s=25 Colin Law (Guest)
on 2011-03-10 08:27
(Received via mailing list)
On 9 March 2011 11:59, anu priya <anuhema1989@gmail.com> 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)?
Please log in before posting. Registration is free and takes only a minute.
Existing account

NEW: Do you have a Google/GoogleMail, Yahoo or Facebook account? No registration required!
Log in with Google account | Log in with Yahoo account | Log in with Facebook account
No account? Register here.