rails mongoid dynamc model失败

时间:2017-11-13 20:22:00

标签: ruby-on-rails mongodb mongoid

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

我的数据库需要非常灵活 - 我需要能够在运行时定义新表并修改它们。所以我创建了一个模型Entity和一个模型Column(属于Entity),因此我可以使用动态列动态创建新模型。

要创建/读取/更新记录,我编写了一个函数,我可以使用实体记录调用它,并返回所请求模型的类:

我用实体记录调用函数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()}

它也适用于创建和更新新记录。但是,只要我的实体拥有“属于”我得到运行时错误:

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

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

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

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

有什么想法在这里出错以及如何解决它?不知道我的方法实现这个是正确的 - 也许还有更好的方法吗?

谢谢, 迈克尔

2 个答案:

答案 0 :(得分:0)

Mongoid的关系代码根据名称进行了很多猜测(就像rails或gem的许多其他部分一样,如active_model_serializer或者你有什么)。因此,如果你有类User,它将假设它应该存储在集合users中,而不需要任何其他配置,通过这些方式做一些事情:

user.class.name.tableize

我没有看到错误的完整堆栈跟踪,因此我无法确定确切来自哪里,但其根本原因是你的动态类没有名字。

datarecord.name # => nil

类通过分配给常量来获取名称。 (也许还有其他一些方式,但我现在不能记住。

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

答案 1 :(得分:0)

最终解决方案:

动态创建所有类。在动态创建/设置类时,我给了他们一个新名称(前缀+模型的名称),因此它们不会覆盖我需要为db(或某些内部进程)播种的初始类定义。这有很多数据库开销:读取包括关联在内的所有类的元数据,并动态创建所有关联模型或继承的类。因此,我只是动态创建一个类,并在模型更改时对其进行实例化(操作字段或关联/继承)。对于所有其他情况,我使用现有的类,如果已经过constantized。