Ruby缺失的define_class

Ruby默認提供了define_method等工具用於動態定義實例方法,但貌似沒提供動態定義類的方法。sql

所謂動態定義類,不是指動態建立類,而是指類名是用字符串或符號動態給定的。看完《Ruby元編程》後,我嘗試着本身實現一個:數據庫

module Kernel
  def define_class(name, ancestor = Object)
    Object.const_set(name, Class.new(ancestor))
    Object.const_get(name).class_eval(&Proc.new) if block_given?
    Object.const_get(name)      # return defined class always
  end
end

你可能會困惑,動態定義類有什麼用?我遇到的一個應用場景就是用在ActiveRecord同時訪問多個數據庫時,須要定義多個ActiveRecord::Base的子類,以下:編程

def LocalBase < ActiveRecord::Base
  self.abstract_class = true
  establish_connection adapter: "sqlite3", database: "local.db"
end

def RemoteBase < ActiveRecord::Base
  self.abstract_class = true
  establish_connection adapter: "sqlite3", database: "remote.db"
end

能夠看出裏面有重複的代碼,使用define_class就能規避這些重複的代碼:ruby

YAML.load(File.read("db.yaml")).each do |name, info|
  define_class(name, ActiveRecord::Base) do
    self.abstract_class = true
    establish_connection info
  end
end

同時,我把數據庫鏈接信息移到了db.yaml文件中:工具

LocalBase:
  adapter: sqlite3
  database: local.db

RemoteBase:
  adapter: sqlite3
  database: remote.db
相關文章
相關標籤/搜索