2013-02-05 33 views
10

Tôi muốn tạo động một phương thức lớp trong Mixin, dựa trên tên lớp bao gồm Mixin này.Đường ray: tự động xác định phương thức lớp dựa trên tên lớp cha trong mô-đun/mối quan tâm

Đây là mã hiện tại của tôi:

module MyModule 
    extend ActiveSupport::Concern 

    # def some_methods 
    # ... 
    # end 

    module ClassMethods 

    # Here is where I'm stuck... 
    define_method "#{self.name.downcase}_status" do 
     # do something... 
    end 

    end 
end 

class MyClass < ActiveRecord::Base 
    include MyModule 
end 

# What I'm trying to achieve: 
MyClass.myclass_status 

Nhưng điều này cho tôi tên phương pháp sau đây:

MyClass.mymodule::classmethods_status 

Bắt tên lớp cơ sở bên trong công trình định nghĩa phương pháp (tự, self.name. ..) nhưng tôi không thể làm cho nó hoạt động cho tên phương thức ...

Cho đến nay, tôi đã thử

define_method "#{self}" 
define_method "#{self.name" 
define_method "#{self.class}" 
define_method "#{self.class.name}" 
define_method "#{self.model_name}" 
define_method "#{self.parent.name}" 

Nhưng không ai trong số này dường như làm các trick:/

Có cách nào tôi có thể lấy lại tên lớp cơ sở (không chắc chắn những gì để gọi lớp mà bao gồm mô-đun của tôi). Tôi đã đấu tranh với vấn đề này trong nhiều giờ ngay bây giờ và tôi dường như không thể tìm ra một giải pháp làm sạch :(

Cảm ơn

Trả lời

5

Bạn không thể làm điều đó như thế - vào thời điểm này nó không phải là chưa biết lớp nào (hoặc các lớp) bao gồm mô-đun:

Nếu bạn xác định phương thức self.included, nó sẽ được gọi mỗi khi mô-đun được bao gồm và điều thực hiện sẽ được chuyển làm đối số. sử dụng AS :: Quan tâm bạn có thể làm

included do 
    #code here is executed in the context of the including class 
end 
+1

Cảm ơn để giải thích. Tôi đã sử dụng 'define_singleton_method' bên trong khối' include do # ... end': 'define_singleton_method" # {self.name} _status "do # ... end' ' – cl3m

1

Bạn có thể làm một cái gì đó như thế này:

module MyModule 
    def self.included(base) 
    (class << base; self; end).send(:define_method, "#{base.name.downcase}_status") do 
     puts "Hey!" 
    end 

    base.extend(ClassMethods) 
end 

    module ClassMethods 
    def other_method 
     puts "Hi!" 
    end 
    end 
end 

class MyClass 
    include MyModule 
end 

MyClass.myclass_status 
MyClass.other_method 
1

trình cho extend:

module MyModule 
    def self.extended who 
    define_method "#{who.name.downcase}_status" do 
     p "Inside" 
    end 
    end 
end 

class MyClass 
    extend MyModule 
end 

MyClass.myclass_status 
5

Tôi tìm thấy một giải pháp làm sạch: sử dụng define_singleton_method (có sẵn trong ruby ​​v1.9.3)

module MyModule 
    extend ActiveSupport::Concern 

    included do 
    define_singleton_method "#{self.name}_status" do 
     # do stuff 
    end 
    end 

    # def some_methods 
    # ... 
    # end 

    module ClassMethods 
    # Not needed anymore! 
    end 
end