diff --git a/lib/active_resource/base.rb b/lib/active_resource/base.rb index 51b21a70ce..9e556b2014 100644 --- a/lib/active_resource/base.rb +++ b/lib/active_resource/base.rb @@ -1380,6 +1380,10 @@ def dup # is Json for the final object as it looked after the \save (which would include attributes like +created_at+ # that weren't part of the original submit). # + # There's a series of callbacks associated with save. If any + # of the before_* callbacks throw +:abort+ the action is + # cancelled and save raises ActiveResource::ResourceInvalid. + # # ==== Examples # my_company = Company.new(:name => 'RoleModel Software', :owner => 'Ken Auer', :size => 2) # my_company.new? # => true @@ -1405,7 +1409,7 @@ def save # See ActiveResource::Validations for more information. # # There's a series of callbacks associated with save!. If any - # of the before_* callbacks return +false+ the action is + # of the before_* callbacks throw +:abort+ the action is # cancelled and save! raises ActiveResource::ResourceInvalid. def save! save || raise(ResourceInvalid.new(self)) @@ -1413,6 +1417,10 @@ def save! # Deletes the resource from the remote service. # + # There's a series of callbacks associated with destroy. If any + # of the before_destroy callbacks throw +:abort+ the action is + # cancelled. + # # ==== Examples # my_id = 3 # my_person = Person.find(my_id) @@ -1468,9 +1476,9 @@ def encode(options = {}) # my_branch.reload # my_branch.name # => "Wilson Road" def reload - self.load(self.class.find(to_param, params: @prefix_options).attributes, false, true) - rescue => exception - rescue_with_handler(exception) || raise + run_callbacks :reload do + self.load(self.class.find(to_param, params: @prefix_options).attributes, false, true) + end end # A method to manually load attributes from a \hash. Recursively loads collections of @@ -1614,6 +1622,10 @@ def update end # Create (i.e., \save to the remote service) the \new resource. + # + # There's a series of callbacks associated with create. If any + # of the before_create callbacks throw +:abort+ the action is + # cancelled. def create run_callbacks :create do connection.post(collection_path, encode, self.class.headers).tap do |response| diff --git a/lib/active_resource/callbacks.rb b/lib/active_resource/callbacks.rb index c8f04cec94..e3a54b9b4d 100644 --- a/lib/active_resource/callbacks.rb +++ b/lib/active_resource/callbacks.rb @@ -3,20 +3,69 @@ require "active_support/core_ext/array/wrap" module ActiveResource + # = Active Resource \Callbacks + # + # \Callbacks are hooks into the life cycle of an Active Resource object that allow you to trigger logic + # before or after a change in the object state. Active Resources instances trigger callbacks for the following methods: + # + # * save (around_save, before_save, after_save) + # * create (around_create, before_create, after_create) + # * update (around_update, before_update, after_update) + # * destroy (around_destroy, before_destroy, after_destroy) + # * reload (around_reload, before_reload, after_reload) + # + # As an example of the callbacks initiated, consider the {ActiveResource::Base#save}[rdoc-ref:Base#save] call for a new resource: + # + # * (-) save + # * (-) valid? + # * (1) before_validation + # * (-) validate + # * (2) after_validation + # * (3) before_save + # * (4) before_create + # * (-) create + # * (5) after_create + # * (6) after_save + # + # == Canceling callbacks + # + # If a before_* callback throws +:abort+, all the later callbacks and + # the associated action are cancelled. + # \Callbacks are generally run in the order they are defined, with the exception of callbacks defined as + # methods on the model, which are called last. + # + # == Debugging callbacks + # + # The callback chain is accessible via the _*_callbacks method on an object. Active Model \Callbacks support + # :before, :after and :around as values for the kind property. The kind property + # defines what part of the chain the callback runs in. + # + # To find all callbacks in the +before_save+ callback chain: + # + # Topic._save_callbacks.select { |cb| cb.kind.eql?(:before) } + # + # Returns an array of callback objects that form the +before_save+ chain. + # + # To further check if the before_save chain contains a proc defined as rest_when_dead use the filter property of the callback object: + # + # Topic._save_callbacks.select { |cb| cb.kind.eql?(:before) }.collect(&:filter).include?(:rest_when_dead) + # + # Returns true or false depending on whether the proc is contained in the +before_save+ callback chain on a Topic model. module Callbacks extend ActiveSupport::Concern CALLBACKS = [ :before_validation, :after_validation, :before_save, :around_save, :after_save, :before_create, :around_create, :after_create, :before_update, :around_update, - :after_update, :before_destroy, :around_destroy, :after_destroy + :after_update, :before_destroy, :around_destroy, :after_destroy, + :before_reload, :around_reload, :after_reload ] included do extend ActiveModel::Callbacks include ActiveModel::Validations::Callbacks - define_model_callbacks :save, :create, :update, :destroy + define_model_callbacks :save, :create, :update, :destroy, :reload end end end diff --git a/lib/active_resource/rescuable.rb b/lib/active_resource/rescuable.rb index f7c2ba8244..78beaf5a73 100644 --- a/lib/active_resource/rescuable.rb +++ b/lib/active_resource/rescuable.rb @@ -14,6 +14,7 @@ module Rescuable around_save :handle_exceptions around_destroy :handle_exceptions + around_reload :handle_exceptions end private diff --git a/test/cases/callbacks_test.rb b/test/cases/callbacks_test.rb index a762266d70..b1dfed4057 100644 --- a/test/cases/callbacks_test.rb +++ b/test/cases/callbacks_test.rb @@ -101,6 +101,21 @@ def test_create ], developer.history end + def test_reload + developer = Developer.find(1) + developer.reload + assert_equal [ + [ :before_reload, :method ], + [ :before_reload, :proc ], + [ :before_reload, :object ], + [ :before_reload, :block ], + [ :after_reload, :method ], + [ :after_reload, :proc ], + [ :after_reload, :object ], + [ :after_reload, :block ] + ], developer.history + end + def test_update developer = Developer.find(1) developer.save