Class: ActiveRecord::Validations::DatabaseConstraintsValidator
- Inherits:
-
ActiveModel::EachValidator
- Object
- ActiveModel::EachValidator
- ActiveRecord::Validations::DatabaseConstraintsValidator
- Defined in:
- lib/active_record/validations/database_constraints.rb
Constant Summary collapse
- TYPE_LIMITS =
{ char: { validator: ActiveModel::Validations::LengthValidator }, varchar: { validator: ActiveModel::Validations::LengthValidator }, varbinary: { validator: ActiveModel::Validations::BytesizeValidator }, tinytext: { validator: ActiveModel::Validations::BytesizeValidator, default_maximum: 2 ** 8 - 1 }, text: { validator: ActiveModel::Validations::BytesizeValidator, default_maximum: 2 ** 16 - 1 }, mediumtext: { validator: ActiveModel::Validations::BytesizeValidator, default_maximum: 2 ** 24 - 1 }, longtext: { validator: ActiveModel::Validations::BytesizeValidator, default_maximum: 2 ** 32 - 1 }, tinyblob: { validator: ActiveModel::Validations::BytesizeValidator, default_maximum: 2 ** 8 - 1 }, blob: { validator: ActiveModel::Validations::BytesizeValidator, default_maximum: 2 ** 16 - 1 }, mediumblob: { validator: ActiveModel::Validations::BytesizeValidator, default_maximum: 2 ** 24 - 1 }, longblob: { validator: ActiveModel::Validations::BytesizeValidator, default_maximum: 2 ** 32 - 1 }, }
- VALID_CONSTRAINTS =
Set[:size, :basic_multilingual_plane, :not_null, :range]
Instance Attribute Summary collapse
-
#constraints ⇒ Object
readonly
Returns the value of attribute constraints.
Instance Method Summary collapse
- #attribute_validators(klass, attribute) ⇒ Object
- #basic_multilingual_plane_validator(klass, column) ⇒ Object
- #check_validity! ⇒ Object
-
#initialize(options = {}) ⇒ DatabaseConstraintsValidator
constructor
A new instance of DatabaseConstraintsValidator.
- #not_null_validator(klass, column) ⇒ Object
- #range_validator(klass, column) ⇒ Object
- #size_validator(klass, column) ⇒ Object
- #validate_each(record, attribute, value) ⇒ Object
Constructor Details
#initialize(options = {}) ⇒ DatabaseConstraintsValidator
Returns a new instance of DatabaseConstraintsValidator.
28 29 30 31 32 |
# File 'lib/active_record/validations/database_constraints.rb', line 28 def initialize( = {}) @constraints = Set.new(Array.wrap([:in]) + Array.wrap([:with])) @constraint_validators = {} super end |
Instance Attribute Details
#constraints ⇒ Object (readonly)
Returns the value of attribute constraints.
24 25 26 |
# File 'lib/active_record/validations/database_constraints.rb', line 24 def constraints @constraints end |
Instance Method Details
#attribute_validators(klass, attribute) ⇒ Object
92 93 94 95 96 97 98 99 100 101 102 103 |
# File 'lib/active_record/validations/database_constraints.rb', line 92 def attribute_validators(klass, attribute) @constraint_validators[attribute] ||= begin column = klass.columns_hash[attribute.to_s] or raise ArgumentError.new("Model #{self.class.name} does not have column #{column_name}!") [ not_null_validator(klass, column), size_validator(klass, column), basic_multilingual_plane_validator(klass, column), range_validator(klass, column), ].compact end end |
#basic_multilingual_plane_validator(klass, column) ⇒ Object
86 87 88 89 90 |
# File 'lib/active_record/validations/database_constraints.rb', line 86 def basic_multilingual_plane_validator(klass, column) return unless constraints.include?(:basic_multilingual_plane) return unless column.text? && column.collation =~ /\Autf8(?:mb3)?_/ ActiveModel::Validations::BasicMultilingualPlaneValidator.new(attributes: [column.name.to_sym], class: klass) end |
#check_validity! ⇒ Object
34 35 36 37 38 39 |
# File 'lib/active_record/validations/database_constraints.rb', line 34 def check_validity! invalid_constraints = constraints - VALID_CONSTRAINTS raise ArgumentError, "You have to specify what constraints to validate for." if constraints.empty? raise ArgumentError, "#{invalid_constraints.map(&:inspect).join(',')} is not a valid constraint." unless invalid_constraints.empty? end |
#not_null_validator(klass, column) ⇒ Object
41 42 43 44 45 46 |
# File 'lib/active_record/validations/database_constraints.rb', line 41 def not_null_validator(klass, column) return unless constraints.include?(:not_null) return if column.null ActiveModel::Validations::NotNullValidator.new(attributes: [column.name.to_sym], class: klass) end |
#range_validator(klass, column) ⇒ Object
63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 |
# File 'lib/active_record/validations/database_constraints.rb', line 63 def range_validator(klass, column) return unless constraints.include?(:range) return unless column.number? unsigned = column.sql_type =~ / unsigned\z/ case column.type when :decimal args = { attributes: [column.name.to_sym], class: klass, allow_nil: true } args[:less_than] = maximum = 10 ** (column.precision - column.scale) if unsigned args[:greater_than_or_equal_to] = 0 else args[:greater_than] = 0 - maximum end ActiveModel::Validations::NumericalityValidator.new(args) when :integer maximum = unsigned ? 1 << (column.limit * 8) : 1 << (column.limit * 8 - 1) minimum = unsigned ? 0 : 0 - maximum ActiveModel::Validations::NumericalityValidator.new(attributes: [column.name.to_sym], class: klass, greater_than_or_equal_to: minimum, less_than: maximum, allow_nil: true, only_integer: true) end end |
#size_validator(klass, column) ⇒ Object
48 49 50 51 52 53 54 55 56 57 58 59 60 61 |
# File 'lib/active_record/validations/database_constraints.rb', line 48 def size_validator(klass, column) return unless constraints.include?(:size) return unless column.text? || column.binary? column_type = column.sql_type.sub(/\(.*\z/, '').gsub(/\s/, '_').to_sym type_limit = TYPE_LIMITS.fetch(column_type, {}) validator_class = type_limit[:validator] maximum = column.limit || type_limit[:default_maximum] encoding = column.text? ? determine_encoding(column) : nil if validator_class && maximum validator_class.new(attributes: [column.name.to_sym], class: klass, maximum: maximum, encoding: encoding) end end |
#validate_each(record, attribute, value) ⇒ Object
105 106 107 108 109 |
# File 'lib/active_record/validations/database_constraints.rb', line 105 def validate_each(record, attribute, value) attribute_validators(record.class, attribute).each do |validator| validator.validate_each(record, attribute, value) end end |