当我只知道集合名称时,如何使用Mongoid动态调用模型



假设我有20多种型号,其中一种称为Job

module API
class Job
include Mongoid::Document
# ...
store_in collection: :jobs
# ...
end
end

我正在处理一些HTTP webhook,我正在指定系统管理员希望订阅更新的集合。

也就是说,我知道这个集合叫做jobs

known_info = { db_name: 'x', collection: 'jobs', id: '6095d84c5be78a26cc9d837b' }
## this is the normally way one would query jobs, but I want to mimic it
## dynamically not using the Module name
API::Job.find(known_info[:id])
## a second way that will NOT work,
## this evades all API code that I have written, I need to use my ruby code in the
## model with access to the class functions
document = nil
Mongoid.default_client.collections.each do |collection|
next unless collection.namespace == "#{known_info[:db_name]}.#{known_info[:collection]}"
document = collection.find(_id: known_info[:id]).limit(1).first
end
## this will return the record from the database,
## but it will not send it through the model, its just the raw database value
pp document =>
{"_id"=>BSON::ObjectId('6095d84c5be78a26cc9d837b'),
...
}

我可以通过以下操作来解决这个问题。

使用模型所包含的名称空间,可以查询常量并缩小

known_info = { db_name: 'x', collection: 'jobs', id: '6095d84c5be78a26cc9d837b' }
document = nil
API.constants.each do |constant|
module_class = API.const_get(constant)
## skip of the constant is not a class
next unless module_class.is_a?(Class)
## skip if the class does not have a method called "collection_name"
next unless module_class.respond_to?(:collection_name)
## skip if the collection does not match the known collection
next unless module_class.collection_name.to_s == known_info[:collection]
document = module_class.find(known_info[:id])
end
p document
## success!

最新更新