Dynamic attributes with Rails and Mongoid
Asked Answered
M

4

16

I'm learning MongoDB through the Mongoid Ruby gem with Rails (Rails 3 beta 3), and I'm trying to come up with a way to create dynamic attributes on a model based on fields from another model, which I thought a schema-less database would be a good choice for.

So for example, I'd have the models:

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

I'm looking to take the "info_needed" attribute of the Account model and created dynamic attributes on the Member model based on what's inside. If club.info_needed was ["first_name", "last_name"], I'm trying to create a form that would save first_name and last_name attributes to the Member model.

However, upon practice, I just keep getting "undefined method first_name=" errors on the Member model when trying to do this. I know MongoDB can handle dynamic attributes per record, but how can I get Mongoid to do this without an undefined method error?

Minesweeper answered 23/4, 2010 at 14:16 Comment(1)
I'd ask that you select my answer below as the answer as it's more accurate than the currently selected answer.Kinnard
G
1

Mongoid doesn't really support it.

I happen to have asked this at Mongoid group myself.

It is possible when you create new document, like this:

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

Geometrician answered 24/5, 2010 at 14:30 Comment(0)
K
31

Mongoid now supports Dynamic Fields. Their documentation can be found here: http://mongoid.org/en/mongoid/docs/documents.html#dynamic_fields

Basically it warns that you have to be slightly careful how you set dynamic fields as it will raise a no method error if you attempt to use the getter and setter methods for a field that did not exist in the document.

[],[]= are shortcuts for read_attribute(),write_attribute() , and should be used if you do not set dynamic_attributes = true in your ./config/mongoid.yml file , otherwise you'll get a no method error.

Setting allow_dynamic_fields: true can be risky, as you might pollute your data/schema with unintended fields caused by bugs in your code. It's probably safer to set this to false and explicitly use [],[]=

# 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")
Kinnard answered 7/4, 2011 at 18:23 Comment(1)
It's been removed in 4.0Endogamy
S
9

Be sure to set allow_dynamic_fields: true in mongoid.yml. Example:

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

...
Sokul answered 19/5, 2010 at 19:30 Comment(2)
Yea, I had done that, but was still having trouble. If you've done this though, and it's been working for you, perhaps mongoid was updated since I posted this question.Minesweeper
downside to setting allow_dynamic_attributes: true is that it is per database, and that you might pollute your schema with unintended fields, caused through bugs in your code. Probably safer to set this to false and to consciously use [],[]=Ramos
R
2

interesting article about Dynamic Attributes with Mongoid and Rails 3.1: http://paul-wong-jr.blogspot.com/2012/03/dynamic-attributes-and-mongodbmongoid.html

To access only the dynamic key/value pairs or dynamic attribute names, see also: List dynamic attributes in a Mongoid Model

Ramos answered 23/7, 2012 at 0:12 Comment(0)
G
1

Mongoid doesn't really support it.

I happen to have asked this at Mongoid group myself.

It is possible when you create new document, like this:

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

Geometrician answered 24/5, 2010 at 14:30 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.