我有一種情況,我試圖利用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
調用它不工作,喜歡它,如果我讓工人模塊外?
請注意,我想通了,在我的第一個問題,這反過來又導致了我一個新的,但類似的問題的一種方式,所以我已經編輯我原來的職位,以反映了我原來的問題的新版本。希望這個編輯/重寫是與StackOverflow規則猶太教。 – Bryan