Validations
- validate 自定义验证方法 (不需要属性,也不需要校验器;直接做校验)
- class Invoice < ApplicationRecord
- validate :active_customer, on: :create
- def active_customer
- errors.add(:customer_id, "is not active") unless customer.active?
- end
- end
复制代码
- validates 和 validates! (需要属性,也需要校验器;间接做校验)
- class Person < ApplicationRecord
- validates :name, presence: true #校验器是PresenceValidator
- end
- #校验器PresenceValidator
- class PresenceValidator < ActiveModel::EachValidator
- def validate_each(record, attribute, value)
- record.errors.add attribute, "can't be blank" if value.blank?
- end
- end
-
复制代码
- validates_each (需要属性,不需要校验器;直接做校验)
- class Person < ApplicationRecord
- validates_each :name, :surname do |record, attr, value|
- record.errors.add(attr, 'must start with upper case') if value =~ /\A[[:lower:]]/
- end
- end
复制代码
- validates_with 验证交给其他类做验证 (不需要属性,需要校验器;作用于所有对象,间接做校验)
- class GoodnessValidator < ActiveModel::Validator
- def validate(record)
- # options = { :fields => [:first_name, :last_name] }
- # options = { :abc => [:first_name, :last_name] }
- if options[:fields].any?{|field| record.send(field) == "Evil" }
- record.errors[:base] << "This person is evil"
- end
- end
- end
-
- class Person < ApplicationRecord
- #fields是options哈希的一个key,也可以是别的例如 abc: [:first_name, :last_name]
- validates_with GoodnessValidator, fields: [:first_name, :last_name]
- end
复制代码 履历:牢记 validate 发生在 save 之前,如果你喜欢用 before_save 之类的举行查验,记得加上 return false 或者改变习惯,用 validate :validate_method 雷同写法举行校验。
Validator
- 自定义的验证类继承自 ActiveModel::Validator,必须实现 validate 方法,其参数是要验证的记录,然后验证这个记录是否有效。自定义的验证类通过 validates_with 方法调用
- class MyValidator < ActiveModel::Validator
- def validate(record)
- unless record.name.starts_with? 'X'
- record.errors[:name] << 'Need a name starting with X please!'
- end
- end
- end
-
- class Person
- include ActiveModel::Validations
- validates_with MyValidator
- end
复制代码
- 自定义的验证类中验证单个属性,最简单的方法是继承 ActiveModel::EachValidator 类。此时,自定义的验证类必须实现 validate_each 方法。这个方法继承三个参数:记录、属性名和属性值。它们分别对应模型实例、要验证的属性及其值。
- class EmailValidator < ActiveModel::EachValidator
- def validate_each(record, attribute, value)
- unless value =~ /\A([^@\s]+)@((?:[-a-z0-9]+\.)+[a-z]{2,})\z/i
- record.errors[attribute] << (options[:message] || "is not an email")
- end
- end
- end
-
- class Person < ApplicationRecord
- # presence: true为内置的验证类,email: true为自定义的验证类,可以同时使用
- # email: true 对应的验证类必须是EmailValidator, title:true 对应的验证类必须是TitlelValidator
- validates :email, presence: true, email: true
- end
复制代码
- 自定义验证方法
自定义验证方法必须使用类方法 validate 注册,传入自定义验证方法名的符号情势。
这个类方法可以继承多个符号,自定义的验证方法会按照注册的顺序执行。
可以设置 n 选项,指定什么时间验证。 n 的可选值为 :create 和 :update。
- class Invoice < ApplicationRecord
- validate :expiration_date_cannot_be_in_the_past,
- :discount_cannot_be_greater_than_total_value
-
- def expiration_date_cannot_be_in_the_past
- if expiration_date.present? && expiration_date < Date.today
- errors.add(:expiration_date, "can't be in the past")
- end
- end
-
- def discount_cannot_be_greater_than_total_value
- if discount > total_value
- errors.add(:discount, "can't be greater than total value")
- end
- end
- end
复制代码
- valid? 校验是否通过,只有一个判断规则:当前 record 对象的 errors 值是否为空 errors.empty?
以是自己写校验方法或者校验器的时间,请记得设置 errors 的值。
Concern实现
- # app/models/concerns/custom_validatable.rb
- module CustomValidatable
- extend ActiveSupport::Concern
- included do
- validate :custom_validate
- end
- def validate_custom_fields(fields)
- CustomValidation.order(:position).each do |validation|
- regex = Regexp.new(validation.regex)
- fields.each do |field|
- value = send(field)
- unless value.match?(regex)
- errors.add(field, validation.error_message)
- end
- end
- end
- end
- end
复制代码- # app/models/issue.rb
- include CustomValidatable
- def custom_validate
- validate_custom_fields(['subject', 'description'])
- end
复制代码 validates_with实现
- class WxMsgSecValidator < ActiveModel::Validator
- # scene: 1 scene_profile 资料, 2 scene_comment 评论, 3 scene_post 论坛, 4 scene_log 社交日志
- def validate(record)
- if options[:fields].select { |field| record.send("#{field}_changed?") }.present?
- case record.class.name
- when 'YouKe'
- @you_ke = record
- else
- @you_ke = record.you_ke
- end
- scene_hash = { desc: 2, content: 2 }
- @you_ke = YouKe.where(is_robot: false).first if @you_ke&.is_robot?
- open_id = @you_ke&.klly? ? @you_ke&.open_id : @you_ke&.wmh_open_id
- return record.errors[:base] << '账号openid不存在' if open_id.nil?
- options[:fields].select { |field| record.send("#{field}_changed?") }.each do |field|
- if record.send(field).present?
- is_deny = @you_ke.klly? ? !Weixin.msg_check(scene_hash[field], open_id, record.send(field)) : !WmhWeixin.msg_check(scene_hash[field], open_id, record.send(field))
- record.errors.add(:base, '输入涉嫌违规') if is_deny
- end
- end
- end
- end
- end
复制代码- # app/models/issue.rb
- include ActiveModel::Validations
- validates_with WxMsgSecValidator, fields: %i[content]
复制代码 免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。 |