Skip to content
Merged
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
20 changes: 16 additions & 4 deletions lib/active_resource/base.rb
Original file line number Diff line number Diff line change
Expand Up @@ -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 <tt>save</tt>. If any
# of the <tt>before_*</tt> callbacks throw +:abort+ the action is
# cancelled and <tt>save</tt> raises ActiveResource::ResourceInvalid.
#
# ==== Examples
# my_company = Company.new(:name => 'RoleModel Software', :owner => 'Ken Auer', :size => 2)
# my_company.new? # => true
Expand All @@ -1405,14 +1409,18 @@ def save
# See ActiveResource::Validations for more information.
#
# There's a series of callbacks associated with <tt>save!</tt>. If any
# of the <tt>before_*</tt> callbacks return +false+ the action is
# of the <tt>before_*</tt> callbacks throw +:abort+ the action is
# cancelled and <tt>save!</tt> raises ActiveResource::ResourceInvalid.
def save!
save || raise(ResourceInvalid.new(self))
end

# Deletes the resource from the remote service.
#
# There's a series of callbacks associated with <tt>destroy</tt>. If any
# of the <tt>before_destroy</tt> callbacks throw +:abort+ the action is
# cancelled.
#
# ==== Examples
# my_id = 3
# my_person = Person.find(my_id)
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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 <tt>create</tt>. If any
# of the <tt>before_create</tt> callbacks throw +:abort+ the action is
# cancelled.
def create
run_callbacks :create do
connection.post(collection_path, encode, self.class.headers).tap do |response|
Expand Down
53 changes: 51 additions & 2 deletions lib/active_resource/callbacks.rb
Original file line number Diff line number Diff line change
Expand Up @@ -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:
#
# * <tt>save</tt> (<tt>around_save</tt>, <tt>before_save</tt>, <tt>after_save</tt>)
# * <tt>create</tt> (<tt>around_create</tt>, <tt>before_create</tt>, <tt>after_create</tt>)
# * <tt>update</tt> (<tt>around_update</tt>, <tt>before_update</tt>, <tt>after_update</tt>)
# * <tt>destroy</tt> (<tt>around_destroy</tt>, <tt>before_destroy</tt>, <tt>after_destroy</tt>)
# * <tt>reload</tt> (<tt>around_reload</tt>, <tt>before_reload</tt>, <tt>after_reload</tt>)
#
# As an example of the callbacks initiated, consider the {ActiveResource::Base#save}[rdoc-ref:Base#save] call for a new resource:
#
# * (-) <tt>save</tt>
# * (-) <tt>valid?</tt>
# * (1) <tt>before_validation</tt>
# * (-) <tt>validate</tt>
# * (2) <tt>after_validation</tt>
# * (3) <tt>before_save</tt>
# * (4) <tt>before_create</tt>
# * (-) <tt>create</tt>
# * (5) <tt>after_create</tt>
# * (6) <tt>after_save</tt>
#
# == Canceling callbacks
#
# If a <tt>before_*</tt> 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 <tt>_*_callbacks</tt> method on an object. Active Model \Callbacks support
# <tt>:before</tt>, <tt>:after</tt> and <tt>:around</tt> as values for the <tt>kind</tt> property. The <tt>kind</tt> 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 <tt>rest_when_dead</tt> use the <tt>filter</tt> 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
1 change: 1 addition & 0 deletions lib/active_resource/rescuable.rb
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ module Rescuable

around_save :handle_exceptions
around_destroy :handle_exceptions
around_reload :handle_exceptions
end

private
Expand Down
15 changes: 15 additions & 0 deletions test/cases/callbacks_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down