在Ruby on Rails中在运行时构建表

如果rails希望从模型名称推断表名,我将如何在运行时创建多个使用相同模型的数据库表? 我希望能够基于模型创建新对象,然后创建一个具有该对象将引用的唯一名称的新表。 有没有人可以分享任何示例或建议来帮助我找到解决方案?

这听起来像是一个架构问题 – 为什么你会有相同模型的克隆而不是将它们全部存储在同一个表中?

在关系数据库模型中,关系是定义行或元组的关系,这意味着它是关于键的属性集。 任何其他类似的属性集属于同一关系(表)。

不确定为什么你想要这样做,但它有可能:

runtime_table_name = "random" ActiveRecord::Migration.create_table(runtime_table_name) do # Table definition goes here end eval <<-EOS class #{runtime_table_name.classify} < YourBaseModel set_table_name #{runtime_table_name.inspect} end EOS runtime_model = runtime_table_name.classify.constantize runtime_model.find(:all) 

您只需将YourBaseModel替换为您希望运行时模型的模型。

 def self.create_table ActiveRecord::Schema.define do create_table :my_table_name do |t| #(define your columns just as you would in a migration file) t.string :my_string end end end 

(请参阅此处 define的方法的文档。)(我在rubyforums上看到了这个答案。这是主题 。)

在寻找类似问题的解决方案时发现这篇文章:我需要将用户生成的报告数据(数据网格)存储在数据库中以进行进一步编辑/导出/等。 我决定在DB中为每个报告创建一个新表并对其进行ORM包装。 Nathan的回答除了eval部分之外有帮助,我认为它与当前的范围有关。 我试图在实例方法( after_save挂钩)中定义一个新类,所以当我后来从另一个方法引用新常量时,我​​得到了一个NameError 。 明确地将binding传递给eval对于一个未知的原因(错误的绑定?)没有帮助,所以我这样做了:

 klass = Class.new(ActiveRecord::Base) do # class body goes here end Object.const_set(class_name, klass) 

我猜,创建表是可能的。 使用ActiveRecord :: Base.connection.execute执行类似“CREATE TABLE newtab AS SELECT * FROM oldtab WHERE 0 = 1”的操作。

然后,您可以以某种方式执行set_table_name以将模型指向创建的表。

这将有助于获得更多关于您认为自己需要的问题的信息,这需要这种扭曲的解决方案。 在Rails中很难做到的原因是你真的不需要这样做。 我希望有一个更简单的替代架构。