Skip to content

Commit

Permalink
Implement save! (#1)
Browse files Browse the repository at this point in the history
  • Loading branch information
jcouball authored Jan 19, 2022
1 parent 2cdbe42 commit ca12c6d
Show file tree
Hide file tree
Showing 3 changed files with 61 additions and 0 deletions.
29 changes: 29 additions & 0 deletions lib/active_model_persistence.rb
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@

# A set of mixins to add to ActiveModel classes to support persistence
#
# @api public
#
module ActiveModelPersistence
# A base class for all ActiveModelPersistence errors
class ModelError < StandardError; end
Expand All @@ -14,6 +16,33 @@ class ObjectNotInIndexError < ModelError; end

# Raised when trying to add an object to an index when the key already exists in the index for another object
class UniqueConstraintError < ModelError; end

# Raised when trying to save an invalid object
class ObjectNotSavedError < ModelError
# The object that was not saved
#
# @example
# object = Object.new
# error = ObjectNotSavedError.new('Invalid object', object)
# error.object == object #=> true
#
# @return [Object] The object that was not saved
#
attr_reader :object

# Create a new error
#
# @example
# ObjectNotSavedError.new('Invalid object', self)
#
# @param message [String] The error message
# @param object [Object] The object that was not saved
#
def initialize(message = nil, object = nil)
@object = object
super(message)
end
end
end

require_relative 'active_model_persistence/index'
Expand Down
23 changes: 23 additions & 0 deletions lib/active_model_persistence/persistence.rb
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ module ActiveModelPersistence
# attribute :id, :integer
# attribute :name, :string
# index :id, unique: true
# validates :id, presence: true
# end
#
# # Creating a model instance with `.new` does not save it to the object store
Expand Down Expand Up @@ -274,6 +275,28 @@ def save(**_options, &block)
result != false
end

# Calls #save and raises an error if #save returns false
#
# @example
# object = ModelExample.new(id: nil, name: 'James')
# object.save! #=> raises ObjectNotSavedError
#
# @param _options [Hash] save options (currently unused)
#
# @param block [Proc] a block to call after the save
#
# @yield [self] a block to call after the save
# @yieldparam saved_model [self] the model object after it was saved
# @yieldreturn [void]
#
# @raise [ObjectNotSavedError] if the model object was not saved
#
# @return [Boolean] returns true or raises an error
#
def save!(**options, &block)
save(**options, &block) || raise(ObjectNotSavedError.new('Failed to save the object', self))
end

# Deletes the object from the object store
#
# This model object is frozen to reflect that no changes should be made
Expand Down
9 changes: 9 additions & 0 deletions spec/active_model_persistence/persistence_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,15 @@
end
end

describe '#save!' do
context 'for an invalid object' do
let(:object) { model_class.new }
it 'should raise an error' do
expect { object.save! }.to raise_error(ActiveModelPersistence::ObjectNotSavedError)
end
end
end

describe '#save' do
let(:object) { model_class.new(attributes) }
before do
Expand Down

0 comments on commit ca12c6d

Please sign in to comment.