使用 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
?
我正在尝试动态创建一个 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
?