代码之家  ›  专栏  ›  技术社区  ›  btelles

如何在插件中保存回调之前在其中包含实例方法?

  •  2
  • btelles  · 技术社区  · 15 年前

    我正在创建一个插件,很难定义一个调用我刚刚定义的实例方法的“保存前”过滤器。下面是一个快速的示例:

    module ValidatesAndFormatsPhones
      def self.included(base)
        base.send :extend, ClassMethods
      end
    
      module ClassMethods
    
        def validates_and_formats_phones(field_names = [:phone])
          send :include, InstanceMethods
    
          # the following variations on calls to :format_phone_fields fail
    
          before_save send(:format_phone_fields, field_names)
    
          before_save format_phone_fields(field_names)
    
          before_save lambda { send(:format_phone_fields, field_names) }
    
          # EACH OF THE ABOVE RETURNS 'undefined_method :format_phone_fields'
        end
      end
    
      module InstanceMethods
    
        def format_phone_fields(fields = [:phone], *args)
          do stuff...
        end
    
      end
    end
    
    ActiveRecord::Base.send :include, ValidatesAndFormatsPhones
    

    我想问题是,如何将上下文更改为实例,而不是类?

    我更喜欢调用实例方法,因为类不应该真正有一个名为“format\phone\u fields”的方法,但实例应该有。

    谢谢!

    2 回复  |  直到 15 年前
        1
  •  4
  •   François Beausoleil    15 年前

    在适当的时候包括您的方法:当您扩展基类时:

    module ValidatesAndFormatsPhones
      def self.included(base)
        base.send :extend, ClassMethods
        base.send :include, InstanceMethods
      end
    
      module ClassMethods
        def validates_and_formats_phones(field_names = [:phone])
          before_save {|r| r.format_phone_fields(field_names)}
        end
      end
    
      module InstanceMethods
        def format_phone_fields(fields = [:phone], *args)
          # do stuff...
        end
      end
    end
    
    ActiveRecord::Base.send :include, ValidatesAndFormatsPhones
    

    我没有运行代码,但它应该可以工作。我经常做类似的事情。

        2
  •  2
  •   roman    15 年前

    使用回调宏时,只能为要运行的方法传递符号,不能传递参数。Rails文档中的“解决方法”是使用在正确上下文中评估的“方法字符串”:

    before_save 'self.format_phone_fields(....)'
    

    另一种可能性是:将字段名存储为类变量,并在实例中访问该变量,然后可以在“保存:格式化”字段之前使用