Skip to content
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

Run after_save and after_commit even if no changes were made #612

Merged
merged 3 commits into from
Jan 15, 2021
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
27 changes: 19 additions & 8 deletions spec/operations/save_operation_callbacks_spec.cr
Original file line number Diff line number Diff line change
Expand Up @@ -160,13 +160,22 @@ end
private class UpdateOperationWithNoUpdates < Post::SaveOperation
include TestableOperation

after_completed :mark_operation_completed
after_completed do |_saved_post|
mark_callback("after_completed_in_a_block")
after_save :mark_operation_saved
after_save do |_saved_post|
mark_callback("after_save_in_a_block")
end

private def mark_operation_completed(_saved_post)
mark_callback("after_completed_called")
after_commit :mark_operation_committed
after_commit do |_saved_post|
mark_callback("after_commit_in_a_block")
end

private def mark_operation_saved(_saved_post)
mark_callback("after_save_called")
end

private def mark_operation_committed(_saved_post)
mark_callback("after_commit_called")
end
end

Expand Down Expand Up @@ -245,12 +254,14 @@ describe "Avram::SaveOperation callbacks" do
end
end

it "runs after_completed callbacks even when nothing is being updated" do
it "runs callbacks even when nothing is being updated" do
post = PostBox.create
UpdateOperationWithNoUpdates.update(post) do |operation, _updated_post|
operation.callbacks_that_ran.should eq([
"after_completed_called",
"after_completed_in_a_block",
"after_save_called",
"after_save_in_a_block",
"after_commit_called",
"after_commit_in_a_block",
])
end
end
Expand Down
31 changes: 19 additions & 12 deletions src/avram/callbacks.cr
Original file line number Diff line number Diff line change
Expand Up @@ -522,9 +522,16 @@ module Avram::Callbacks
# ```
#
macro after_completed(method_name)
after_completed do |object|
{{ method_name.id }}(object)
end
{% raise <<-ERROR
after_completed has been removed

The after_save and after_commit callbacks are called even if no changes were made

Try this...

▸ after_commit #{method_name.id}
ERROR
%}
end

# Run the given block after save and after successful transaction commit
Expand All @@ -541,16 +548,16 @@ module Avram::Callbacks
# end
# ```
macro after_completed(&block)
def after_completed(%object : T)
{% if @type.methods.map(&.name).includes?(:after_completed.id) %}
previous_def
{% else %}
super
{% end %}
{% raise <<-ERROR
after_completed has been removed

{{ block.args.first }} = %object
{{ block.body }}
end
The after_save and after_commit callbacks are called even if no changes were made

Try this...

▸ after_commit #{block.id}
ERROR
%}
end

# :nodoc:
Expand Down
18 changes: 5 additions & 13 deletions src/avram/save_operation.cr
Original file line number Diff line number Diff line change
Expand Up @@ -291,19 +291,17 @@ abstract class Avram::SaveOperation(T)

def save : Bool
before_save
if valid? && (!persisted? || changes.any?)

if valid?
transaction_committed = database.transaction do
insert_or_update
saved_record = record.not_nil!
after_save(saved_record)
insert_or_update if changes.any? || !persisted?
akadusei marked this conversation as resolved.
Show resolved Hide resolved
after_save(record.not_nil!)
true
end

if transaction_committed
saved_record = record.not_nil!
after_commit(saved_record)
self.save_status = SaveStatus::Saved
after_completed(saved_record)
after_commit(record.not_nil!)
Avram::Events::SaveSuccessEvent.publish(
operation_class: self.class.name,
attributes: generic_attributes
Expand All @@ -313,10 +311,6 @@ abstract class Avram::SaveOperation(T)
mark_as_failed
false
end
elsif valid? && changes.empty?
self.save_status = SaveStatus::Saved
after_completed(record.not_nil!)
true
else
mark_as_failed
false
Expand Down Expand Up @@ -357,8 +351,6 @@ abstract class Avram::SaveOperation(T)

def after_commit(_record : T); end

def after_completed(_record : T); end

private def insert : T
self.created_at.value ||= Time.utc if responds_to?(:created_at)
self.updated_at.value ||= Time.utc if responds_to?(:updated_at)
Expand Down