4

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

因此,举一个具体的例子:

class Order
  include Mongoid::Document

  field :status, type: String, default: "pending"
end

然后我执行以下操作:

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

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

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

4

6 回答 6

5

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

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

如果您使用其他 Mongoid 功能,则需要减去与这些功能相关的字段:例如Mongoid::Versioning

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

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

确保克隆 attributes() 的结果,否则你修改 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)}
于 2012-07-22T23:07:44.333 回答
5

只需在您的模型中包含这样的内容:

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
于 2012-11-07T01:34:57.720 回答
1

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

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

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

于 2012-07-05T14:22:27.850 回答
0

尝试 .methods 或 .instance_variables

于 2012-07-04T00:07:40.997 回答
0

不确定我是否喜欢克隆方法,所以我也写了一个。由此,您也可以轻松构建内容的散列。这仅输出所有动态字段(平面结构)

 (d.attributes.keys - d.fields.keys).each {|a| puts "#{a} = #{d[a]}"};
于 2012-08-27T13:34:21.340 回答
0

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

助手/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 (i.e. {"_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

模型/用户.rb

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

一旦我将上述包含 ( include MongoidAttributeHelper) 添加到我想使用此方法的每个模型中,我可以使用User.get_all_attributes.

当然,这可能不是最有效或最优雅的方法,但它确实有效。:)

于 2015-03-18T20:28:52.650 回答