Dynamic attributes with Rails and Mongoid
Solution 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 => "...")
Solution 2
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")
Solution 3
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
...
Solution 4
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
joeellis
Updated on June 14, 2022Comments
-
joeellis almost 2 years
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?