- A
- C
- V
实例公共方法
attribute_method?(attribute) 链接
如果 attribute
是一个属性方法,则返回 true
,否则返回 false
。
class Person
include ActiveModel::Validations
attr_accessor :name
end
User.attribute_method?(:name) # => true
User.attribute_method?(:age) # => false
源代码:显示 | 在 GitHub 上
# File activemodel/lib/active_model/validations.rb, line 282 def attribute_method?(attribute) method_defined?(attribute) end
clear_validators!() 链接
清除所有验证器和验证。
请注意,这将清除用于验证模型的任何内容,包括 validates_with
和 validate
方法。它会清除使用 validates_with
调用创建的验证器以及使用 validate
调用设置的回调。
class Person
include ActiveModel::Validations
validates_with MyValidator
validates_with OtherValidator, on: :create
validates_with StrictValidator, strict: true
validate :cannot_be_robot
def cannot_be_robot
errors.add(:base, 'A person cannot be a robot') if person_is_robot
end
end
Person.validators
# => [
# #<MyValidator:0x007fbff403e808 @options={}>,
# #<OtherValidator:0x007fbff403d930 @options={on: :create}>,
# #<StrictValidator:0x007fbff3204a30 @options={strict:true}>
# ]
如果运行 Person.clear_validators!
然后检查这个类有哪些验证器,你会得到
Person.validators # => []
此外,通过 validate :cannot_be_robot
设置的回调将被删除,因此
Person._validate_callbacks.empty? # => true
源代码:显示 | 在 GitHub 上
# File activemodel/lib/active_model/validations.rb, line 246 def clear_validators! reset_callbacks(:validate) _validators.clear end
validate(*args, &block) 链接
将验证方法或代码块添加到类中。当覆盖 validate
实例方法变得过于繁琐时,这很有用,此时你正在寻找对验证进行更具描述性的声明。
这可以通过指向方法的符号来完成
class Comment
include ActiveModel::Validations
validate :must_be_friends
def must_be_friends
errors.add(:base, 'Must be friends to leave a comment') unless commenter.friend_of?(commentee)
end
end
使用传递给要验证的当前记录的代码块
class Comment
include ActiveModel::Validations
validate do |comment|
comment.must_be_friends
end
def must_be_friends
errors.add(:base, 'Must be friends to leave a comment') unless commenter.friend_of?(commentee)
end
end
或者使用 self
指向要验证的当前记录的代码块
class Comment
include ActiveModel::Validations
validate do
errors.add(:base, 'Must be friends to leave a comment') unless commenter.friend_of?(commentee)
end
end
请注意,验证方法的返回值无关紧要。无法停止验证回调链。
选项
-
:on
- 指定此验证生效的上下文。默认情况下,在所有验证上下文中运行nil
。你可以传递一个符号或一个符号数组。(例如on: :create
或on: :custom_validation_context
或on: [:create, :custom_validation_context]
) -
:except_on
- 指定此验证无效的上下文。默认情况下,在所有验证上下文中运行nil
。你可以传递一个符号或一个符号数组。(例如except: :create
或except_on: :custom_validation_context
或except_on: [:create, :custom_validation_context]
) -
:if
- 指定要调用的方法、proc 或字符串,以确定是否应执行验证 (例如if: :allow_validation
,或if: Proc.new { |user| user.signup_step > 2 }
)。该方法、proc 或字符串应返回或评估为true
或false
值。 -
:unless
- 指定要调用的方法、proc 或字符串,以确定是否不应执行验证 (例如unless: :skip_validation
,或unless: Proc.new { |user| user.signup_step <= 2 }
)。该方法、proc 或字符串应返回或评估为true
或false
值。
注意:对同一方法多次调用 validate
会覆盖以前的定义。
源代码:显示 | 在 GitHub 上
# File activemodel/lib/active_model/validations.rb, line 160 def validate(*args, &block) options = args.extract_options! if args.all?(Symbol) options.each_key do |k| unless VALID_OPTIONS_FOR_VALIDATE.include?(k) raise ArgumentError.new("Unknown key: #{k.inspect}. Valid keys are: #{VALID_OPTIONS_FOR_VALIDATE.map(&:inspect).join(', ')}. Perhaps you meant to call `validates` instead of `validate`?") end end end if options.key?(:on) options = options.merge(if: [predicate_for_validation_context(options[:on]), *options[:if]]) end if options.key?(:except_on) options = options.dup options[:except_on] = Array(options[:except_on]) options[:unless] = [ ->(o) { (options[:except_on] & Array(o.validation_context)).any? }, *options[:unless] ] end set_callback(:validate, *args, options, &block) end
validates(*attributes) 链接
此方法是所有默认验证器和以 ‘Validator’ 结尾的任何自定义验证器类的快捷方式。请注意,Rails 默认验证器可以通过在特定类中创建自定义验证器类来覆盖,例如 PresenceValidator。
使用默认 Rails
验证器的示例
validates :username, absence: true
validates :terms, acceptance: true
validates :password, confirmation: true
validates :username, exclusion: { in: %w(admin superuser) }
validates :email, format: { with: /\A([^@\s]+)@((?:[-a-z0-9]+\.)+[a-z]{2,})\z/i, on: :create }
validates :age, inclusion: { in: 0..9 }
validates :first_name, length: { maximum: 30 }
validates :age, numericality: true
validates :username, presence: true
validates
方法的强大功能体现在对给定属性使用自定义验证器和默认验证器时。
class EmailValidator < ActiveModel::EachValidator
def validate_each(record, attribute, value)
record.errors.add attribute, (options[:message] || "is not an email") unless
/\A([^@\s]+)@((?:[-a-z0-9]+\.)+[a-z]{2,})\z/i.match?(value)
end
end
class Person
include ActiveModel::Validations
attr_accessor :name, :email
validates :name, presence: true, length: { maximum: 100 }
validates :email, presence: true, email: true
end
Validator
类也可以存在于正在验证的类中,允许根据需要包含自定义验证器模块。
class Film
include ActiveModel::Validations
class TitleValidator < ActiveModel::EachValidator
def validate_each(record, attribute, value)
record.errors.add attribute, "must start with 'the'" unless /\Athe/i.match?(value)
end
end
validates :name, title: true
end
此外,验证器类也可以位于另一个命名空间中,并且仍然可以在任何类中使用。
validates :name, :'film/title' => true
验证器哈希还可以以快捷形式处理正则表达式、范围、数组和字符串。
validates :email, format: /@/
validates :role, inclusion: %w(admin contributor)
validates :password, length: 6..20
在使用快捷形式时,范围和数组作为 options[:in]
传递给你的验证器初始化器,而其他类型,包括正则表达式和字符串,则作为 options[:with]
传递。
还有一些选项可与验证器一起使用
-
:on
- 指定此验证生效的上下文。默认情况下,在所有验证上下文中运行nil
。你可以传递一个符号或一个符号数组。(例如on: :create
或on: :custom_validation_context
或on: [:create, :custom_validation_context]
) -
:except_on
- 指定此验证无效的上下文。默认情况下,在所有验证上下文中运行nil
。你可以传递一个符号或一个符号数组。(例如except: :create
或except_on: :custom_validation_context
或except_on: [:create, :custom_validation_context]
) -
:if
- 指定要调用的方法、proc 或字符串,以确定是否应执行验证 (例如if: :allow_validation
,或if: Proc.new { |user| user.signup_step > 2 }
)。该方法、proc 或字符串应返回或评估为true
或false
值。 -
:unless
- 指定要调用的方法、proc 或字符串,以确定是否不应执行验证 (例如unless: :skip_validation
,或unless: Proc.new { |user| user.signup_step <= 2 }
)。该方法、proc 或字符串应返回或评估为true
或false
值。 -
:allow_nil
- 如果属性为nil
,则跳过验证。 -
:allow_blank
- 如果属性为空,则跳过验证。 -
:strict
- 如果:strict
选项设置为 true,则会引发ActiveModel::StrictValidationFailed
,而不是添加错误。:strict
选项也可以设置为任何其他异常。
示例
validates :password, presence: true, confirmation: true, if: :password_required?
validates :token, length: { is: 24 }, strict: TokenLengthException
最后,选项 :if
、:unless
、:on
、:allow_blank
、:allow_nil
、:strict
和 :message
可以作为哈希传递给一个特定的验证器
validates :password, presence: { if: :password_required?, message: 'is forgotten.' }, confirmation: true
源代码:显示 | 在 GitHub 上
# File activemodel/lib/active_model/validations/validates.rb, line 111 def validates(*attributes) defaults = attributes.extract_options!.dup validations = defaults.slice!(*_validates_default_keys) raise ArgumentError, "You need to supply at least one attribute" if attributes.empty? raise ArgumentError, "You need to supply at least one validation" if validations.empty? defaults[:attributes] = attributes validations.each do |key, options| key = "#{key.to_s.camelize}Validator" begin validator = const_get(key) rescue NameError raise ArgumentError, "Unknown validator: '#{key}'" end next unless options validates_with(validator, defaults.merge(_parse_validates_options(options))) end end
validates!(*attributes) 链接
此方法用于定义无法由最终用户纠正的验证,并且被认为是例外情况。因此,使用感叹号或将 :strict
选项设置为 true
定义的每个验证器在验证失败时总是会引发 ActiveModel::StrictValidationFailed
,而不是添加错误。有关验证本身的更多信息,请参阅 validates
。
class Person
include ActiveModel::Validations
attr_accessor :name
validates! :name, presence: true
end
person = Person.new
person.name = ''
person.valid?
# => ActiveModel::StrictValidationFailed: Name can't be blank
源代码:显示 | 在 GitHub 上
# File activemodel/lib/active_model/validations/validates.rb, line 153 def validates!(*attributes) options = attributes.extract_options! options[:strict] = true validates(*(attributes << options)) end
validates_each(*attr_names, &block) 链接
根据代码块验证每个属性。
class Person
include ActiveModel::Validations
attr_accessor :first_name, :last_name
validates_each :first_name, :last_name, allow_blank: true do |record, attr, value|
record.errors.add attr, "starts with z." if value.start_with?("z")
end
end
选项
-
:on
- 指定此验证生效的上下文。默认情况下,在所有验证上下文中运行nil
。你可以传递一个符号或一个符号数组。(例如on: :create
或on: :custom_validation_context
或on: [:create, :custom_validation_context]
) -
:except_on
- 指定此验证无效的上下文。默认情况下,在所有验证上下文中运行nil
。你可以传递一个符号或一个符号数组。(例如except: :create
或except_on: :custom_validation_context
或except_on: [:create, :custom_validation_context]
) -
:allow_nil
- 如果属性为nil
,则跳过验证。 -
:allow_blank
- 如果属性为空,则跳过验证。 -
:if
- 指定要调用的方法、proc 或字符串,以确定是否应执行验证 (例如if: :allow_validation
,或if: Proc.new { |user| user.signup_step > 2 }
)。该方法、proc 或字符串应返回或评估为true
或false
值。 -
:unless
- 指定要调用的方法、proc 或字符串,以确定是否不应执行验证 (例如unless: :skip_validation
,或unless: Proc.new { |user| user.signup_step <= 2 }
)。该方法、proc 或字符串应返回或评估为true
或false
值。
源代码:显示 | 在 GitHub 上
# File activemodel/lib/active_model/validations.rb, line 88 def validates_each(*attr_names, &block) validates_with BlockValidator, _merge_attributes(attr_names), &block end
validates_with(*args, &block) 链接
将记录传递给指定的类或多个类,并允许它们根据更复杂的条件添加错误。
class Person
include ActiveModel::Validations
validates_with MyValidator
end
class MyValidator < ActiveModel::Validator
def validate(record)
if some_complex_logic
record.errors.add :base, 'This record is invalid'
end
end
private
def some_complex_logic
# ...
end
end
你也可以像这样传递多个类
class Person
include ActiveModel::Validations
validates_with MyValidator, MyOtherValidator, on: :create
end
validates_with
没有默认的错误消息。你必须在验证器类中手动将错误添加到记录的错误集合中。
要实现 validate 方法,你必须定义一个 record
参数,它是要验证的记录。
配置选项
-
:on
- 指定此验证生效的上下文。默认情况下,在所有验证上下文中运行nil
。你可以传递一个符号或一个符号数组。(例如on: :create
或on: :custom_validation_context
或on: [:create, :custom_validation_context]
) -
:if
- 指定要调用的方法、proc 或字符串,以确定是否应执行验证 (例如if: :allow_validation
,或if: Proc.new { |user| user.signup_step > 2 }
)。该方法、proc 或字符串应返回或评估为true
或false
值。 -
:unless
- 指定要调用的方法、proc 或字符串,以确定是否不应执行验证 (例如unless: :skip_validation
,或unless: Proc.new { |user| user.signup_step <= 2 }
)。该方法、proc 或字符串应返回或评估为true
或false
值。 -
:strict
- 指定验证是否应严格执行。有关更多信息,请参阅ActiveModel::Validations#validates!
。
如果你传递任何其他配置选项,它们将传递给类,并作为 options
提供。
class Person
include ActiveModel::Validations
validates_with MyValidator, my_custom_key: 'my custom value'
end
class MyValidator < ActiveModel::Validator
def validate(record)
options[:my_custom_key] # => "my custom value"
end
end
源代码:显示 | 在 GitHub 上
# File activemodel/lib/active_model/validations/with.rb, line 88 def validates_with(*args, &block) options = args.extract_options! options[:class] = self args.each do |klass| validator = klass.new(options.dup, &block) if validator.respond_to?(:attributes) && !validator.attributes.empty? validator.attributes.each do |attribute| _validators[attribute.to_sym] << validator end else _validators[nil] << validator end validate(validator, options) end end
validators() 链接
列出所有用于使用 validates_with
方法验证模型的验证器。
class Person
include ActiveModel::Validations
validates_with MyValidator
validates_with OtherValidator, on: :create
validates_with StrictValidator, strict: true
end
Person.validators
# => [
# #<MyValidator:0x007fbff403e808 @options={}>,
# #<OtherValidator:0x007fbff403d930 @options={on: :create}>,
# #<StrictValidator:0x007fbff3204a30 @options={strict:true}>
# ]
源代码:显示 | 在 GitHub 上
# File activemodel/lib/active_model/validations.rb, line 204 def validators _validators.values.flatten.uniq end
validators_on(*attributes) 链接
列出所有用于验证特定属性的验证器。
class Person
include ActiveModel::Validations
attr_accessor :name, :age
validates_presence_of :name
validates_inclusion_of :age, in: 0..99
end
Person.validators_on(:name)
# => [
# #<ActiveModel::Validations::PresenceValidator:0x007fe604914e60 @attributes=[:name], @options={}>,
# ]
源代码:显示 | 在 GitHub 上
# File activemodel/lib/active_model/validations.rb, line 266 def validators_on(*attributes) attributes.flat_map do |attribute| _validators[attribute.to_sym] end end