config.cache_classes

105 views
Skip to first unread message

Stijnster

unread,
Feb 6, 2009, 7:19:52 AM2/6/09
to Ruby on Rails: Core
Hi all,

a while ago I developed a CMS that allows user with the "designer"
role to create templates. These templates are written to disk and are
regular erb files. They are stored inside the app/views folder.

Back then I developed on rails 2.1 which had the
config.action_view.cache_template_loading settings. That allowed me to
cache the whole application, except the views (since the designer
could edit them, bringing the application down-and-up wouldn't be a
good idea).

After a migration to rails 2.3 I noticed this settings was gone and
replaced by "config.cache_classes", which caches the application as a
whole, including the views. I was forced to set the production setting
to "false" in order to make it work.

The current request-response time is only 25% of the request-response
time in rails 2.1 (it dropped from 20 to 6).

Is there anyone with an idea to enable the config.cache_classes, but
still reload the views as necessary (faking out the old
config.action_view.cache_template_loading setting)?

Cheers,

Stijn

Sven Fuchs

unread,
Feb 6, 2009, 7:00:30 PM2/6/09
to rubyonra...@googlegroups.com
We've had the same problem and hope it's now working like this:

http://github.com/svenfuchs/adva_cms/blob/fd7f9348b9e9cccd3ab5af2da5437e6ca6ac9e56/engines/adva_themes/lib/theme_support/compiled_template_expiration.rb

Basically, when the user saves a template we touch the theme
directory. When the template is rendered we check the directory mtime
against the compile time for that template and recompile if necessary.

It's necessary to do it this way around (instead of just expiring the
compiled/cached template in the same request when the template was
saved) because compiled templates of course are cached per process
(e.g. mongrel) and you could not expire them for all other running
processes.

Of course that code is likely to break as soon as ActionView moves by
a millimeter ;)

Stijnster

unread,
Feb 7, 2009, 4:45:27 AM2/7/09
to Ruby on Rails: Core
Hi Sven,


thanks for pointing me in the right direction. I use a slightly
different caching method, once the user logs out of the backend, 30
minutes later the cache (page caching) starts kicking in. So I added a
method to my site_controller which looks like this;

