• 跟着大师混没错的💪

  • 还清晰的记得这个问题抛出来的时候,我答非所问,失了方寸去解答时的样子。回来之后,花了一段时间才真正去解决这个问题。

    实现代码

    module Validate
    
      VALIDATE_RULES = {
        :presence => {
          :condition => /^\S+$/,
          :message => "%{name} cannot be blank"
        },
        :maxlength => {
         :condition => -> (attr, val){ attr.to_s.length <= val },
         :message => "%{name} max length is %{val}"
        }
      }
    
      def self.included(base)
        class << base; attr_accessor :defined_validates; end
        base.defined_validates = {}
        base.send(:include, InstanceMethods)
        base.extend ClassMethods
      end
    
      # def self.extended(base)
      #   class << base; attr_accessor :defined_validates; end
      #   base.defined_validates = {}
      #   base.extend ClassMethods
      #   base.send(:include, InstanceMethods)
      # end
    
      module ClassMethods
        def inherited(base)
          base.defined_validates = defined_validates.deep_dup
          super
        end
    
        def validates(name, options)
          defined_validates[name.to_s] = options
        end
      end
    
      module InstanceMethods
        def valid?
          @error_messages = {}
    
          self.class.defined_validates.each do |name, conditon|
            conditon.each do |rule, value|
              next unless value
              rule = VALIDATE_RULES[rule]
              cond = rule[:condition]
              attr_value = send(name)
    
              valid = case cond
                when Regexp
                  cond === attr_value
                when Proc
                  cond.(attr_value, value)
              end
    
              @error_messages[name] = rule[:message] % {
                name: name,
                val: value
              } unless valid
            end
          end
    
          @error_messages.size == 0
        end
    
        def error_messages
          @error_messages || {}
        end
      end
    end
    
    class User
      include Validate
      # extend Validate
      attr_accessor :name
      validates :name, :presence => true, :maxlength => 5
    
      def self.create(options = {})
        user = new.tap do |_|
          options.each do |attr, value|
            _.send("#{attr}=", value)
          end
        end
      end
    end
    
    user = User.create(:name => nil)
    user.valid?
    user.error_messages
    

    思路:

    不继承于任何类,所以只能用include或extend的方法。这里写一个Validate的module,这样任何类只要include或extend它就有了validates的功能了。 实现: validates是用来验证一个类的实例的,所以我们只要把validates的验证条件存在类的变量就可以了

    def validates(name, options)
      defined_validates[name.to_s] = options
    end
    

    这里有个类变量叫defined_validates 通过钩子方法把我写好的方法变成了对应类的类方法和实例方法

    def self.included(base)
      class << base; attr_accessor :defined_validates; end
      base.defined_validates = {}
      base.send(:include, InstanceMethods)
      base.extend ClassMethods
    end
    

    我们把我们定义的InstanceMethods中的所有方法include了,成了实例方法 定义的ClassMethods中的所有方法extend了,成了类方法

    class << base; attr_accessor :defined_validates; end
        base.defined_validates = {}
    

    这个只要是定义类变量,就是@@defined_validates,并且初始化,后面在User中我们的validates其实就存在这个变量中的 我们在使用valid的时候,再进行判断就可以了,然后再把判断结果输出到实例变量@error_messages

    无二是个好公司,自己还有很长的路要走。

  • 投了 简历写的太low了吧 没有面试机会😅

  • 郑州还不错,有4 5家ruby公司呢😀

  • 好嘞,我投递一下。😜

  • 好的,已投递,您看一下。

  • 想问一下可以远程进行面试吗?现在人在北京。

  • 寫 RoR 的人要求特別高? at 2018年03月01日

    会。

  • 这家公司很棒!

  • 2017 技术达人年度总结 at 2018年02月06日

    最后, 别忘记关注 "技术达人李亚飞" 公众号, 推荐给你的朋友们反思与成长.

寻找一份北京的ruby工作机会