2013-02-08 8 views
5

Mam moduł z metodami, które zapisują do dziennika. Do każdej wiadomości chcę wstawić nazwę klasy, która zalogowała tę wiadomość.self.class.name w module typu mix-in

Moduł można mieszać przy użyciu include lub . Potrzebuję, aby mój log miał prawidłowe nazwy klas w każdym przypadku.

kod destylowana:

module M 
    def f 
    self.class.name 
    end 
end 

class C 
    extend M 
    include M 
end 

p C.f # => "Class" 
p C.new.f # => "C" 

Jak widać, pierwsze wywołanie niepoprawnie drukuje "Class". Chcę też, żeby to było "C".

Jak to zrobić?

Odpowiedz

4

Nie ma potrzeby uciekać się do haków, wystarczy zmienić swoje zachowanie, gdy self jest Class/Module:

module M 
    def f 
    self.is_a?(Module) ? name : self.class.name 
    end 
end 

class C 
    extend M 
    include M 
end 

C.f  #=> "C" 
C.new.f #=> "C" 
3

Możesz to zrobić w ten sposób, nie wiesz, czy istnieje lepsza metoda.

module M 
    def self.included(base) 
    base.extend ClassMethods 
    end 

    def f 
    self.class.name 
    end 

    module ClassMethods 
    def f 
     self.name 
    end 
    end 
end 

class C 
    include M 
end 
+0

To nie działa w ogóle, jeśli 'przedłużyć M', choć. –

+0

Nie musisz przedłużać. Metody, które chcesz przekształcić w metody klasowe umieszczone w module ClassMethods. :) – Kaeros

+0

Co, jeśli chcę tylko rozszerzyć i nie uwzględnić? Następnie muszę zrobić 'extend M :: ClassMethods' bez ważnego powodu. Osobiście też po prostu nie lubię całego wzorca rozszerzania się po włączeniu. –