Skip to content

Commit ba9e52e

Browse files
committed
Forward :context option from #save and #save!
Forward the `:context` option from `Base#save` and `Base#save!` to the underlying `Validations#valid?` call. This commit alos includes test coverage for directly calling `Validations#valid?` with a `context` value, since that behavior wasn't covered by tests elsewhere in the suite.
1 parent 4fffccc commit ba9e52e

File tree

4 files changed

+40
-6
lines changed

4 files changed

+40
-6
lines changed

lib/active_resource/base.rb

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1477,6 +1477,12 @@ def dup
14771477
# is Json for the final object as it looked after the \save (which would include attributes like +created_at+
14781478
# that weren't part of the original submit).
14791479
#
1480+
# With <tt>save</tt> validations run by default. If any of them fail
1481+
# ActiveResource::ResourceInvalid gets raised, and nothing is POSTed to
1482+
# the remote system. To skip validations, pass <tt>validate: false</tt>. To
1483+
# validate withing a custom context, pass the <tt>:context</tt> option.
1484+
# See ActiveResource::Validations for more information.
1485+
#
14801486
# There's a series of callbacks associated with <tt>save</tt>. If any
14811487
# of the <tt>before_*</tt> callbacks throw +:abort+ the action is
14821488
# cancelled and <tt>save</tt> raises ActiveResource::ResourceInvalid.
@@ -1489,7 +1495,7 @@ def dup
14891495
# my_company.new? # => false
14901496
# my_company.size = 10
14911497
# my_company.save # sends PUT /companies/1 (update)
1492-
def save
1498+
def save(**options)
14931499
run_callbacks :save do
14941500
new? ? create : _update
14951501
end
@@ -1500,16 +1506,17 @@ def save
15001506
# If the resource is new, it is created via +POST+, otherwise the
15011507
# existing resource is updated via +PUT+.
15021508
#
1503-
# With <tt>save!</tt> validations always run. If any of them fail
1509+
# With <tt>save!</tt> validations run by default. If any of them fail
15041510
# ActiveResource::ResourceInvalid gets raised, and nothing is POSTed to
1505-
# the remote system.
1511+
# the remote system. To skip validations, pass <tt>validate: false</tt>. To
1512+
# validate withing a custom context, pass the <tt>:context</tt> option.
15061513
# See ActiveResource::Validations for more information.
15071514
#
15081515
# There's a series of callbacks associated with <tt>save!</tt>. If any
15091516
# of the <tt>before_*</tt> callbacks throw +:abort+ the action is
15101517
# cancelled and <tt>save!</tt> raises ActiveResource::ResourceInvalid.
1511-
def save!
1512-
save || raise(ResourceInvalid.new(self))
1518+
def save!(**options)
1519+
save(**options) || raise(ResourceInvalid.new(self))
15131520
end
15141521

15151522
##

lib/active_resource/validations.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -283,7 +283,7 @@ def save_with_validation(options = {})
283283
# ones. Otherwise we get an endless loop and can never change the
284284
# fields so as to make the resource valid.
285285
@remote_errors = nil
286-
if perform_validation && valid? || !perform_validation
286+
if perform_validation && valid?(options[:context]) || !perform_validation
287287
save_without_validation
288288
true
289289
else

test/cases/validations_test.rb

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,12 +32,30 @@ def test_fails_save!
3232
assert_raise(ActiveResource::ResourceInvalid) { p.save! }
3333
end
3434

35+
def test_save_with_context
36+
p = new_project(summary: nil)
37+
assert_not p.save(context: :completed)
38+
assert_equal [ "can't be blank" ], p.errors.messages_for(:summary, :blank)
39+
end
40+
41+
def test_save_bang_with_context
42+
p = new_project(summary: nil)
43+
assert_raise(ActiveResource::ResourceInvalid) { p.save!(context: :completed) }
44+
assert_equal [ "can't be blank" ], p.errors.messages_for(:summary, :blank)
45+
end
46+
3547
def test_save_without_validation
3648
p = new_project(name: nil)
3749
assert_not p.save
3850
assert p.save(validate: false)
3951
end
4052

53+
def test_save_bang_without_validation
54+
p = new_project(name: nil)
55+
assert_raises(ActiveResource::ResourceInvalid) { p.save! }
56+
assert p.save!(validate: false)
57+
end
58+
4159
def test_validate_callback
4260
# we have a callback ensuring the description is longer than three letters
4361
p = new_project(description: "a")
@@ -56,6 +74,14 @@ def test_client_side_validation_maximum
5674
assert_equal [ "is too long (maximum is 10 characters)" ], project.errors[:description]
5775
end
5876

77+
def test_validation_context
78+
project = new_project(summary: "")
79+
80+
assert_predicate project, :valid?
81+
assert_not project.valid?(:completed)
82+
assert_equal [ "can't be blank" ], project.errors.messages_for(:summary, :blank)
83+
end
84+
5985
def test_invalid_method
6086
p = new_project
6187

test/fixtures/project.rb

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ class Project < ActiveResource::Base
1111
validates :name, presence: true
1212
validates :description, presence: false, length: { maximum: 10 }
1313
validate :description_greater_than_three_letters
14+
validates :summary, presence: { on: :completed }
1415

1516
# to test the validate *callback* works
1617
def description_greater_than_three_letters

0 commit comments

Comments
 (0)