rails mongoid 动态模型失败

rails mongoid dynamc model fails

我正在使用 rails/mongodb 作为我的 Web 应用程序的后端服务器。

我的数据库需要非常灵活 - 我需要能够定义新表并在运行时修改它们。所以我创建了一个模型实体和一个模型列(属于实体),这样我就可以动态地创建带有动态列的新模型。

我为 create/read/update 记录编写了一个函数,我可以用实体记录调用它,它 returns 所请求模型的 class:

我用实体记录调用函数 getObject:

entity = Entity.find_by(name: obj)
datarecord = getObject(entity)

使用这个函数:

def getObject(entity)

  obj= Class.new() do
      include Mongoid::Document
      include Mongoid::Attributes::Dynamic
      store_in collection: entity.name.pluralize.downcase

      entity.columns.each do |column|
          field column[:fieldNameOrPath]
      end

      entity.relationships.each do |relationship|
        if relationship.typ =='Belongs To'
          e = Entity.find(relationship.relationship_id)
          belongs_to e.name.downcase
          default_scope { includes(e.name.downcase)}
        end
        if relationship.typ =='Has Many'
          e = Entity.find(relationship.relationship_id)
          has_many e.name.pluralize.downcase
        end
        if relationship.typ =='Has And Belongs To Many'
          e = Entity.find(relationship.relationship_id)
          has_and_belongs_to_many e.name.pluralize.downcase
        end
      end

#     def as_json(options={})
#        attrs = super(:include => [:user])
#        attrs["user"]["id"] = attrs["user"]["_id"].to_s
#        attrs
#     end
     end
   end
   obj
end

这在我使用返回的对象 obj 检索数据时起作用:

render json: { result: datarecord.all()}

它也适用于创建和更新新记录。但是一旦我的实体具有 'Belongs To' 关系,我就会收到运行时错误:

NoMethodError (undefined method `demodulize' for nil:NilClass):

NoMethodError (undefined method `constantize' for nil:NilClass):

我想问题是我没有为相关模型定义 class?

我的第二个问题是,我想要此记录 belongs_to 自动加载的其他记录。在静态实现中,我可以实现这个 definde a as_json 方法,其中包括关联的记录(请参阅我的代码中的注释行)。但是我不知道如何在我的动态模型中做到这一点。

知道这里出了什么问题以及如何解决吗?不确定我的实现方式是否正确 - 也许有更好的方法?

谢谢, 迈克尔

Mongoid 的关系代码根据名称进行大量猜测(rails 或 gems 的许多其他部分也是如此,例如 active_model_serializer 或你有什么)。因此,如果您有 class 用户,它会假设,无需任何额外配置,它应该存储在集合 users 中,方法是按照以下行做一些事情:

user.class.name.tableize

我没有看到你的错误的完整堆栈跟踪,所以我不能确切地说出它来自哪里,但根本原因是你的动态class没有名字。

datarecord.name # => nil

A class 通过分配给常量来获取名称。 (也许还有其他方式,但我现在不记得了。

datarecord.name # => nil
FooBar = datarecord
datarecord.name # => 'FooBar'

最终解决方案:

动态创建所有 classes。虽然动态 creating/instatiating classes 我给了他们一个新名称(模型的前缀+名称)所以他们不会覆盖我需要为数据库播种的初始 class 定义(或用于一些内部流程)。这有相当多的数据库开销:读取所有 classes 的元数据,包括关联,并为所有关联模型或继承动态创建 classes。所以我只动态创建一个 class 并在模型发生变化时将其常量化(操作字段或 associations/inheritance)。对于所有其他情况,如果已经常量化,我将使用现有的 class。