在Mongoid型号列表动态属性(List dynamic attributes in a Mong

2019-07-30 05:32发布

我已经在文件上,我无法找到一个特定的方式去了解这一点。 我已经增加了一些动态属性的模型,我希望能够遍历他们在所有。

所以,对于一个具体的例子:

class Order
  include Mongoid::Document

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

然后我做到以下几点:

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

而后来我想回来,能够得到所有的动态属性的列表/阵列(在这种情况下,“INTERNAL_ID”是吧)。

我还在挖,但我很乐意听到的话,任何人都已经解决了这个了。

Answer 1:

只需在您的模型是这样的:

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


Answer 2:

这会给你只给定记录x中的动态字段名:

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

如果你使用其他Mongoid功能,你需要减去与这些功能相关的领域:例如用于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)}


Answer 3:

所以,我最后做的就是这个。 我不知道,如果是去了解它的最佳方式,但它似乎给我,我要找的结果。

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

属性似乎是在对象上的实际属性的列表,而场似乎是被预先定义的字段的哈希值。 不能准确找到的文档中,但我用它去了,现在除非别人知道的更好的方法!



Answer 4:

尝试。方法或.instance_variables



Answer 5:

不知道如果我喜欢的克隆方法,所以我写了一个了。 从这里就可以很容易地构建内容的哈希过。 这仅仅输出它的所有动态字段(平面结构)

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


Answer 6:

我是不是能够得到任何上述溶液的工作(因为我不希望有地砖和地砖的代码添加到每个模型,并且,出于某种原因,该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

车型/ user.rb:

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

一旦我已经添加了上述包括( include MongoidAttributeHelper ),以每一个我想用此方法,我可以使用所有字段的列表模式User.get_all_attributes

当然,这可能不是最有效的还是高雅的方法,但它肯定工程。 :)



文章来源: List dynamic attributes in a Mongoid Model