使用活动记录连接动态创建 Ruby 类



我正在尝试动态创建一个类,并将多个数据库连接之一分配给每个类。

正在使用两个或三个随时间变化的数据库之间的任何地方,因此,我犹豫是否将每个连接字符串存储在单独的类中并从中继承而不是 ActiveRecord::Base。

下面抛出一个错误"运行时错误:不允许匿名类",但我不确定如何解决它,或者是否有更好的选择。

  class ClassFactory
    def self.create_class(new_class, table, db_connection)
      c = Class.new(ActiveRecord::Base) do
        db = db_connection
        self.table_name = table
        establish_connection(:adapter => db.database_type, :host => db.host, :database => db.database, :username => db.username, :password => db.password).connection
      end
      Module.const_set new_class, c
    end
  end

根据ActiveRecord::ConnectionHandling#establish_connection的源代码,您无法从 name 不返回真实值的类建立连接。

现在,您将使用 const_set 将类分配给一个常量,这将给它一个名称。但是您需要在致电establish_connection之前执行此操作:

class ClassFactory
  def self.create_class(new_class, table, db_connection)
    c = Class.new(ActiveRecord::Base) do
      db = db_connection
      self.table_name = table
    end
    Module.const_set new_class, c
    c.establish_connection(:adapter => db.database_type, :host => db.host, :database => db.database, :username => db.username, :password => db.password).connection
  end
end

另外,你真的想要Module.const_set(...)吗?这将生成一个名为 Module::Foo 的类。可能你只是想要Object.const_set(...)(这只会给Foo(?甚至const_set(...),所以你得到ClassFactory::Foo

您可以

动态设置模型establish_connection

数据库.yml

development:
  adapter: mysql
  username: root
  password: 
  database: example_development
oracle_development:
  adapter: oracle
  username: root
  password: 
  database: example_oracle_development

在代码的任何地方,您都可以更改模型的数据库连接:

User.establish_connection "oracle_#{RAILS_ENV}".to_sym

您还可以动态创建模型类:

class ClassFactory
  def self.create_class(new_class, table, connection_name)
    Object.const_set(new_class, Class.new(ActiveRecord::Base) {})
    new_class.constantize.table_name = table
    new_class.constantize.establish_connection(connection_name)
  end
end
ClassFactory.create_class('NewUser', 'users', :development)

之后NewUser类将可供使用。

此版本适用于 Rails 5.0 和 3.2。

最新更新