Bob Hutchison
2007-Mar-12 04:10 UTC
Clarification of how controllers and views work together...
Hi, So I''ve started mucking about with Merb. I''m doing some experimenting with some product ideas. Things are working out quite well, Merb is a pleasure to use. It seems very fast too. A couple of rough spots but that might be me, if they are still chaffing after a few more days I''ll mention them. One thing... I wrote a controller and a view with several partials. Works fine. Now lets say that I have to generate a bunch of static files that are exactly like that page generated by that controller. So I generated an array of hashes, where each hash provides the information needed by the views and partials. In a loop, I set an instance variable, say @data, to each hash in the array then render the view. It works the first time, subsequent times produce pages identical to the first. I put a few puts in the view so I know it is executing and isn''t caching its results. When I look at object_ids I''m starting to see what might be going on. The object_id of the @data object is never the same as in the controller, and it never changes during that request. Next request it is different but doesn''t change. Sounds like some kind of cache. Now, I''m thinking I''m either out of luck, or there is a trivial thing I have to do to loosen the view''s grip on that copy of @data that it has. Any help is appreciated. Cheers, Bob ---- Bob Hutchison -- blogs at <http://www.recursive.ca/ hutch/> Recursive Design Inc. -- <http://www.recursive.ca/> xampl for Ruby -- <http://rubyforge.org/projects/xampl/>
Ezra Zygmuntowicz
2007-Mar-12 07:01 UTC
Clarification of how controllers and views work together...
Hey Bob- Let me explain what is happening. WHen you call render in your controller action a new ViewContext instance is created. The ViewContext takes the controller as an argument and copies all of its instance variables into the VIewContext, then the same view context is cached for the life of one request so subsequent renders don''t suffer the perf hit of making a new VIewContext. That being said, I will take a look and come up with a flag to create a new viewcontext by passing in a flag. Ok I took a look. Here is a patch for you to try before I commit it to the repo. The default behavior remains the same and the viewcontext is cached for subsequest renders. But if you pass in :clean_context => true along with your render method you will get a fresh context with your current ivars as you expect. Index: lib/merb/mixins/render_mixin.rb ==================================================================--- lib/merb/mixins/render_mixin.rb (revision 195) +++ lib/merb/mixins/render_mixin.rb (working copy) @@ -78,7 +78,7 @@ engine = engine_for(template) options = { :file => template, - :view_context => _view_context, + :view_context => (opts[:clean_context] ? clean_view_context : _view_context), :opts => opts } content = engine.transform(options) @@ -96,6 +96,10 @@ @_view_context_cache ||= ViewContext.new(self) end + def clean_view_context + ViewContext.new(self) + end + # does a render with no layout. Also sets the # content type header to text/javascript. Use # this when you want to render a template with Cheers- -Ezra On Mar 11, 2007, at 9:10 PM, Bob Hutchison wrote:> Hi, > > So I''ve started mucking about with Merb. I''m doing some experimenting > with some product ideas. Things are working out quite well, Merb is a > pleasure to use. It seems very fast too. A couple of rough spots but > that might be me, if they are still chaffing after a few more days > I''ll mention them. > > One thing... > > I wrote a controller and a view with several partials. Works fine. > Now lets say that I have to generate a bunch of static files that are > exactly like that page generated by that controller. > > So I generated an array of hashes, where each hash provides the > information needed by the views and partials. In a loop, I set an > instance variable, say @data, to each hash in the array then render > the view. It works the first time, subsequent times produce pages > identical to the first. I put a few puts in the view so I know it is > executing and isn''t caching its results. When I look at object_ids > I''m starting to see what might be going on. The object_id of the > @data object is never the same as in the controller, and it never > changes during that request. Next request it is different but doesn''t > change. > > Sounds like some kind of cache. > > Now, I''m thinking I''m either out of luck, or there is a trivial thing > I have to do to loosen the view''s grip on that copy of @data that it > has. > > Any help is appreciated. > > Cheers, > Bob > > ---- > Bob Hutchison -- blogs at <http://www.recursive.ca/ > hutch/> > Recursive Design Inc. -- <http://www.recursive.ca/> > xampl for Ruby -- <http://rubyforge.org/projects/ > xampl/> > > > > _______________________________________________ > Merb-devel mailing list > Merb-devel at rubyforge.org > http://rubyforge.org/mailman/listinfo/merb-devel-- Ezra Zygmuntowicz -- Lead Rails Evangelist -- ez at engineyard.com -- Engine Yard, Serious Rails Hosting -- (866) 518-YARD (9273)
Bob Hutchison
2007-Mar-14 12:19 UTC
Clarification of how controllers and views work together...
Thanks Ezra, I''ll give it a shot this afternoon. Sorry for the delayed response, it has been crazy here. Cheers, Bob On 12-Mar-07, at 3:01 AM, Ezra Zygmuntowicz wrote:> Hey Bob- > > Let me explain what is happening. WHen you call render in your > controller action a new ViewContext instance is created. The > ViewContext takes the controller as an argument and copies all of > its instance variables into the VIewContext, then the same view > context is cached for the life of one request so subsequent renders > don''t suffer the perf hit of making a new VIewContext. > > That being said, I will take a look and come up with a flag to > create a new viewcontext by passing in a flag. > > Ok I took a look. Here is a patch for you to try before I commit > it to the repo. The default behavior remains the same and the > viewcontext is cached for subsequest renders. But if you pass > in :clean_context => true along with your render method you will > get a fresh context with your current ivars as you expect. > > > Index: lib/merb/mixins/render_mixin.rb > ==================================================================> --- lib/merb/mixins/render_mixin.rb (revision 195) > +++ lib/merb/mixins/render_mixin.rb (working copy) > @@ -78,7 +78,7 @@ > engine = engine_for(template) > options = { > :file => template, > - :view_context => _view_context, > + :view_context => (opts[:clean_context] ? > clean_view_context : _view_context), > :opts => opts > } > content = engine.transform(options) > @@ -96,6 +96,10 @@ > @_view_context_cache ||= ViewContext.new(self) > end > > + def clean_view_context > + ViewContext.new(self) > + end > + > # does a render with no layout. Also sets the > # content type header to text/javascript. Use > # this when you want to render a template with > > > > Cheers- > -Ezra > > > On Mar 11, 2007, at 9:10 PM, Bob Hutchison wrote: > >> Hi, >> >> So I''ve started mucking about with Merb. I''m doing some experimenting >> with some product ideas. Things are working out quite well, Merb is a >> pleasure to use. It seems very fast too. A couple of rough spots but >> that might be me, if they are still chaffing after a few more days >> I''ll mention them. >> >> One thing... >> >> I wrote a controller and a view with several partials. Works fine. >> Now lets say that I have to generate a bunch of static files that are >> exactly like that page generated by that controller. >> >> So I generated an array of hashes, where each hash provides the >> information needed by the views and partials. In a loop, I set an >> instance variable, say @data, to each hash in the array then render >> the view. It works the first time, subsequent times produce pages >> identical to the first. I put a few puts in the view so I know it is >> executing and isn''t caching its results. When I look at object_ids >> I''m starting to see what might be going on. The object_id of the >> @data object is never the same as in the controller, and it never >> changes during that request. Next request it is different but doesn''t >> change. >> >> Sounds like some kind of cache. >> >> Now, I''m thinking I''m either out of luck, or there is a trivial thing >> I have to do to loosen the view''s grip on that copy of @data that it >> has. >> >> Any help is appreciated. >> >> Cheers, >> Bob >> >> ---- >> Bob Hutchison -- blogs at <http://www.recursive.ca/ >> hutch/> >> Recursive Design Inc. -- <http://www.recursive.ca/> >> xampl for Ruby -- <http://rubyforge.org/projects/ >> xampl/> >> >> >> >> _______________________________________________ >> Merb-devel mailing list >> Merb-devel at rubyforge.org >> http://rubyforge.org/mailman/listinfo/merb-devel > > -- Ezra Zygmuntowicz-- Lead Rails Evangelist > -- ez at engineyard.com > -- Engine Yard, Serious Rails Hosting > -- (866) 518-YARD (9273) > >---- Bob Hutchison -- blogs at <http://www.recursive.ca/ hutch/> Recursive Design Inc. -- <http://www.recursive.ca/> xampl for Ruby -- <http://rubyforge.org/projects/xampl/>
Bob Hutchison
2007-Mar-17 14:42 UTC
Clarification of how controllers and views work together...
Hi Ezra, On 12-Mar-07, at 3:01 AM, Ezra Zygmuntowicz wrote:> Ok I took a look. Here is a patch for you to try before I commit > it to the repo. The default behavior remains the same and the > viewcontext is cached for subsequest renders. But if you pass > in :clean_context => true along with your render method you will > get a fresh context with your current ivars as you expect. >That worked perfectly. Thanks! Just wondering... what do you gain by caching the ViewContext? Well, more precisely, when would the output of the render be different when using the cached ViewContext? Doesn''t the ViewContext pretty much control the input to the rendering? ... I suppose some of the view''s input could be computed by calls (that changed the state of something, otherwise the result of the call would always be the same) made by the view but is that a good idea? Cheers, Bob ---- Bob Hutchison -- tumblelog at <http:// www.recursive.ca/so/> Recursive Design Inc. -- <http://www.recursive.ca/> xampl for Ruby -- <http://rubyforge.org/projects/xampl/>
Ezra Zygmuntowicz
2007-Mar-17 18:10 UTC
Clarification of how controllers and views work together...
On Mar 17, 2007, at 7:42 AM, Bob Hutchison wrote:> Hi Ezra, > > On 12-Mar-07, at 3:01 AM, Ezra Zygmuntowicz wrote: > >> Ok I took a look. Here is a patch for you to try before I commit >> it to the repo. The default behavior remains the same and the >> viewcontext is cached for subsequest renders. But if you pass >> in :clean_context => true along with your render method you will >> get a fresh context with your current ivars as you expect. >> > > That worked perfectly. Thanks! > > Just wondering... what do you gain by caching the ViewContext? > Well, more precisely, when would the output of the render be > different when using the cached ViewContext? Doesn''t the > ViewContext pretty much control the input to the rendering? ... I > suppose some of the view''s input could be computed by calls (that > changed the state of something, otherwise the result of the call > would always be the same) made by the view but is that a good idea? > > Cheers, > BobHey Bob- If we don''t cache the view context then layouts will not work properly. The views that have layouts are rendered in a 2 step process. First the inner template is rendered and an instance var is set on the cached view context so when the layout gets rendered that ivar is expanded to the layout content. If the view context is not cached the layout will be empty, and its a performance hit to copy ivars over twice. You will notice rails does something similar by only allowing you to render once. I don''t limit you to rendering once and merb renders just return strings and merb actions send whatever their return value is to the browser. Cheers- -- Ezra Zygmuntowicz -- Lead Rails Evangelist -- ez at engineyard.com -- Engine Yard, Serious Rails Hosting -- (866) 518-YARD (9273)
Bob Hutchison
2007-Mar-17 19:16 UTC
Clarification of how controllers and views work together...
On 17-Mar-07, at 2:10 PM, Ezra Zygmuntowicz wrote:> > On Mar 17, 2007, at 7:42 AM, Bob Hutchison wrote: > >> Hi Ezra, >> >> On 12-Mar-07, at 3:01 AM, Ezra Zygmuntowicz wrote: >> >>> Ok I took a look. Here is a patch for you to try before I commit >>> it to the repo. The default behavior remains the same and the >>> viewcontext is cached for subsequest renders. But if you pass >>> in :clean_context => true along with your render method you >>> will get a fresh context with your current ivars as you expect. >>> >> >> That worked perfectly. Thanks! >> >> Just wondering... what do you gain by caching the ViewContext? >> Well, more precisely, when would the output of the render be >> different when using the cached ViewContext? Doesn''t the >> ViewContext pretty much control the input to the rendering? ... I >> suppose some of the view''s input could be computed by calls (that >> changed the state of something, otherwise the result of the call >> would always be the same) made by the view but is that a good idea? >> >> Cheers, >> Bob > > > Hey Bob- > > If we don''t cache the view context then layouts will not work > properly. The views that have layouts are rendered in a 2 step > process. First the inner template is rendered and an instance var > is set on the cached view context so when the layout gets rendered > that ivar is expanded to the layout content. If the view context is > not cached the layout will be empty, and its a performance hit to > copy ivars over twice.Coincidentally I''m not using layouts, so I didn''t seen any problems :-) And you can''t accomplish the same by caching the result in the case of layouts? Not via the view context, but an option maybe?> > You will notice rails does something similar by only allowing you > to render once. I don''t limit you to rendering once and merb > renders just return strings and merb actions send whatever their > return value is to the browser.I certainly did notice and I think what you''ve done is a very good idea. Very handy. I''m doing stuff in Merb that I can''t do in Rails so I''m happy. I think this is a pretty nice feature that you should draw a bit of attention to. Cheers, Bob> > Cheers- > -- Ezra Zygmuntowicz-- Lead Rails Evangelist > -- ez at engineyard.com > -- Engine Yard, Serious Rails Hosting > -- (866) 518-YARD (9273) > >---- Bob Hutchison -- tumblelog at <http:// www.recursive.ca/so/> Recursive Design Inc. -- <http://www.recursive.ca/> xampl for Ruby -- <http://rubyforge.org/projects/xampl/>