0

我想使用 Datamapper 动态创建和查询表。

虽然 Datamapper 允许您使用旧表和模式,并以这种方式设置使用的表名,但这仅在初始化期间,而不是在应用程序内。

有没有一种简单的方法可以告诉 Datamapper 在应用程序中迁移/升级具有分配表名的模型,然后告诉它查询该表?

4

2 回答 2

1

这应该不是问题。

所有 Ruby 类都可以在运行时创建和重新定义。甚至初始化也在运行时。初始化恰好在执行其他代码之前首先执行。

这就是猴子补丁如此容易工作的原因。它只是初始化时的附加代码,只是重新定义类以添加额外的方法、变量等。

没有 Ruby 代码是“特殊的”,因为它只在编译时运行。Ruby 是一种解释型语言。


要动态创建类,请参阅在 Ruby 中动态创建类

假设您不需要从字符串数组动态创建类,您可以使用 定义其他方法define_method,或者在运行时调用 Datamapper 方法来添加属性。

在类中定义新方法:

Post.send :define_method, :new_method_name do
end

要使用 Datamapper 属性定义新属性:

class Post
  include DataMapper::Resource
  property :title, String # the static way
end

Post.send :property, :title, String # add property the dynamic way (at run-time)

请注意,如果您重新启动服务器,您在运行时定义的任何表或属性都将不可用,除非重新执行动态生成它们的代码。


要在运行时更新表,您只需像往常一样做同样的事情,即调用:

DataMapper.auto_upgrade!

要仅升级单个表,您还可以执行以下操作:

Post.auto_upgrade!

第二个警告:如果您有多个进程,则需要在每个进程中运行动态代码,否则附加表 Models 和 Properties 将不可用。

如果您有多个工作进程,这将是一个问题,就像生产中可能发生的那样(例如,Nginx 具有多个 Unicorn 工作人员,或者 Ha_proxy 后面有多个 Mongrel 工作人员)。

如果您有一个单进程服务器,那么这不是问题。但是,如果您有多个工作进程,则必须运行动​​态代码以在每个进程中生成这些额外的类和属性以使其可用。

这实际上与初始化相同,因为每个进程都经过初始化(或者如果分叉,则继承任何初始化)。

于 2012-09-03T02:53:34.307 回答
0

无需更改任何内容的最简单方法是使用单独的数据库而不是表(假设任何关系也将存储在单独的数据库中)并打开与块中其他存储库的连接。

DataMapper.setup(:external, "adapter://username:password@hostname/dbname")
DataMapper.repository(:external) do...end
于 2012-10-04T00:50:22.513 回答