我使用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方法,该方法包括相关记录(请参阅我的代码中的注释行)。但我不知道如何在动态模型中做到这一点。
有什么想法在这里出错以及如何解决它?不知道我的方法实现这个是正确的 - 也许还有更好的方法吗?
谢谢, 迈克尔
答案 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。