2013-03-08 25 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方法,如果你沒有任何行爲引發包括,但我只是爲了演示。