Skip to content

Activate sweeper AR callback only in context of the configured controller actions #28

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 17 additions & 2 deletions lib/rails/observers/action_controller/caching/sweeper.rb
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,14 @@ def around(controller)
clean_up
end

# Execute standard observer logic only if controller was initiated, i.e.
# it is being triggered from the controller/action as specified in
# controller's <tt>cache_sweeper</tt> class method.
def update(observed_method, object, *extra_args, &block) #:nodoc:
return unless controller
super
end

protected
# gets the action cache path for the given options.
def action_path_for(options)
Expand All @@ -48,8 +56,15 @@ def callback(timing)
controller_callback_method_name = "#{timing}_#{controller.controller_name.underscore}"
action_callback_method_name = "#{controller_callback_method_name}_#{controller.action_name}"

__send__(controller_callback_method_name) if respond_to?(controller_callback_method_name, true)
__send__(action_callback_method_name) if respond_to?(action_callback_method_name, true)
if respond_to?(controller_callback_method_name, true)
warn "[DEPRECATION] Using Sweeper for controller callback is deprecated. Sweeper is just an observer of ActiveRecord object that gets triggered when specified controller action is executed"
__send__(controller_callback_method_name)
end

if respond_to?(action_callback_method_name, true)
warn "[DEPRECATION] Using Sweeper for controller callback is deprecated. Sweeper is just an observer of ActiveRecord object that gets triggered when specified controller action is executed"
__send__(action_callback_method_name)
end
end

def method_missing(method, *arguments, &block)
Expand Down
6 changes: 4 additions & 2 deletions lib/rails/observers/action_controller/caching/sweeping.rb
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
module ActionController #:nodoc:
module Caching
# Sweepers are the terminators of the caching world and responsible for expiring caches when model objects change.
# They do this by being half-observers, half-filters and implementing callbacks for both roles. A Sweeper example:
# They do this by being observers of model that are executed only when specified controller action is being executed.
# Sweeper can access the corresponding controller via <tt>controller</tt> accessor. Additionally, missing method calls are automatically routed to the corresponding controller.
# A Sweeper example:
#
# class ListSweeper < ActionController::Caching::Sweeper
# observe List, Item
Expand All @@ -21,7 +23,7 @@ module Caching
# cache_sweeper :list_sweeper, :only => [ :edit, :destroy, :share ]
# end
#
# In the example above, four actions are cached and three actions are responsible for expiring those caches.
# In the example above, four actions are cached and three actions are responsible for expiring those caches, i.e. <tt>ListSweeper.after_save</tt> will only be executed in the context of those actions.
#
# You can also name an explicit class in the declaration of a sweeper, which is needed if the sweeper is in a module:
#
Expand Down
27 changes: 26 additions & 1 deletion test/sweeper_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,13 @@

SharedTestRoutes = ActionDispatch::Routing::RouteSet.new

class AppSweeper < ActionController::Caching::Sweeper; end
class AppSweeper < ActionController::Caching::Sweeper

def around_save(record)
yield :in_around_save
end

end

class SweeperTestController < ActionController::Base
include SharedTestRoutes.url_helpers
Expand Down Expand Up @@ -40,6 +46,25 @@ def test_sweeper_should_not_ignore_no_method_error
end
end

def test_sweeper_should_not_respond_to_update_if_controller_is_not_set
sweeper = AppSweeper.send(:new)
yielded_value = nil
sweeper.update(:around_save, Object.new) do |val|
yielded_value = val
end
assert_nil yielded_value
end

def test_sweeper_should_respond_to_update_if_controller_is_set
sweeper = AppSweeper.send(:new)
sweeper.controller = SweeperTestController.new
yielded_value = nil
sweeper.update(:around_save, Object.new) do |val|
yielded_value = val
end
assert_equal :in_around_save, yielded_value
end

def test_sweeper_should_not_block_rendering
response = test_process(SweeperTestController)
assert_equal 'hello world', response.body
Expand Down