2013-02-22 9 views
6

Używam g logger we wszystkich moich klasach. chcę każdy msg na początku nazwy klasy i nazwy metody tak:implementuj szyny before_filter w ruby ​​bez szyn

Class_name::Method_name 

to co robię teraz:

class FOO 

def initialize 
end 

def bar 
    msg_prefix = "#{self.class}::#{__method__}" 
    ... some code ... 
    @logeer = "#{msg_prefix} msg ..." 
end 

def bar2 
    msg_prefix = "#{self.class}::#{__method__}" 
    ... some code 2 ... 
    @logeer = "#{msg_prefix} msg2 ..." 
end 

end 

chcę używać before_filter jak na szynach, aby zapobiec dwulicowość, Używam sinatra ale klasy są zwykłe stare ruby 1.9.3 klasy

pomysły ??

+0

możesz użyć activerecord z sinatra https://github.com/janko-m/sinatra-activerecord – AJcodez

Odpowiedz

5

można dostać zwrotnej jakiejkolwiek metody tworzone z Module#method_added, alias starej metody, a następnie zdefiniuj nową metodę, która najpierw wywołuje metodę before_filter. Oto moja (bardzo) szorstki Pierwsza koncepcja:

module Filter 
    def before_filter name 
    @@filter = name 
    end 

    def method_added name 
    return if @filtering # Don't add filters to original_ methods 
    return if @@filter == name # Don't filter filters 
    return if name == :initialize 

    @filtering = true 

    alias_method :"original_#{name}", name 
    define_method name do |*args| 
     self.send @@filter, name 
     self.send :"original_#{name}", *args 
    end 
    @filtering = false 
    end 
end 

class FilterTest 
    extend Filter 
    before_filter :prepare_logs 

    def baz 
    puts "#{@msg_prefix} message goes here" 
    end 

    def prepare_logs name 
    @msg_prefix = "#{self.class}::#{name}" 
    end 
end 

ft = FilterTest.new 
ft.baz 

Korzystając __method__ jak byłaś w create_prefix, dostaniesz nazwę metody filtra, a nie oryginalna metoda, więc trzeba przekazać nazwę metody w Mogą istnieć inne rozwiązania, które sprawią, że będzie nieco czystszy.

+0

dzięki Zaius, to rzeczywiście podstęp, ale wdrożyłem go w super klasie, i zadziałało dla 1. samej klasy super, 2. to dziecko, 3. dla wnuków, dało mi "Uncaught wyjątek: poziom stosu jest zbyt głęboki "Zastanawiam się, dlaczego ... – WebQube

+0

Cóż .. to trochę hakowate rozwiązanie, więc mnie to nie dziwi. Wklej swój kod i komunikat o błędzie w mgnieniu oka lub coś w tym stylu i mogę Ci powiedzieć, dlaczego się załamuje. – zaius

+0

jasne, oto jest. instancje są na końcu. [gist] (https://gist.github.com/ohadpartuck/5070783) – WebQube

1

Można użyć ActiveModel::Callbacks dostać before_filter -jak zachowanie w zwykłych klasach Ruby (choć być może w twoim przypadku to przesada za jedyne wykonanie jednej linii):

require 'active_model' 

class FOO 
    extend ActiveModel::Callbacks 

    define_model_callbacks :baz, only: :before 

    before_baz :create_prefix 

    def initialize 
    end 

    def bar 
    run_callbacks :baz do 
     ... some code ... 
     @logeer = "#{@msg_prefix} msg ..." 
    end 
    end 

    def bar2 
    run_callbacks :baz do 
     ... some code 2 ... 
     @logeer = "#{@msg_prefix} msg2 ..." 
    end 
    end 

    private 

    def create_prefix 
     @msg_prefix = "#{self.class}::#{__method__}" 
    end 
end 
+0

hi paul, dziękuję za odpowiedź, ale szukam sposobu, aby użyć go w taki sam sposób, jak użycie szyn, jeden linia 'before_filter: do_prefix_msg' uruchamia się automatycznie przed każdą funkcją (chyba, że ​​powiedziano inaczej) – WebQube

+0

Myślę, że użycie' ActiveModel :: Callbacks' jest najłatwiejszym sposobem uzyskania pożądanego efektu bez konieczności ponownego wdrażania sprawiedliwej ilości kodu to jest za odwołaniami [Railsów] (https://github.com/rails/rails/blob/v3.2.12/actionpack/lib/abstract_controller/callbacks.rb). Miałem ten sam problem jakiś czas temu z jednym z moich własnych projektów i nie mogłem znaleźć lepszego rozwiązania niż "ActiveModel :: Callbacks". Ale w nadziei, że jest jakiś inny sposób, który zna ktoś inny, dam ci pytanie. –