Forum: Ruby on Rails cache everything but...

Announcement (2017-05-07): www.ruby-forum.com is now read-only since I unfortunately do not have the time to support and maintain the forum any more. Please see rubyonrails.org/community and ruby-lang.org/en/community for other Rails- und Ruby-related community platforms.
9daa9b4739a6e95078cbcfb624d7bb8e?d=identicon&s=25 davidnwelton@gmail.com (Guest)
on 2007-05-29 14:11
(Received via mailing list)
I saw this older post when searching for information:

On Feb 16, 5:10 pm, Ingo Weiss <rails-mailing-l...@andreas-s.net>
wrote:

> possible?
I have exactly the same need - a front page that has a bit of text
that changes depending on whether the user is logged in or not.
Everything else could be cached using page cacheing.

Hrm.... I'll take a look at the code... maybe something like
'cache_except' is possible?

Thanks,
Dave
--
http://www.dedasys.com/davidw/
19605c7ede229e507e894865308a6d53?d=identicon&s=25 Gustav Paul (Guest)
on 2007-05-29 15:29
(Received via mailing list)
davidnwelton@gmail.com wrote:
>> content instead. A good example would be a page whereallcontent would
> Everything else could be cached using page cacheing.
>
> Hrm.... I'll take a look at the code... maybe something like
> 'cache_except' is possible?
>
> Thanks,
> Dave
> --
> http://www.dedasys.com/davidw/
>
Hey

I had the same issue and settled for two cashed versions of my page, one
for logged in users and one for visitors.
I put the code changes into a plugin you might want to have a look at.

http://rails.co.za/articles/2007/01/10/cachefilter-update
and then some bug fixes later...
http://rails.co.za/articles/2007/02/07/cachefilter...

HTH

Gustav Paul
9daa9b4739a6e95078cbcfb624d7bb8e?d=identicon&s=25 davidnwelton@gmail.com (Guest)
on 2007-05-29 16:04
(Received via mailing list)
> > I have exactly the same need - a front page that has a bit of text
> > that changes depending on whether the user is logged in or not.
> > Everything else could be cached using page cacheing.

> I had the same issue and settled for two cashed versions of my page, one
> for logged in users and one for visitors.
> I put the code changes into a plugin you might want to have a look at.
>
> http://rails.co.za/articles/2007/01/10/cachefilter-update
> and then some bug fixes 
later...http://rails.co.za/articles/2007/02/07/cachefilter......

Looks like a good way of doing it.

I was thinking about something like this:

1) Create a no_cache method as a helper.  The trick is that it outputs
something like <%= blah blah %>
2) Cache the page.
3) Render the cached version, which does the substitution on what
no_cache slipped into the cache.

I don't know whether how efficient that is, since the whole page still
has to be parsed up for erb, when there is only one little chunk of
it.  I also don't know if there are any lurking problems...

Thanks,
Dave
--
http://www.dedasys.com/davidw/
9daa9b4739a6e95078cbcfb624d7bb8e?d=identicon&s=25 davidnwelton@gmail.com (Guest)
on 2007-05-29 19:14
(Received via mailing list)
> I was thinking about something like this:
>
> 1) Create a no_cache method as a helper.  The trick is that it outputs
> something like <%= blah blah %>
> 2) Cache the page.
> 3) Render the cached version, which does the substitution on what
> no_cache slipped into the cache.

Ok, some code that seems to work:

class NoCacheFilter

  include ActionController::Caching::Actions

  def initialize(*actions, &block)
    @actions = actions
  end

  def before(controller)
    return unless @actions.include?(controller.action_name.intern)
    controller.instance_variable_set '@dont_interpolate_this', true
    action_cache_path = ActionCachePath.new(controller)
    if cache = controller.read_fragment(action_cache_path.path)
      controller.rendered_action_cache = true
      set_content_type!(action_cache_path)
      controller.send(:render, :inline => cache)
      false
    end

  end

  def after(controller)
    return if !@actions.include?(controller.action_name.intern) ||
controller.rendered_action_cache
    controller.write_fragment(ActionCachePath.path_for(controller),
controller.response.body)
    controller.send(:render, :inline => controller.response.body)
  end

  private
  def set_content_type!(action_cache_path)
    if extention = action_cache_path.extension
      content_type = Mime::EXTENSION_LOOKUP[extention]
      action_cache_path.controller.response.content_type =
content_type.to_s
    end
  end

end

Combined with this helper:

  def no_cache(text)
    return eval(text) unless @dont_interpolate_this
    return "<%= #{text} %>"
  end

Things that could perhaps be improved:

1) I don't like setting the variable in the controller.
2) I don't really like the fact that no_cache takes text as an
argument rather than somehow accomplishing the same thing with a
block, but there's no way to get a block's text out, so a string it
is, as far as I can tell.
9daa9b4739a6e95078cbcfb624d7bb8e?d=identicon&s=25 davidnwelton@gmail.com (Guest)
on 2007-05-29 20:05
(Received via mailing list)
>   def after(controller)
>     return if !...@actions.include?(controller.action_name.intern) ||
> controller.rendered_action_cache
>     controller.write_fragment(ActionCachePath.path_for(controller),
> controller.response.body)
>     controller.send(:render, :inline => controller.response.body)
>   end

Ugh, that isn't quite right, either, because apparently you can't do
any sort of render operation in the after filter, not even
render_to_string.  This is pretty hacky feeling, but if that's what it
takes...

  def after(controller)
    return if !@actions.include?(controller.action_name.intern) ||
controller.rendered_action_cache
    controller.write_fragment(ActionCachePath.path_for(controller),
controller.response.body)
    controller.instance_variable_set '@performed_render', false
    controller.response.body =
controller.send(:render_to_string, :inline =>
controller.response.body)
  end

Cleaner ideas welcome!
This topic is locked and can not be replied to.