我已经阅读了文档,我找不到具体的方法来解决这个问题。我已经为模型添加了一些动态属性,我希望能够遍历所有这些属性。
所以,举一个具体的例子:
class Order
include Mongoid::Document
field :status, type: String, default: "pending"
end
然后我会做以下事情:
Order.new(status: "processed", internal_id: "1111")
后来我想回来并且能够获得所有动态属性的列表/数组(在这种情况下,“internal_id”就是它)。
我还在挖掘,但我很想知道其他人是否已经解决了这个问题。
答案 0 :(得分:5)
这将只为您提供给定记录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)}
答案 1 :(得分: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
答案 2 :(得分:1)
所以,我最终做的就是这个。我不确定这是否是最佳方式,但它似乎给了我正在寻找的结果。
class Order
def dynamic_attributes
self.attributes.delete_if { |attribute|
self.fields.keys.member? attribute
}
end
end
属性似乎是对象上实际属性的列表,而字段似乎是预定义字段的哈希值。无法在文档中找到它,但我现在正在使用它,除非有人知道更好的方法!
答案 3 :(得分:0)
尝试.methods或.instance_variables
答案 4 :(得分:0)
不确定我是否喜欢克隆方法,所以我也写了一个。从这里你可以轻松地构建内容的哈希值。这只是输出所有动态字段(平面结构)
(d.attributes.keys - d.fields.keys).each {|a| puts "#{a} = #{d[a]}"};
答案 5 :(得分:0)
我无法使上述任何解决方案起作用(因为我不想为每个模型添加slab和slab代码,并且出于某种原因,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(include MongoidAttributeHelper
)添加到我想使用此方法的每个模型中,我就可以使用User.get_all_attributes
获取所有字段的列表。
当然,这可能不是最有效或最优雅的方法,但绝对有效。 :)