【问题标题】:How to create activerecord style validations outside of activerecord?如何在 activerecord 之外创建 activerecord 样式验证?
【发布时间】:2009-04-22 06:51:00
【问题描述】:

我正在为我公司编写的软件开发一个测试框架。我们的产品是基于网络的,在我运行 RESTful 请求后,我想处理结果。我希望能够在每个命令类中进行 activerecord 类型验证,以便在运行后自动针对所有“验证”测试结果。但是,我不知道该怎么做。我的代码看起来像这样(简化以显示重要部分)。

class CodesecureCommand
  def execute
    result = RestClient.post("http://#{codesecure.host_name_port}#{path}", post_data)

    return parse(result) #parse simple returns a Hpricot document
  end
end

class RunScan < CodesecureCommand

  #What I have now
  #I have to override the execute function so that it calls the local success method
  #to see if it failed or not.
  def execute()
    result = super()

    if success(result)
      return true
    else
    end

  end

  def success(result)
    result.search('div.transaction-message') do |message|
      if message.innerHTML.scan(/Configure abuse setting for domain users successfully\./).length == 1
        return true
      end
    end
  end



  #What I would like is to be able to call execute (without having to override it).
  #then after it runs it calls back to this class to check

  #if the regex matches the command was successful and returns true
  test_success /regex/

  #if test_success fails then these are called
  #the idea being that I can use the regex to identify errors that happened then
  #report them to the user
  identify_error /regex/, "message"
  identify_error /regex/, "message"
  end
end

我想要的是,在调用执行方法之后,会自动调用 test_success 和 identify_error,就像在 activerecord 中的验证一样。谁能告诉我该怎么做?谢谢

【问题讨论】:

    标签: ruby-on-rails ruby activerecord


    【解决方案1】:

    没有过多查看您的代码,以下是我对实现验证类方法的看法:

    module Validations
      def self.included(base)
        base.extend ClassMethods
      end
    
      def validate
        errors.clear
        self.class.validations.each {|validation| validation.call(self) }
      end
    
      def valid?
        validate
        errors.blank?
      end
    
      def errors
        @errors ||= {}
      end
    
      module ClassMethods
        def validations
          @validations ||= []
        end
    
        def validates_presence_of(*attributes)
          validates_attributes(*attributes) do |instance, attribute, value, options|
            instance.errors[attribute] = "cant't be blank" if value.blank?
          end
        end
    
        def validates_format_of(*attributes)
          validates_attributes(*attributes) do |instance, attribute, value, options|
            instance.errors[attribute] = "is invalid" unless value =~ options[:with]
          end
        end
    
        def validates_attributes(*attributes, &proc)
          options = attributes.extract_options!
    
          validations << Proc.new { |instance|
            attributes.each {|attribute|
              proc.call(instance, attribute, instance.__send__(attribute), options)
            }
          }
        end
      end
    end
    

    它假定 ActiveSupport 存在,它位于 Rails 环境中。您可能希望使用instance.errors[attribute] &lt;&lt; "the message" 扩展它以允许每个属性出现多个错误,但我省略了这样的晦涩之处,以使这个简短的示例尽可能简单。

    这是一个简短的用法示例:

    class MyClass
      include Validations
    
      attr_accessor :foo
      validates_presence_of :foo
      validates_format_of :foo, :with => /^[a-z]+$/
    end
    
    a = MyClass.new
    puts a.valid?
    # => false
    
    a.foo = "letters"
    puts a.valid?
    # => true
    
    a.foo = "Oh crap$(!)*#"
    puts a.valid?
    # => false
    

    【讨论】:

    • 感谢我正在寻找的答案。一个问题,它需要什么 ActiveSupport?谢谢。
    • 它使用Hash#blank?(在valid?方法中)。不过就这些了,呵呵。放弃 active_support 应该不会太难。我只是假设它已经在那里,因为无论如何你都在 rails 上下文中。
    • 它也使用 Array#extract_options!,但这很简单,可以复制/提取。
    • 是的,本来可以是options = attributes.last.is_a?(Hash) ? attributes.pop : {}
    【解决方案2】:

    你想要Validatablesudo gem install validatable

    class Person
      include Validatable
      validates_presence_of :name
      attr_accessor :name
    end
    

    此外,Validatable 不依赖于 ActiveSupport。

    【讨论】:

    • 我更喜欢这个答案。更干燥,更少依赖。
    猜你喜欢
    • 1970-01-01
    • 2011-01-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-09-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多