2010-01-29 87 views
2

我正在创建一个插件,并且很难定义一个before_save过滤器来调用我刚定义的实例方法。这里有一个快速示例:如何在插件的before_save回调中包含实例方法?

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_fields'的方法,但实例应该。

谢谢!

回答

4

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

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 

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

+0

优秀。感谢弗朗索瓦......我真的希望美国的键盘可以在C下做扭曲。看起来很有趣。 – btelles 2010-01-30 16:18:05

2

当您使用回调宏时,您只能为要运行的方法传递符号,传递参数是不可能的。从Rails文档的“处理方法”是使用“的方法字符串”是获取正确的上下文中进行评估:

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

另一种可能性:你的字段名存储为一个类变量并获得一个在你的情况下,那么你可以使用before_save:format_phone_fields

+0

很酷,这也适用。谢谢罗马 – btelles 2010-01-30 16:18:31

相关问题