如何使attribute_names列出具有动态属性的文档中的所有属性名称

时间:2015-04-16 11:30:16

标签: ruby-on-rails-4 mongoid dynamic-attributes

我有一个带有mongoid的Rails 4.2应用程序,我在其中导入带有测试结果的csv文件。我无法定义模型中的所有字段,因为它们从测试变为测试,并且总是大约700个字段。我使用动态属性,导入和显示工作正常。

我正在尝试使用attribute_names方法获取所有属性名称,但我得到的只是模型中定义的那些。如果我没有在模型中定义任何内容,则仅返回“_id”。另一方面,attributes方法可以在实际文档中看到属性。

>> @results.first.attributes.count
=> 763
>> @results.first.attribute_names
=> ["_id"]

我也尝试过fields.keys,同样的问题

>> @results.first.fields.keys
=> ["_id"]

我的模特目前看起来像这样

class Result
  include Mongoid::Document
  include Mongoid::Attributes::Dynamic

  def self.import(file)
    CSV.foreach(file.path, headers: true) do |row|
        Result.create! row.to_hash
    end
  end
end

有人可以解释如何让它发挥作用吗?

非常感谢任何帮助。

1 个答案:

答案 0 :(得分:0)

这部分在文档中不是很清楚。 这个答案没有解决你如何使你的案件有效(我真的不知道)...... 但最后有一个猴子补丁...

所有我知道的是为什么这个案例工作......

作为documentation states

  

处理动态属性时,以下规则适用:

     

如果文档中存在该属性,Mongoid将为您提供标准的getter和setter方法。

     

例如,考虑在文档上设置了“性别”属性的人:

# Set the person's gender to male.
person[:gender] = "Male"
person.gender = "Male"

# Get the person's gender.
person.gender

这不是你的情况......因为看起来你没有在模型中定义任何属性......

适用于您的情况(根据您展示的代码和您描述的问题)

  

如果文档上尚不存在该属性,

     

Mongoid不会为您提供getter和setter ,并会强制执行正常的method_missing行为。

     

在这种情况下,您必须使用其他提供的访问者方法:([][]=)或(read_attributewrite_attribute)。

# Raise a NoMethodError if value isn't set.
person.gender
person.gender = "Male"

# Retrieve a dynamic field safely.
person[:gender]
person.read_attribute(:gender)

# Write a dynamic field safely.
person[:gender] = "Male"
person.write_attribute(:gender, "Male")

正如你所看到的...... mongoid无法在运行时添加setter和getter方法......

猴子补丁

  • 你可以在文档中添加一个字段(可能是字符串,数组,哈希,无论你是什么套件)(文档中存在属性)
  • 从CSV行填充文档..只需保存该字段中CSV的字段...(将CSV键保存在其中)
  • 使用您预定义的字段(包含密钥),而不是使用.keys

您的案例中的代码示例。

class Result
  include Mongoid::Document
  include Mongoid::Attributes::Dynamic

  field :the_field_that_holds_the_keys, type: Array
  # ...
end

并在您的控制器中:

@results.first.some_attribute
#=> method missing error
@results.first[:some_attribute]
#=> some_value
@results.first.the_field_that_holds_the_keys
#=> [:some_attribute, :some_other_attribute, :yada]