From 830b7041f213669c3877edf459ef83a31c84cc4d Mon Sep 17 00:00:00 2001 From: Lucas Mazza Date: Fri, 20 Feb 2015 15:50:49 -0200 Subject: Move the `validate!` method to `ActiveModel::Validations`. --- activemodel/lib/active_model/locale/en.yml | 1 + activemodel/lib/active_model/validations.rb | 33 +++++++++++++++++++++++++++++ activemodel/test/cases/validations_test.rb | 19 +++++++++++++++++ 3 files changed, 53 insertions(+) (limited to 'activemodel') diff --git a/activemodel/lib/active_model/locale/en.yml b/activemodel/lib/active_model/locale/en.yml index b11c8f53b4..061e35dd1e 100644 --- a/activemodel/lib/active_model/locale/en.yml +++ b/activemodel/lib/active_model/locale/en.yml @@ -6,6 +6,7 @@ en: # The values :model, :attribute and :value are always available for interpolation # The value :count is available when applicable. Can be used for pluralization. messages: + model_invalid: "Validation failed: %{errors}" inclusion: "is not included in the list" exclusion: "is reserved" invalid: "is invalid" diff --git a/activemodel/lib/active_model/validations.rb b/activemodel/lib/active_model/validations.rb index 6a2668b8f7..176d4c0607 100644 --- a/activemodel/lib/active_model/validations.rb +++ b/activemodel/lib/active_model/validations.rb @@ -371,6 +371,15 @@ module ActiveModel !valid?(context) end + # Runs all the validations within the specified context. Returns +true+ if + # no errors are found, raises +ValidationError+ otherwise. + # + # Validations with no :on option will run no matter the context. Validations with + # some :on option will only run in the specified context. + def validate!(context = nil) + valid?(context) || raise_validation_error + end + # Hook method defining how an attribute value should be retrieved. By default # this is assumed to be an instance named after the attribute. Override this # method in subclasses should you need to retrieve the value for a given @@ -395,6 +404,30 @@ module ActiveModel _run_validate_callbacks errors.empty? end + + def raise_validation_error + raise(ValidationError.new(self)) + end + end + + # = Active Model ValidationError + # + # Raised by validate! when the model is invalid. Use the + # +model+ method to retrieve the record which did not validate. + # + # begin + # complex_operation_that_internally_calls_validate! + # rescue ActiveModel::ValidationError => invalid + # puts invalid.model.errors + # end + class ValidationError < StandardError + attr_reader :model + + def initialize(model) + @model = model + errors = @model.errors.full_messages.join(", ") + super(I18n.t(:"#{@model.class.i18n_scope}.errors.messages.model_invalid", errors: errors, default: :"errors.messages.model_invalid")) + end end end diff --git a/activemodel/test/cases/validations_test.rb b/activemodel/test/cases/validations_test.rb index dc125bc884..f0317ad219 100644 --- a/activemodel/test/cases/validations_test.rb +++ b/activemodel/test/cases/validations_test.rb @@ -351,6 +351,25 @@ class ValidationsTest < ActiveModel::TestCase assert_not_empty topic.errors end + def test_validate_with_bang + Topic.validates :title, presence: true + + assert_raise(ActiveModel::ValidationError) do + Topic.new.validate! + end + end + + def test_validate_with_bang_and_context + Topic.validates :title, presence: true, on: :context + + assert_raise(ActiveModel::ValidationError) do + Topic.new.validate!(:context) + end + + t = Topic.new(title: "Valid title") + assert t.validate!(:context) + end + def test_strict_validation_in_validates Topic.validates :title, strict: true, presence: true assert_raises ActiveModel::StrictValidationFailed do -- cgit v1.2.3