2012-12-13 48 views
0

我是Ruby和Sinatra的新手,嘗試訪問logger關閉內部對象(EM.run do .. end)。登錄關閉和非Sinatra類

這是工作代碼的摘錄,其中帶有消息「日誌不可訪問」的日誌語句給出編譯錯誤。

class Connection 
    def get_updates 
    logger.info "LOGGER IS NOT ACCESSIBLE HERE 1" 
    end 
end 

class Streamer < Sinatra::Base 
    def stream 
    logger.info "Inside stream" 
    EM.run do 
    logger.info "LOGGER IS NOT ACCESSIBLE HERE 3" 
    Connection.new.get_updates 

    EM::PeriodicTimer.new(10) do 
     logger.info "LOGGER IS NOT ACCESSIBLE HERE 4" 
    end 
    end 
    end 
end 
get '/' do 
    logger.info "loading data" 
    Streamer.new.stream 
end 

document我發現西納特拉使用env['rack.logger']。在上面的代碼中,我們如何在Connection和Streamer等非Sinatra類中使用它們?

回答

1

其實是一個非常有趣的問題。事實證明,logger字段實際上並不是一個變量 - 它是Sinatra::Base中的一種方法。因此,當您執行的代碼位於Sinatra::Base對象的範圍內時,只需鍵入它即可呼叫logger,它會返回給您記錄器對象。

由於它是Sinatra::Base對象的一部分,因此它在Connection對象的範圍內將不可見。

現在我們結束簡單的紅寶石的東西,時間爲更高級的位。

當您從EM.run do節中調用它時,更有趣的部分是。之所以不能在此處使用記錄器,是因爲這些塊是而不是Streamer對象的範圍內執行的,它們在某個其他範圍內由eventmachine自己使用類似instance_evalclass_evalclass_eval - this post顯示了一個很好的示例instance_eval如何在像EM這樣的DSL中工作。

這也是爲什麼logger方法是從get '/'塊訪問 - 西納特拉將在具有使用instance_eval一個logger方法的對象的範圍執行該塊。

爲了做你想做的事,你可以嘗試創建一個包含記錄儀的局部變量:

class Streamer < Sinatra::Base 
    def stream 
    # This will create a local variable called logger that will 
    # save whatever is returned by the logger method 
    logger = self.logger 

    logger.info "Inside stream" 
    EM.run do 
    logger.info "This should now be accessible" 
    Connection.new.get_updates 

    EM::PeriodicTimer.new(10) do 
     logger.info "This should now be accessible" 
    end 
    end 
    end 
end 

這仍然沒有從Connection類內解決採伐問題的。要做到這一點,要麼是使用全局日誌變量(壞主意),要麼在傳遞變量時傳入Connection.new(這不是個好主意,但比全局更好)。