Skip to content

Commit 92ac827

Browse files
committed
Validations: Default context based on persistence
This commit proposed that Active Resource follow the same pattern as [Active Record Validations][], namely that an instance's default validation context will be `:create` when the record **is not yet** persisted and `:update` when the record **is** persisted. [Active Record Validations]: https://api.rubyonrails.org/v8.1/classes/ActiveRecord/Validations.html#method-i-valid-3F
1 parent 492ed12 commit 92ac827

File tree

2 files changed

+44
-0
lines changed

2 files changed

+44
-0
lines changed

lib/active_resource/validations.rb

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -314,6 +314,14 @@ def load_remote_errors(remote_errors, save_cache = false) # :nodoc:
314314
# saved.
315315
# Remote errors can only be cleared by trying to re-save the resource.
316316
#
317+
# If the argument is +false+ (default is +nil+), the context is set to <tt>:create</tt> if
318+
# {new_record?}[rdoc-ref:Base#new_record?] is +true+, and to <tt>:update</tt> if it is not.
319+
# If the argument is an array of contexts, <tt>post.valid?([:create, :update])</tt>, the validations are
320+
# run within multiple contexts.
321+
#
322+
# \Validations with no <tt>:on</tt> option will run no matter the context. \Validations with
323+
# some <tt>:on</tt> option will only run in the specified context.
324+
#
317325
# ==== Examples
318326
# my_person = Person.create(params[:person])
319327
# my_person.valid?
@@ -324,6 +332,8 @@ def load_remote_errors(remote_errors, save_cache = false) # :nodoc:
324332
# # => false
325333
#
326334
def valid?(context = nil)
335+
context ||= new_record? ? :create : :update
336+
327337
run_callbacks :validate do
328338
super
329339
load_remote_errors(@remote_errors, true) if defined?(@remote_errors) && @remote_errors.present?

test/cases/validations_test.rb

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,13 @@
88
# This test case simply makes sure that they are all accessible by
99
# Active Resource objects.
1010
class ValidationsTest < ActiveSupport::TestCase
11+
class DraftProject < ::Project
12+
self.element_name = "project"
13+
14+
validates :name, format: { with: /\ACREATE:/, on: :create }
15+
validates :name, format: { with: /\AUPDATE:/, on: :update }
16+
end
17+
1118
VALID_PROJECT_HASH = { name: "My Project", description: "A project" }
1219
def setup
1320
@my_proj = { "person" => VALID_PROJECT_HASH }.to_json
@@ -38,6 +45,33 @@ def test_save_with_context
3845
assert_equal [ "can't be blank" ], p.errors.messages_for(:summary)
3946
end
4047

48+
def test_save_with_default_create_context
49+
p = DraftProject.new VALID_PROJECT_HASH.merge(name: "Invalid")
50+
assert_not p.save
51+
assert_equal [ "is invalid" ], p.errors.messages_for(:name)
52+
53+
p.name = "CREATE: Valid"
54+
assert p.save, "should save"
55+
assert_empty p.errors
56+
end
57+
58+
def test_save_with_default_update_context
59+
attributes = VALID_PROJECT_HASH.merge(id: 1, name: "CREATE: Created")
60+
61+
ActiveResource::HttpMock.respond_to do |mock|
62+
mock.get "/projects/1.json", {}, attributes.to_json
63+
mock.put "/projects/1.json", {}, attributes.to_json
64+
end
65+
66+
p = DraftProject.find(1)
67+
assert_not p.save
68+
assert_equal [ "is invalid" ], p.errors.messages_for(:name)
69+
70+
p.name = "UPDATE: Updated"
71+
assert p.save, "should save"
72+
assert_empty p.errors
73+
end
74+
4175
def test_save_bang_with_context
4276
p = new_project(summary: nil)
4377
assert_raise(ActiveResource::ResourceInvalid) { p.save!(context: :completed) }

0 commit comments

Comments
 (0)