使用Rails和Mongoid的动态属性

时间:2010-04-23 14:16:27

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

我正在通过带有Rails(Rails 3 beta 3)的Mongoid Ruby gem学习MongoDB,我正试图想出一种基于另一个模型的字段在模型上创建动态属性的方法,我认为无模式数据库将是一个不错的选择。

例如,我有模型:

class Account
  include Mongoid::Document

  field :name, :type => String
  field :token, :type => String
  field :info_needed, :type => Array

  embeds_many :members
end

class Member
  include Mongoid::Document

  embedded_in :account, :inverse_of => :members

end

我希望获取Account模型的“info_needed”属性,并根据内部的内容在Member模型上创建动态属性。如果club.info_needed是[“first_name”,“last_name”],我正在尝试创建一个将first_name和last_name属性保存到Member模型的表单。

然而,在练习时,我只是在尝试执行此操作时不断在Member模型上获得“undefined method first_name =”错误。我知道MongoDB可以处理每条记录的动态属性,但是如何在没有未定义的方法错误的情况下让Mongoid执行此操作?

4 个答案:

答案 0 :(得分:28)

Mongoid现在支持动态字段。他们的文档可以在这里找到: http://mongoid.org/en/mongoid/docs/documents.html#dynamic_fields

基本上它警告你必须要小心谨慎设置动态字段,因为如果你试图对文档中不存在的字段使用getter和setter方法,它会引发no方法错误。

[],[] =是read_attribute(),write_attribute()的快捷方式,如果您未在dynamic_attributes = true中设置./config/mongoid.yml file,则应该使用它,否则您将获得没有方法错误。

设置allow_dynamic_fields: true可能会有风险,因为您可能会因代码中的错误导致的非预期字段污染您的数据/架构。将此设置为false并明确使用[],[] =

可能更安全
# 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")

答案 1 :(得分:8)

务必在allow_dynamic_fields: true中设置mongoid.yml。例如:

defaults: &defaults
  allow_dynamic_fields: true
  parameterize_keys: true
  persist_in_safe_mode: true
  raise_not_found_error: true
  reconnect_time: 3
  use_object_ids: false

development:
  <<: *defaults

...

答案 2 :(得分:1)

Mongoid并不真正支持它。

我自己在Mongoid小组碰巧有asked这个。

创建新文档时可以这样:

account = Account.new(:some_dynamic_field => "...")

答案 3 :(得分:1)

有关Mongoid和Rails 3.1的动态属性的有趣文章:http://paul-wong-jr.blogspot.com/2012/03/dynamic-attributes-and-mongodbmongoid.html

要仅访问动态键/值对或动态属性名称,另请参阅:  List dynamic attributes in a Mongoid Model