2013-02-05 13 views
10

Ich möchte eine Klassenmethode in einem Mixin, basierend auf dem Klassennamen, die diese Mixin enthalten dynamisch generieren.Rails: dynamisch definieren Klassenmethode basierend auf Elternklasse Name in Modul/Anliegen

Hier ist meine aktuellen Code:

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 

Aber geben Sie mir die folgende Methode Name:

MyClass.mymodule::classmethods_status 

gibt es die Basisklasse Name innerhalb der Methodendefinition Werke (self, self.name. ..), aber ich kann es nicht für den Namen der Methode machen funktioniert ...

Bisher habe ich versucht

Aber nichts davon scheint den Trick zu tun:/

Gibt es eine Möglichkeit, die Basisklassennamen abrufen kann (nicht sicher, was die Klasse zu nennen, die mein Modul enthalten). Ich habe jetzt stundenlang mit diesem Problem zu kämpfen, und ich kann nicht eine saubere Lösung :(

Dank

Antwort

5

Sie können nicht tun, es so scheinen, um herauszufinden - an dieser Stelle nicht ist noch bekannt, welche Klasse (oder Klassen) das Modul enthält

Wenn Sie eine self.included Methode definieren, wird sie jedes Mal aufgerufen, wenn das Modul enthalten ist, und die Sache, die das Einschließen übernimmt, wird als Argument übergeben Mit AS :: Concern können Sie Folgendes tun:

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

Dank für die Erklärung. Ich habe 'define_singleton_method' im' included do # ... end'-Block verwendet: 'define_singleton_method" # {self.name} _status "do # ... end' ' – cl3m

1

Sie können etwas tun:

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

Werke für 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

ich eine saubere Lösung gefunden: define_singleton_method (erhältlich in Ruby v1.9.3) mit

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