def clear_templates
ActionView::Base::CompiledTemplates.instance_methods(false).each
do |method|
if method =~ /47#{@project.code}47/ # 47 is the ord of /, rails
encodes methods that way
ActionView::Base::CompiledTemplates.send(:remove_method,
method)
end
end
RAILS_DEFAULT_LOGGER.info("Cleared all compiled views from cache
for project '#{@project.name}'")
end

After some debugging I found out that 2 methods are being "memoized"
ActionView::Renderable.compiled_source and
ActionView::Template.source. I think the best way to disable that
behaviour would be extending the Memoizable class with a "dememoize"
method (currently it only has a dememoize_all), and next dememoize
those methods.

I should also mention that I'm on rails 2.2.2, I guess I was a bit
confused because I just read the announcement of 2.3 RC1.

Didn't you have problems with the memoized methods when you wrote your
patch?


On Feb 7, 1:00 am, Sven Fuchs <svenfu...@artweb-design.de> wrote:
> We've had the same problem and hope it's now working like this:
>
> http://github.com/svenfuchs/adva_cms/blob/fd7f9348b9e9cccd3ab5af2da54...

Sven Fuchs

unread,
Feb 7, 2009, 5:45:19 AM2/7/09
to rubyonra...@googlegroups.com
Ah, sorry!

I should have mentioned that this worksforme on Rails 2.2 (so we've
had similar issues to yours when porting from Rails 2.1). We haven't
tried porting to Rails 2.3, yet, although we plan to do so soon.

On Rails 2.2 I haven't seen any problems with memoizing here. But
perhaps I'm still missing something.

Stijnster

unread,
Feb 7, 2009, 6:16:16 AM2/7/09
to Ruby on Rails: Core
Here is what I think that's happening;

* rails boots and start loading its template files into memory
* method calls to Template.source (that loads the template from disk)
and Renderable.compiled_source are memoized so it stores the result of
those methods
* by deleteing the necessary CompiledTempaltes, the compiled_source is
being reloaded the next time the template is requested
* since compiled_source is aliased by memoization, its is now replaced
with a static method, thus it won't reload the Template.source
* by quoting the "memoize :compile_source" line, the original method
will get triggered, and now calls the source method on the template
* but that's also memoized, so by unquoting that, I get the result
that I need

I'm going to look further into this and hopefully let you know what
solution I'll find :-D

Thanks for your help so far.

On Feb 7, 11:45 am, Sven Fuchs <svenfu...@artweb-design.de> wrote:
> Ah, sorry!
>
> I should have mentioned that this worksforme on Rails 2.2 (so we've  
> had similar issues to yours when porting from Rails 2.1). We haven't  
> tried porting to Rails 2.3, yet, although we plan to do so soon.
>
> On Rails 2.2 I haven't seen any problems with memoizing here. But  
> perhaps I'm still missing something.
>
> On 07.02.2009, at 10:45, Stijnster wrote:
>
>
>
> > Hi Sven,
>
> > thanks for pointing me in the right direction. I use a slightly
> > different caching method, once the user logs out of the backend, 30
> > minutes later the cache (page caching) starts kicking in. So I added a
> > method to my site_controller which looks like this;
>
> >  def clear_templates
> >    ActionView::Base::CompiledTemplates.instance_methods(false).each
> > do |method|
> >      if method =~ /4...@project.code}47/ # 47 is the ord of /, rails
> > encodes methods that way
> >        ActionView::Base::CompiledTemplates.send(:remove_method,
> > method)
> >      end
> >    end
> >    RAILS_DEFAULT_LOGGER.info("Cleared all compiled views from cache
> > for project '...@project.name}'")

Stijnster

unread,
Feb 8, 2009, 7:22:14 AM2/8/09
to Ruby on Rails: Core
To conclude my journey into the rails-core, I'm posting the controller
method that I've added to my application controller that forces the
reload of template files, even if config.cache_classes is set to true.
As said before, I trigger this function as long as the user is logged
in to the backend + 30 minutes. After that template caching and page
caching is kicking in.

Response times are now back as the where with rails 2.1 (maybe even a
bit better, but it's hard to measure, because sites are running on the
server).

On to rails 2.3, let's hope it will work there as well :-)

def reload_templates!
# reload all templates from disk, there's no way to reload
specific templates only, since the
# templates and the array that contains them, are frozen
self.response.template.view_paths.each do |view_path|
view_path.reload!
end
logger.info("Reloaded all templates from disk")

# rails stores compiled templates as methods, so we need to remove
them in order to recompile them
ActionView::Base::CompiledTemplates.instance_methods(false).each
do |method|
if method =~ /47#{@project.code}47/ # 47 is the ord of /, rails
encodes methods that way
ActionView::Base::CompiledTemplates.send(:remove_method,
method)
end
end
logger.info("Cleared all compiled templates from cache for project
'#{@project.name}'")
end

Stijnster

unread,
Feb 9, 2009, 3:42:18 AM2/9/09
to Ruby on Rails: Core
And one final itteration; I override the eager_load_templates setting,
which will prevent to reload ALL templates ALL the times in non-cache
mode.

module ActionView
class PathSet
class Path
# alias the eager_load_templates
class << self

alias_method :old_eager_load_templates!, :eager_load_templates!
end

# don't eager_load_templates, even if cache_classes is turned on
def self.eager_load_templates!
@eager_load_templates = false
end
end
end
end

On Feb 8, 1:22 pm, Stijnster <st...@skylight.be> wrote:
> To conclude my journey into the rails-core, I'm posting the controller
> method that I've added to my application controller that forces the
> reload of template files, even if config.cache_classes is set to true.
> As said before, I trigger this function as long as the user is logged
> in to the backend + 30 minutes. After that template caching and page
> caching is kicking in.
>
> Response times are now back as the where with rails 2.1 (maybe even a
> bit better, but it's hard to measure, because sites are running on the
> server).
>
> On to rails 2.3, let's hope it will work there as well :-)
>
>   def reload_templates!
>     # reload all templates from disk, there's no way to reload
> specific templates only, since the
>     # templates and the array that contains them, are frozen
>     self.response.template.view_paths.each do |view_path|
>       view_path.reload!
>     end
>     logger.info("Reloaded all templates from disk")
>
>     # rails stores compiled templates as methods, so we need to remove
> them in order to recompile them
>     ActionView::Base::CompiledTemplates.instance_methods(false).each
> do |method|
>       if method =~ /4...@project.code}47/ # 47 is the ord of /, rails
> encodes methods that way
>         ActionView::Base::CompiledTemplates.send(:remove_method,
> method)
>       end
>     end
>     logger.info("Cleared all compiled templates from cache for project
> '...@project.name}'")
Reply all
Reply to author
Forward
0 new messages