使用 ActiveRecord 连接动态创建 Ruby class

Dynamically create Ruby class with ActiveRecord connection

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

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

以下会引发错误 "RuntimeError: Anonymous class is not allowed.",但我不确定如何解决它或是否有更好的替代方法。

  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

您可以为模型动态设置establish_connection

database.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

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

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 class 就可以使用了。

此版本适用于 Rails 5.0 和 3.2。

根据 ActiveRecord::ConnectionHandling#establish_connection's source,您无法从 class 建立连接,因为 name 没有 return 真实值。

现在,您使用 const_set 将 class 分配给常量,这将为它命名。但是你需要在 之前 你调用 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 的 class。可能你只是想要 Object.const_set(...)(它只给出 Foo)?甚至 const_set(...),所以你得到 ClassFactory::Foo?