列出Mongoid模型中的动态属性

我已经阅读了文档,我找不到具体的方法来解决这个问题。 我已经为模型添加了一些动态属性,我希望能够遍历所有这些属性。

所以,举一个具体的例子:

class Order include Mongoid::Document field :status, type: String, default: "pending" end 

然后我做以下事情:

 Order.new(status: "processed", internal_id: "1111") 

后来我想回来并且能够获得所有动态属性的列表/数组(在这种情况下,“internal_id”就是它)。

我还在挖,但我很想听听其他人是否已经解决了这个问题。

只需在您的模型中包含以下内容:

 module DynamicAttributeSupport def self.included(base) base.send :include, InstanceMethods end module InstanceMethods def dynamic_attributes attributes.keys - _protected_attributes[:default].to_a - fields.keys end def static_attributes fields.keys - dynamic_attributes end end end 

这是一个规范:

 require 'spec_helper' describe "dynamic attributes" do class DynamicAttributeModel include Mongoid::Document include DynamicAttributeSupport field :defined_field, type: String end it "provides dynamic_attribute helper" do d = DynamicAttributeModel.new(age: 45, defined_field: 'George') d.dynamic_attributes.should == ['age'] end it "has static attributes" do d = DynamicAttributeModel.new(foo: 'bar') d.static_attributes.should include('defined_field') d.static_attributes.should_not include('foo') end it "allows creation with dynamic attributes" do d = DynamicAttributeModel.create(age: 99, blood_type: 'A') d = DynamicAttributeModel.find(d.id) d.age.should == 99 d.blood_type.should == 'A' d.dynamic_attributes.should == ['age', 'blood_type'] end end 

这将只为您提供给定记录x的动态字段名称:

 dynamic_attribute_names = x.attributes.keys - x.fields.keys 

如果使用其他Mongoidfunction,则需要减去与这些function相关的字段:例如,对于Mongoid::Versioning

 dynamic_attribute_names = (x.attributes.keys - x.fields.keys) - ['versions'] 

要仅获取动态属性的键/值对:

确保克隆属性()的结果,否则你修改x !!

 attr_hash = x.attributes.clone #### make sure to clone this, otherwise you modify x !! dyn_attr_hash = attr_hash.delete_if{|k,v| ! dynamic_attribute_names.include?(k)} 

或者在一行中:

 x.attributes.clone.delete_if{|k,v| ! dynamic_attribute_names.include?(k)} 

所以,我最终做的就是这个。 我不确定这是否是最佳方式,但它似乎给了我正在寻找的结果。

 class Order def dynamic_attributes self.attributes.delete_if { |attribute| self.fields.keys.member? attribute } end end 

属性似乎是对象上实际属性的列表,而字段似乎是预定义字段的哈希值。 无法在文档中找到它,但我现在正在使用它,除非别人知道更好的方法!

尝试.methods或.instance_variables

不确定我是否喜欢克隆方法,所以我也写了一个。 从这里你也可以轻松地构建内容的哈希值。 这只是输出所有动态字段(扁平结构)

  (d.attributes.keys - d.fields.keys).each {|a| puts "#{a} = #{d[a]}"}; 

我无法使上述任何解决方案工作(因为我不想为每个模型添加slab和slab代码,并且由于某种原因,在模型实例上不存在attributes方法,对我来说。:/),所以我决定写我自己的助手为我做这件事。 请注意,此方法包括动态和预定义字段

helpers / mongoid_attribute_helper.rb

 module MongoidAttributeHelper def self.included(base) base.extend(AttributeMethods) end module AttributeMethods def get_all_attributes map = %Q{ function() { for(var key in this) { emit(key, null); } } } reduce = %Q{ function(key, value) { return null; } } hashedResults = self.map_reduce(map, reduce).out(inline: true) # Returns an array of Hashes (ie {"_id"=>"EmailAddress", "value"=>nil} ) # Build an array of just the "_id"s. results = Array.new hashedResults.each do |value| results << value["_id"] end return results end end end 

models / user.rb

 class User include Mongoid::Document include MongoidAttributeHelper ... end 

一旦我将上述include( include MongoidAttributeHelper )添加到我想使用此方法的每个模型中,我就可以使用User.get_all_attributes获取所有字段的列表。

当然,这可能不是最有效或最优雅的方法,但绝对有效。 🙂