Ruby Forum Ruby on Rails > Do cache sweepers observe the controller and not the model?

Posted by Pat Maddox (pergesu)
on 09.07.2007 00:28
(Received via mailing list)
I'm (finally) looking into caching, and it seems kind of strange to
me.  If I cache a page, and then create a sweeper to expire that page,
the sweeper appears to "observe" controller actions rather than the
model.

For example, say I've got the following sweeper:

class StylesheetSweeper < ActionController::Caching::Sweeper
  observe Stylesheet

  def after_save(stylesheet)
    expire_stylesheet_page stylesheet.id
  end

  def after_destroy(stylesheet)
    expire_stylesheet_page stylesheet.id
  end

  private
  def expire_stylesheet_page(stylesheet_id)
    expire_page hash_for_stylesheet_path(stylesheet_id)
  end
end

If I open the console and make a change to a Stylesheet object, the
cache doesn't get expired.  That seems wrong to me.  Editing records
through the console would lead to a stale cache.

What am I missing?

Pat
Posted by Gone Sail (gonesail)
on 23.10.2007 23:39
i think we are missing some key documentation.  i would like to call a 
sweeper method (after_save) that is observing my model.  in essence i 
need to get around the model update  method.  i would like to know how 
to see the observers of a model.  too much to ask?
Posted by Pat Maddox (pergesu)
on 23.10.2007 23:46
(Received via mailing list)
On 10/23/07, Gone Sail <rails-mailing-list@andreas-s.net> wrote:
>
Cache sweepers are invoked from the controller, not the model.  It'd
be nice if my_model.update automatically invoked the sweeper, but
afaik that doesn't currently happen.  You set up the cache expiration
when my_controller#update gets called, etc.

Pat
Posted by Gone Sail (gonesail)
on 24.10.2007 15:49
Pat Maddox wrote:
> On 10/23/07, Gone Sail <rails-mailing-list@andreas-s.net> wrote:
>>
> Cache sweepers are invoked from the controller, not the model.  It'd
> be nice if my_model.update automatically invoked the sweeper, but
> afaik that doesn't currently happen.  You set up the cache expiration
> when my_controller#update gets called, etc.
> 
> Pat


but they ARE invoked on a save from the model.  why do you say invoked 
from controller?
Posted by Yaxm Yaxm (yaxm)
on 16.02.2008 06:51
You must put your sweeper inside the controller that'd trigger the 
sweeper.
The sweeper is triggered on change in models.
but when you step into any expire_* method in a debugger,, you'd see 
that a controller is needed!

http://trac.extendviget.com/tyrant/browser/branches/edge-conversion/vendor/rails/actionpack/lib/action_controller/caching/sweeping.rb?rev=160

          def method_missing(method, *arguments)
            return if @controller.nil?
            @controller.send(method, *arguments)
          end





Gone Sail wrote:
> Pat Maddox wrote:
>> On 10/23/07, Gone Sail <rails-mailing-list@andreas-s.net> wrote:
>>>
>> Cache sweepers are invoked from the controller, not the model.  It'd
>> be nice if my_model.update automatically invoked the sweeper, but
>> afaik that doesn't currently happen.  You set up the cache expiration
>> when my_controller#update gets called, etc.
>> 
>> Pat
> 
> 
> but they ARE invoked on a save from the model.  why do you say invoked 
> from controller?
Posted by Gone Sail (gonesail)
on 28.02.2008 18:59
OK on your logic Yaxm. So now what do we do if the controller (for 
reasons which I do not know) is nil ??  the model sweeper is trying to 
expire the fragment as it was intended but now rails is preventing it !! 
what a pain.  help.


Yaxm Yaxm wrote:
> You must put your sweeper inside the controller that'd trigger the 
> sweeper.
> The sweeper is triggered on change in models.
> but when you step into any expire_* method in a debugger,, you'd see 
> that a controller is needed!
> 
> http://trac.extendviget.com/tyrant/browser/branches/edge-conversion/vendor/rails/actionpack/lib/action_controller/caching/sweeping.rb?rev=160
> 
>           def method_missing(method, *arguments)
>             return if @controller.nil?
>             @controller.send(method, *arguments)
>           end
> 
Posted by Gone Sail (gonesail)
on 13.03.2008 23:09
can anybody respond to this? @controller is nil so expire_fragment does 
NOT get called even though the model was updated which is exactly how it 
should be done. is there a work around? a way to set the controller? i 
think this is a bug. any answers out there in the community? thanks.

>           def method_missing(method, *arguments)
>             return if @controller.nil?
>             @controller.send(method, *arguments)
>           end
Posted by Nathan Esquenazi (xgamerx)
on 14.03.2008 09:39
I don't get it. How is your model being "updated" if not through a 
controller. The whole point is that models are updated through 
controller actions. You then add sweepers to those actions which are 
invoked when the model is altered through those actions. Why would the 
controller "be nil"? There should always be a controller that is 
responsible for the actions which modify the state of your models...
Posted by RSL ___ (rsl)
on 14.03.2008 12:15
(Received via mailing list)
Are you modifying your model via script/console or runner? How often 
will
you be doing this? You could prolly instantiate a controller here or
something but if it's a really rare instance, you might just want to do
something cheap and easy like sweep the whole cache [via FileUtils.rm_rf 
or
something]. The problem with instantiating a controller is that it's 
gonna
need a CGI request to generate the urls when it is trying to expire_page
IIRC. And that may be more trouble than it's worth.

RSL

On Thu, Mar 13, 2008 at 6:09 PM, Gone Sail 
<rails-mailing-list@andreas-s.net>
Posted by Gone Sail (gonesail)
on 14.03.2008 13:57
Nathan Esquenazi wrote:
> I don't get it. How is your model being "updated" if not through a 
> controller. The whole point is that models are updated through 
> controller actions. You then add sweepers to those actions which are 
> invoked when the model is altered through those actions. Why would the 
> controller "be nil"? There should always be a controller that is 
> responsible for the actions which modify the state of your models...

i didn't say it was not going thru a controller. the thing is that the 
model is being instantiated via classify.constantize. the model name is 
not the same as the controller name but i am still doing a model.save 
therefore this should clear the cache correctly but it fails in 
caching.rb Sweeping module in the method_missing method because 
@controller is nil. i did not write this code i am just trying to fix 
it. the method that is missing is expire_fragment.

def method_missing(method, *arguments)
  return if @controller.nil?
  @controller.send!(method, *arguments)
end
Posted by RSL ___ (rsl)
on 14.03.2008 14:14
(Received via mailing list)
the controller shouldn't be nil if you are editing the model via a rails
action instigated by a controller. in your controller you should have

cache_sweeper :foo_sweeper

and in yr sweeper do you have

observe Foo

right? if so, then controller should not be nil. if not, try adding 
those
things [obviously taking into account the actual names of the sweeper 
and
model] and see if it solves yr problem. if not, please include the code 
you
use in your reply so we can see what is happening exactly. :)

RSL

On Fri, Mar 14, 2008 at 8:57 AM, Gone Sail 
<rails-mailing-list@andreas-s.net>