Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

MongoDB and Mongoid - Dynamic Fields

I'm using MongoDB but I'm not really using it's dynamic fields capabilities

  field :fb_followers => Integer
  field :twitter_followers => Integer
  field :twitter_rts => Integer
  field :link_visiting => Integer
  field :reduce_points_per_day => Integer

How do I write this so each of those fields is optional for the model?

like image 680
CamelCamelCamel Avatar asked Jun 23 '26 10:06

CamelCamelCamel


1 Answers

So here's some Mongoid-specific information. First of all, make sure allow_dynamic_fields is set to true in your configuration (it defaults to true, but always good to be sure).

Here's the world's simplest Mongoid class, for my examples:

class Foobj
  include Mongoid::Document
  field :static_field
end

So, we can of course set our static_field normally:

ruby-1.9.2-p290 :012 > f = Foobj.create!(:static_field => 'barbaz!')
 => #<Foobj _id: 4ec1f2eb90a110143b000003, _type: nil, regular_field: nil, static_field: "barbaz!">

But we can't do a dynamic field "on the fly" because Mongoid doesn't know about it yet.

ruby-1.9.2-p290 :013 > f.dynamic_field = "hi"
NoMethodError: undefined method `dynamic_field=' for #<Foobj:0x000000044e7ee8>

However, I can use write_attribute to write a dynamic field:

ruby-1.9.2-p290 :014 > f.write_attribute(:dynamic_field,"hi!")
 => "hi!"
ruby-1.9.2-p290 :015 > f
 => #<Foobj _id: 4ec1f2eb90a110143b000003, _type: nil, regular_field: nil, static_field: "barbaz!", dynamic_field: "hi!">

And, now that I've "created" that field in Mongoid, I can now use the regular mechanism for accessing a field, even though it's not in my class definition:

ruby-1.9.2-p290 :017 > f.dynamic_field
 => "hi!"

Also, note that if you load a Mongoid document with non-Mongoid-specified fields, you can indeed access them the same way:

ruby-1.9.2-p290 :028 > g = Foobj.first
 => #<Foobj _id: 4ec1f2eb90a110143b000003, _type: nil, regular_field: nil, dynamic_field: "hi!", static_field: "barbaz!">
ruby-1.9.2-p290 :029 > g.dynamic_field
 => "hi!"

However, the safest way to work with dynamic fields is using write_attribute and read_attribute (or their shortcuts, []= and []) as these won't throw NoMethodErrors if the field doesn't exist.

Hope that helps. It's really pretty simple when you get used to it. For more info, see: http://mongoid.org/docs/documents/dynamic.html

like image 141
tkrajcar Avatar answered Jun 25 '26 02:06

tkrajcar