2013-03-08 70 views
3

我有我想要包括类和实例方法的Ruby类。继模式描述here,我目前使用下列内容:通过include添加类方法

class SomeObject 

    include SomeObject::Ability 

    def self.some_builder_method(params) 
    # use some_class_method ... 
    end 

end 

module SomeObject::Ability 

    module ClassMethods 

    def some_class_method(param) 
     # ... 
    end 

    end 

    def self.included(klass) 
    klass.extend(ClassMethods) 
    end 

    def some_instance_method 
    # ... 
    end 

end 

我宁愿不使两个独立的模块(一个被列入,另一种是扩展),因为我模块中的所有方法合情合理一起。另一方面,这种模式a)要求我定义一个额外的模块,并且b)要求我为每个模块编写一个样板self.included方法。

有没有更好的方法来做到这一点?

编辑1:我找到了另一种方式,但我不确定这是否比第一种更好。

module Concern 

    def included(base) 

    # Define instance methods. 
    instance_methods.each do |m| 
     defn = instance_method(m) 
     base.class_eval { define_method(m, defn) } 
    end 

    # Define class methods. 
    (self.methods - Module.methods).each do |m| 
     unless m == __method__ 
     base.define_singleton_method(m, &method(m)) 
     end 
    end 

    end 

end 

module SomeModule 

    extend Concern 

    def self.class_m 
    puts "Class" 
    end 

    def instance_m 
    puts "Instance" 
    end 

end 

class Allo 

    include SomeModule 

end 


Allo.class_m   # => "Class" 
Allo.new.instance_m # => "Instance" 
+0

有关'最佳实践'等问题。与[codereview.se]相关,而不是SO。 – 2013-03-08 23:34:46

+0

这不是一个“最佳实践”,而是“最有效的方法”。我同意这可能在灰色地带,但它非常适合SO恕我直言。 – user2398029 2013-03-08 23:46:38

+0

@WouterJ对于StackOverflow来说,这是一个完全可以接受的问题,并且这个原型问题已经提示了一个存在于Rails中并且广泛使用的模块。 – coreyward 2013-03-08 23:55:16

回答

4

如果我理解正确的话,你真的只是想用ActiveSupport::Concern

module PetWorthy 
    extend ActiveSupport::Concern 

    included do 
    validates :was_pet, inclusion: [true, 'yes'] 
    end 

    def pet #instance method 
    end 

    module ClassMethods 
    def find_petworthy_animal 
     # ... 
    end 
    end 
end 

class Kitty 
    include PetWorthy 
end 

Kitty.find_petworthy_animal.pet 

你(希望显然)不需要使用included方法,如果你没有任何行为引发包括,但我只是为了演示。