I\'ve pretty much tried everything, but it seems impossible to use expire_fragment from models? I know you\'re not supposed to and it\'s non-MVC, but surely there much be
This might not work for what you're doing, but you may be able to define a custom call back on your model:
class SomeModel < ActiveRecord::Base
define_callback :after_exploded
def explode
... do something that invalidates your cache ...
callback :after_exploded
end
end
You can then use a sweeper like you would normally:
class SomeModelSweeper < ActionController::Caching::Sweeper
observe SomeModel
def after_exploded(model)
... expire your cache
end
end
Let me know if this is useful!
Will it not be easier and clean just to pass the current controller as an argument to the model method call? Like following:
def delete_cascade(controller)
self.categories.each do |c|
c.delete_cascade(controller)
controller.expire_fragment(%r{article_manager/list/#{c.id}.*})
end
PtSection.delete(self.id)
controller.expire_fragment(%r{category_manager/list/#{self.id}.*})
end
You can access all public methods and properties of the controller from within model. As long as you do not modify the state of the controller, it should be fine.
The solution provided by Orion works perfectly. As an enhancement and for convenience, I've put the following code into config/initializers/active_record_expire_fragment.rb
class ActiveRecord::Base
def expire_fragment(*args)
ActionController::Base.new.expire_fragment(*args)
end
end
Now, you can use expire_fragment on all instances of ActiveRecord::Base, e.g. User.first.expire_fragment('user-stats')
Disclaimer: My rails is a bit rusty, but this or something like it should work
ActionController::Base.new.expire_fragment(key, options = nil)
I'm a bit of a rails noob, so this may not be correct, or even helpful, but it seems wrong to be trying to call controller actions from within the model.
Is it not possible to write an action within the controller that does what you want and then invoke the controller action from within your rake task?
In one of my scripts I use the following hack:
require 'action_controller/test_process'
sweepers = [ApartmentSweeper]
ActiveRecord::Base.observers = sweepers
ActiveRecord::Base.instantiate_observers
controller = ActionController::Base.new
controller.request = ActionController::TestRequest.new
controller.instance_eval do
@url = ActionController::UrlRewriter.new(request, {})
end
sweepers.each do |sweeper|
sweeper.instance.controller = controller
end
Then, once the ActiveRecord callbacks are called, sweepers are able to call expire_fragment.