Rails:如何验证我放入lib /目录的代码?

时间:2010-05-08 21:01:48

标签: ruby-on-rails ruby activerecord

在我为Rails 2.3.5的lib /目录放入的代码中找到合适的混合方法时遇到了一些困难。

我有几种需要手机验证的型号。我至少有三个使用相同代码的模型,所以我想保持DRY并将其移到lib /目录中。我曾经在每个模型中都有这样的代码:

validate :phone_is_valid

然后我在模型中有一个phone_is_valid方法:

protected
def phone_is_valid
  # process a bunch of logic
  errors.add_to_base("invalid phone") if validation failed
end 

我将这段代码移到lib / phones /中,在lib / phones中我有lib / phones / phone_validation.rb,在那里我复制粘贴了phone_is_valid方法。

我的问题是,我现在如何将它混合到我的所有模型中?我的验证:phone_is_valid方法是保持不变还是更改?我想确保errors.add_to_base方法继续像以前一样运行,同时保持一切干燥。显然以下内容不起作用:

validate :Phones::PhoneValidation::phone_is_valid(number)

我还在lib / phones /中创建了另一个名为lib / phones / phone_normalize.rb的文件。同样,许多模型需要用户输入的值进行标准化。含义转(555)222-1212至5552221212或类似的东西。我可以通过调用Phones :: Phone_Normalize :: normalize_method(number)来调用它吗?

我想我对以下内容感到困惑:

  • 如何使用lib目录验证需要访问特定验证方法的多个模型
  • 如何将lib目录用于返回值的常用方法

2 个答案:

答案 0 :(得分:2)

class Profile < ActiveRecord::Base
  include Phones::PhoneValidation
  validate_phone_is_valid
end

如果您想将它用于许多模型,那么您可能会将验证直接修补到ActiveRecord中:

module ActiveRecord
  module Validations
    module ClassMethods
      def validates_photo(*attr_names)
        # ....
      end
    end
  end
end

答案 1 :(得分:1)

一点元编程魔法?

module Phones

  def self.included(base)
    base.send :extend, ClassMethods
  end

  module ClassMethods
    def validate_phone(*attr_names)
      #setup the config array eg. configuration = atrr.extract_options!
      validates_each(attr_names, configuration) do |record, attr_name, value|
          record.errors.add(attr_name, configuration[:message]) unless #validation
       end
       #setup the phone normalization
       unless configuration[:normalize]
         before_save do
           # normalization code here
         end
       end
    end
  end
end

ActiveRecord::Base.send :include, Phones

然后在你的模型中:

validate_phone :main_phone, :cellphone, :message => "not a valid telephone number"