Forum: Ruby on Rails Expiring cache from a rake task

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.
679c9b82011303c2affa33adba533e36?d=identicon&s=25 Levy Carneiro Jr. (Guest)
on 2009-02-11 11:14
(Received via mailing list)
Hello,

I have a question on cache expiration only working from the web, and not
from the console or from a rake task.

I have 2 models, Post e Comments.
I have this page /archives where I list all old posts.
I created a controller 'archives', where I have a page cache
(caches_page
:index).
I need to expire this page cache, every time a Post or Comment is
created/updated/destroyed.

Using sweepers, this works 100%. (
http://www.railsenvy.com/2007/2/28/rails-caching-t...)

The problem is that, now, I implemented spam moderation by Akismet.
So when a new comment is created in the database, it gets a 'pending'
status. And there's a rake task that runs every x minutes, in order to
check
all 'pending' comments against the Akismet database, and only then
comments
earn an 'approved' or 'spam' status. And it's only then that I should
expire
the /archives page.

So I need to expire a cached page, from something that happens outsite a
controller. And it seems the only situation a sweeper works is when the
event is triggered by the web.

If I open the console, add a new comment to a post, nothing happens
(ok!).
And now I run the Akismet check, and assuming it gives the comment an
'approved' status, the cache is not expired, when it should be.

I tried to use Observers, from the Rails docs (
http://www.railsbrain.com/api/rails-2.2.2/doc/inde...
).

In environment.rb I added the line: config.active_record.observers =
:archives_observer
I created the file app/models/archives_observer.rb with:

class ArchivesObserver < ActiveRecord::Observer
  observe :post, :comment

  def after_save(record)
    expire_page(:controller => 'archives', :action => 'index')
  end
end

But I get an error: NoMethodError: undefined method `expire_page' for
#<ArchivesObserver:0x247eddc>

I tried this also:

class ArchivesObserver < ActionController::Caching::Sweeper
(...)

In this case, there's no error, and it does nothing at all. The
public/archives.html just stays there.

I'm trying my best to avoid hacking it, using a simple File.delete :)
Like the code below:

    # File rails/actionpack/lib/action_controller/caching/pages.rb, line
65
65:         def expire_page(path)
66:           return unless perform_caching
67:
68:           benchmark "Expired page: #{page_cache_file(path)}" do
69:             File.delete(page_cache_path(path)) if
File.exist?(page_cache_path(path))
70:           end
71:         end

Is there a way to expire pages without having to hack it?

Thanks a lot,
Levy
Ef9ecd30591995af2cf62cde10b26e49?d=identicon&s=25 Wincent Colaiuta (Guest)
on 2009-02-22 18:10
(Received via mailing list)
On Feb 11, 11:14 am, "Levy Carneiro Jr." <l...@levycarneiro.com>
wrote:

>
> Is there a way to expire pages without having to hack it?
I ran into a similar issue a few days ago. If I remember correctly, if
you look at what Rails is doing under the covers, you'll see that
ActionController::Caching::Sweeper subclasses will only work when
called from inside a controller. Basically the "expire_page" message
ends up getting intercepted by "method_missing", which tries to
forward it on to a controller stored in the @controller instance
variable. So if you invoke your Sweeper subclass from somewhere else
(like a Rake task), that @controller variable will be nil and nothing
will happen.

My workaround was just to fall back to File.delete and friends. Ugly,
but it works.

Cheers,
Wincent
679c9b82011303c2affa33adba533e36?d=identicon&s=25 Levy Carneiro Jr. (Guest)
on 2009-03-01 04:32
(Received via mailing list)
Thanks, Vincent.

I just wanted to know if there was something better. I guess I'll resort
to
the File.delete and friends as you mentioned :)

Regards,
Levy
2505b282d57c29be797dc35b245adb4c?d=identicon&s=25 Philip Hallstrom (Guest)
on 2009-03-01 05:33
(Received via mailing list)
Coming in late, but this might be helpful... I've used this from ./
script/runner... not quite rake, but...

...
require 'lib/console_app'
...
ActionController::Base.expire_page(app.user_profile_path(:id =>
user.username))
...

(where 'user_profile' is a named route)
This topic is locked and can not be replied to.