2013-02-22 2 views
6

Я использую g регистратор во всех своих классах. Я хочу, чтобы каждый тзд начать с именем класса и именем метода следующим образом:реализовать рельсы before_filter в рубине без рельсов

Class_name::Method_name 

это то, что я делаю сейчас:

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 

я хочу использовать before_filter как в рельсах, чтобы предотвратить duplicity, Я использую sinatra, но классы простые старые ruby 1.9.3 классы

идеи ??

+0

вы можете использовать activerecord с sinatra https://github.com/janko-m/sinatra-activerecord – AJcodez

ответ

5

Вы можете получить обратный вызов по любому методу создается с Module#method_added, аналогично старому методу, затем определите новый метод, который сначала вызовет метод before_filter. Вот мой (очень) грубый первое понятие:

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 

Используя __method__ как вы были в create_prefix, вы получите имя метода фильтра, а не оригинальный метод, так что вы должны передать имя метода в Возможно, будут другие решения, которые сделают это немного чище.

+0

спасибо zaius, это действительно трюк, но я реализовал его в суперклассе, и он работал над 1. суперклассом, 2. он был ребенком, 3. для его внуков это дало мне исключение «Uncaught»: уровень стека слишком глубокий' Интересно, почему .. – WebQube

+0

Ну .. это своего рода хакерское решение, так что меня это не удивляет. Вставьте свой код и сообщение об ошибке в суть или что-то еще, и я могу сказать вам, почему он ломается. – zaius

+0

уверен, вот оно. экземпляры заканчиваются. [gist] (https://gist.github.com/ohadpartuck/5070783) – WebQube

1

Вы можете использовать ActiveModel::Callbacks, чтобы получить before_filter -как поведения в простых классах Руби (хотя, возможно, в вашем случае это слишком для просто выполнение одной строки):

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

привет, paul, спасибо за ответ, но я ищу способ использовать его точный способ использования рельсов, один line 'before_filter: do_prefix_msg' для запуска автоматически перед каждой функцией (если не указано иначе) – WebQube

+0

Я думаю, что использование« ActiveModel :: Callbacks »- это самый простой способ получить точный эффект, который вам нужен, без необходимости повторной реализации достаточного количества кода это за [обратные вызовы Rails] (https://github.com/rails/rails/blob/v3.2.12/actionpack/lib/abstract_controller/callbacks.rb). Недавно у меня была такая же проблема с одним из моих собственных проектов, и я не мог найти решение лучше, чем «ActiveModel :: Callbacks». Но, в надежде, что есть какой-то другой способ, который знает кто-то другой, я задам вопрос. –