2013-02-05 8 views
10

Chcę dynamicznie generować metodę klasy w Mixin, w oparciu o nazwę klasy, która zawiera ten Mixin.Szyny: dynamicznie definiuj metodę klasy opartą na nadrzędnej nazwie klasy w module/problemie

Tu jest mój bieżący kod:

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 

Ale to daje mi następujące nazwy metoda:

MyClass.mymodule::classmethods_status 

Pierwsze nazwę klasy bazowej wewnątrz pracach definition metoda (self, self.name. ..) ale nie mogę sprawić, żeby to działało dla nazwy metody ...

Do tej pory próbowałem

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}" 

Ale nic z tego nie zdaje rade:/

Czy jest jakiś sposób mogę odzyskać nazwę klasy bazowej (nie wiem jak to nazwać, które obejmują klasę mój moduł). Mam zmaga się z tym problemem przez wiele godzin, a ja teraz nie potrafię wymyślić czyste rozwiązanie :(

Dzięki

Odpowiedz

5

nie można zrobić tak, że - w tym momencie nie jest ale wiadomo, która klasa (lub klasy) są w tym module.

Jeśli zdefiniujesz metodę self.included, zostanie ona wywołana za każdym razem, gdy moduł zostanie włączony, a element robiący uwzględnianie zostanie przekazany jako argument. przy użyciu AS :: Concern można wykonać:

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

Thanks dla wyjaśnienia. Użyłem 'define_singleton_method' wewnątrz' included do # ... end' block: 'define_singleton_method" # {self.name} _status "do # ... end' ' – cl3m

1

można zrobić coś takiego:

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

pracuje dla 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

znalazłem rozwiązanie: przy użyciu czystej define_singleton_method (dostępne w 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 
Powiązane problemy