Rails 中实现自定义的 Validation

October 17, 2018 20:06
访问量:165
摘要:能够根据项目的需求来自定义 validation

我们先要尝试归纳出我们需要的或者说已知的内容——「一个ActiveModel Validator 能实现什么和做到什么?」

  1. 可以通过validates 类方法来验证需要验证的字段
  2. 具有Valid? 方法,可以返回布尔值
  1. app/model/post.rb,调用 validates 类方法。
class Post < Base
  attr_accessor :title:content
  validates :title:contentPresence: true

  def initialize(title, content)
    @title = title
    @content = content
  end
end
  1. 在 app/models/concerns/base.rb 类中添加:
require('validator')
require('validators/presence')

class Base
  class << self
    @@validators = []

    def validates(*attributes)
      validators = extract_option!(attributes)
      validators.each do |validator, option|
        attributes.each do |attr_key|
          key = "#{validator.to_s}Validator"
          # const_get获得validate子类的class名称
          @@validators << Object.const_get(key).new(attr_key, option)
        end
      end
    end

    def extract_option!(attributes)
      if attributes.last.is_a?(Hash)
        attributes.pop
      else
        {}
      end
    end

    def validators
      @@validators
    end
  end

  def valid?
    self.class.validators.each do |validator|
      return false unless validator.valid?(self)
    end
    true
  end
end

3.app/models/concerns/validator.rb 中

class Validator
  attr_accessor :attr_name:option

  def initialize(attr_name, option)
    @attr_name = attr_name
    @option = option
  end

  def valid?(obj)
    raise NotImplementError, 'You should override this method in subclass'
  end
end

4.app/models/concerns/validators/presence.rb 中

class PresenceValidator < Validator
  def valid?(obj)
    value = obj.send(@attr_name)
    result = value.respond_to?(:empty?) ? !value.empty? : !!value
    @option ? result : !result
  end
end

参考文章

评论

暂无相关评论,快来抢占沙发吧!
评论框离家出走了,点击找回!
昵称
邮箱
网站
昵称
邮箱
网站