2011-10-23 71 views
0

我有一種情況,我試圖利用Padrino使用的數據庫配置文件來爲我正在編寫的自定義工作程序,而無需加載Padrino環境,也無需修改現有數據庫配置。總之,我想寫我的代碼來處理現有的數據庫配置代碼,而不是修改現有的配置。如何在Ruby模塊中動態定義Object方法?

有問題的數據庫配置文件如下所示:

# This is just here for right now so I can test 
# to see if logger is set to anything in DB config 
puts "Logger in DB config: #{logger}" 

ActiveRecord::Base.configurations[:development] = { 
    :adapter => 'sqlite3', 
    :database => Padrino.root('db', "app_development.db") } 
ActiveRecord::Base.logger = logger 
ActiveRecord::Base.include_root_in_json = true 
ActiveRecord::Base.store_full_sti_class = true 
ActiveSupport.use_standard_json_time_format = true 
ActiveSupport.escape_html_entities_in_json = false 
ActiveRecord::Base.establish_connection(ActiveRecord::Base.configurations[Padrino.env]) 

我定製的工人看起來如下:

ROOT = File.expand_path(File.dirname(__FILE__)) 
$LOAD_PATH.unshift(ROOT) 

require 'active_record' 
require 'logger' 

# Mock Padrino module with methods used by database config file 
module Padrino 
    def self.root(*args) 
    return File.expand_path(File.join("#{ROOT}/..", *args)) 
end 

    def self.env 
    return :development 
    end 
end 

module Worker 
    class << self 
    attr_accessor :logger 

    def init 
     @logger  = Logger.new(STDOUT) 
     @logger.level = Logger::DEBUG 

     require "#{ROOT}/../config/database" 
    end 
    end 
end 

Worker.init 

當我要求我的員工數據庫配置文件,我得到一個錯誤說以下內容:

/home/user/devel/app/config/database.rb:3:in `<top (required)>': undefined local variable or method `logger' for main:Object (NameError) 
from /home/user/.rvm/rubies/ruby-1.9.2-p290/lib/ruby/site_ruby/1.9.1/rubygems/custom_require.rb:55:in `require' 
from /home/user/.rvm/rubies/ruby-1.9.2-p290/lib/ruby/site_ruby/1.9.1/rubygems/custom_require.rb:55:in `require' 
from worker.rb:26:in `init' 
from worker.rb:31:in `<main>' 

鑑於此,我mod指明分數的Worker#init功能如下所示:

def init 
    @logger  = Logger.new(STDOUT) 
    @logger.level = Logger::DEBUG 

    Object.send(:define_method, :logger, lambda { @logger }) 

    puts "Logger in Worker module: #{logger}" 

    require "#{ROOT}/../config/database" 
end 

這種變化帶來了以下的輸出:

Logger in Worker module: #<Logger:0x9505088> 
Logger in DB config: 

我認爲這意味着該@logger是不是在數據庫配置文件中的適用範圍,即使我在Object上定義記錄器方法時使用了lambda表達式。

奇怪的是,如果我拉Object.send行代碼出Worker#init功能,而是把它叫做我叫Worker.init像下面的權利之前,我得到以下結果。

Object.send(:define_method, :logger, lambda { Worker.logger }) 
Worker.init 

結果

Logger in Worker module: #<Logger:0x81bc8b4> 
Logger in DB config: #<Logger:0x81bc8b4> 

有人能向我解釋爲什麼,如果我做了Worker#init函數內Object.send調用它不工作,喜歡它,如果我讓工人模塊外?

+0

請注意,我想通了,在我的第一個問題,這反過來又導致了我一個新的,但類似的問題的一種方式,所以我已經編輯我原來的職位,以反映了我原來的問題的新版本。希望這個編輯/重寫是與StackOverflow規則猶太教。 – Bryan

回答

0

在第一個示例中,您嘗試使用未定義的變量「記錄器」,如您從錯誤消息中看到的那樣。嘗試使用記錄器功能,這樣一來:

ActiveRecord::Base.logger = Logger.new(STDOUT) 
+0

感謝WarHog的建議,但爲了做你所建議的,我將不得不修改Padrino生成和使用的數據庫配置文件。而不是這樣做,我希望能夠通過使我的代碼與它一起工作來使用配置文件(試圖讓事情乾燥,因此如果我更改Padrino應用的配置文件,則不必更新我的工作人員的數據庫配置文件)。我更新了我原來的問題,試圖讓這個更清楚。 – Bryan

+0

你能分享一下你的配置文件的代碼段? – WarHog

+0

WarHog,請注意,我想出了一個解決我的第一個問題的方法,這又引發了一個新的,但類似的問題,所以我編輯了我的原始文章以反映我的原始問題的新版本。 – Bryan

相關問題