Merge pull request #4790 from consul/custom_validations
Make it easier to customize validations
This commit is contained in:
@@ -1,5 +1,6 @@
|
||||
class ApplicationRecord < ActiveRecord::Base
|
||||
include HumanName
|
||||
include SkipValidation
|
||||
self.abstract_class = true
|
||||
|
||||
def self.sample(count = 1)
|
||||
|
||||
26
app/models/concerns/skip_validation.rb
Normal file
26
app/models/concerns/skip_validation.rb
Normal file
@@ -0,0 +1,26 @@
|
||||
module SkipValidation
|
||||
extend ActiveSupport::Concern
|
||||
|
||||
module ClassMethods
|
||||
def skip_validation(field, validator)
|
||||
validator_class = if validator.is_a?(Class)
|
||||
validator
|
||||
else
|
||||
"ActiveModel::Validations::#{validator.to_s.camelize}Validator".constantize
|
||||
end
|
||||
|
||||
_validators[field].reject! { |existing_validator| existing_validator.is_a?(validator_class) }
|
||||
|
||||
_validate_callbacks.each do |callback|
|
||||
if callback.raw_filter.is_a?(validator_class)
|
||||
callback.raw_filter.instance_variable_set("@attributes", callback.raw_filter.attributes - [field])
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def skip_translation_validation(field, validator)
|
||||
skip_validation(field, validator)
|
||||
translation_class.skip_validation(field, validator)
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -9,6 +9,10 @@ module Globalize
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
class Translation
|
||||
include SkipValidation
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
83
spec/models/skip_validation_spec.rb
Normal file
83
spec/models/skip_validation_spec.rb
Normal file
@@ -0,0 +1,83 @@
|
||||
require "rails_helper"
|
||||
|
||||
describe SkipValidation do
|
||||
describe ".skip_validation" do
|
||||
before do
|
||||
dummy_model = Class.new do
|
||||
include ActiveModel::Model
|
||||
include SkipValidation
|
||||
attr_accessor :title, :description
|
||||
|
||||
validates :title, presence: true, length: { in: 10..60, allow_nil: true }
|
||||
validates :description, presence: true
|
||||
end
|
||||
|
||||
stub_const("DummyModel", dummy_model)
|
||||
end
|
||||
|
||||
it "accepts validator classes as parameters" do
|
||||
DummyModel.skip_validation :title, ActiveModel::Validations::PresenceValidator
|
||||
|
||||
expect(DummyModel.new(title: nil, description: "Something")).to be_valid
|
||||
end
|
||||
|
||||
it "accepts symbols as parameters" do
|
||||
DummyModel.skip_validation :title, :presence
|
||||
|
||||
expect(DummyModel.new(title: nil, description: "Something")).to be_valid
|
||||
end
|
||||
|
||||
it "does not affect other attributes" do
|
||||
DummyModel.skip_validation :title, :presence
|
||||
|
||||
expect(DummyModel.new(title: nil, description: nil)).not_to be_valid
|
||||
end
|
||||
|
||||
it "does not affect other validations" do
|
||||
DummyModel.skip_validation :title, :presence
|
||||
|
||||
expect(DummyModel.new(title: "Short", description: "Something")).not_to be_valid
|
||||
end
|
||||
|
||||
it "works with validators other than presence" do
|
||||
DummyModel.skip_validation :title, :length
|
||||
|
||||
expect(DummyModel.new(title: "Short", description: "Something")).to be_valid
|
||||
expect(DummyModel.new(title: nil, description: "Something")).not_to be_valid
|
||||
end
|
||||
end
|
||||
|
||||
describe ".skip_translation_validation" do
|
||||
before do
|
||||
dummy_banner = Class.new(Banner) do
|
||||
def self.translation_class
|
||||
@translation_class ||= Class.new(Banner::Translation) { clear_validators! }
|
||||
end
|
||||
reflect_on_association(:translations).options[:class_name] = "DummyBanner::Translation"
|
||||
|
||||
clear_validators!
|
||||
validates_translation :title, presence: true
|
||||
validates_translation :description, presence: true
|
||||
end
|
||||
|
||||
stub_const("DummyBanner", dummy_banner)
|
||||
stub_const("DummyBanner::Translation", dummy_banner.translation_class)
|
||||
end
|
||||
|
||||
it "removes the validation from the translatable attribute" do
|
||||
DummyBanner.skip_translation_validation :title, :presence
|
||||
|
||||
custom_banner = DummyBanner.new(build(:banner).attributes.merge(title: nil))
|
||||
|
||||
expect { custom_banner.save! }.not_to raise_exception
|
||||
end
|
||||
|
||||
it "does not affect other validations" do
|
||||
DummyBanner.skip_translation_validation :title, :presence
|
||||
|
||||
custom_banner = DummyBanner.new(build(:banner).attributes.merge(description: nil))
|
||||
|
||||
expect { custom_banner.save! }.to raise_exception(ActiveRecord::RecordInvalid)
|
||||
end
|
||||
end
|
||||
end
|
||||
Reference in New Issue
Block a user