-
Type: Task
-
Resolution: Done
-
Affects Version/s: None
-
Component/s: None
-
None
Hi, I'm a relative noob wrt Mongoid (polymorphic) relations and having some trouble. I'm not sure if I'm doing something wrong or there's a bug, but there seems to be a workaround. I have a parent Activity which is simplified here for discussion and a child Contact, also simplified.
class Activity include Mongoid::Document attr_accessible :contacts embeds_many :contacts, as: :contactable, validate: true, class_name: 'Contact' end class Contact include Mongoid::Document attr_accessor :name, :sites field :name, type: String field :sites, type: Array embedded_in :contactable, polymorphic: true end
Note: I added "validate" and "class_name" attributes to the embeds_many clause from other posts I found which don't seem to help/affect my issue.
In my seeds.rb rake task I generate many activities and want to embed contacts. When I set up a contact using method assignment syntax, it doesn't work as documented. Here a is a new Activity and activity is a hash of mock data:
c = Contact.new c.name = CONTACT_NAME c.sites = [ activity[:link] ] puts "contact #{c.inspect}" a.contacts << c puts "activity #{a.inspect}" a.save! # results (fail): contact #<Contact _id: 506861fd05b58e472a000012, _type: nil, salu: nil, name: nil, title: nil, phones: nil, email: nil, sites: nil> activity #<Activity _id: 506861fd05b58e472a000013, _type: nil, created_at: nil, updated_at: nil, tags: ["gumps", "macys", "nordstrom"], title: {"en"=>"Shopping in Union Square5"}, type: "a", cat: "shopping", author: "506861f705b58e472a000001", desc: {"en"=>nil}, cost: 0.0, notes: {"en"=>"Take BART"}, dur: 30, views: 0, icon: nil, public: nil, protected: nil, address: "Union Square, San Francisco, CA", icon_filename: nil> MOPED: 127.0.0.1:27017 INSERT database=fixer_development collection=activities documents=[{"_id"=>"506861fd05b58e472a000013", "type"=>"a", "cat"=>"shopping", "cost"=>0.0, "dur"=>30, "views"=>0, "protected"=>nil, "title"=>{"en"=>"Shopping in Union Square5"}, "address"=>"Union Square, San Francisco, CA", "author"=>"506861f705b58e472a000001", "desc"=>{"en"=>nil}, "tags"=>["gumps", "macys", "nordstrom"], "notes"=>{"en"=>"Take BART"}, "coordinates"=>[-122.4074374, 37.7879938], "icon_filename"=>"images", "updated_at"=>2012-09-30 15:15:10 UTC, "created_at"=>2012-09-30 15:15:10 UTC, "contacts"=>[{"_id"=>"506861fd05b58e472a000012"}]}] flags=[] (0.3278ms)
Notice above that the embedded activity being written to Mongo contains a contact with only an _id field. Other variations fail too:
a.contacts = [ Contact.new(name: CONTACT_NAME, sites: [ activity[:link] ]) ] a.save! # results (fail): activity #<Activity _id: 506863da05b58e722a00000c, _type: nil, created_at: nil, updated_at: nil, tags: ["gumps", "macys", "nordstrom"], title: {"en"=>"Shopping in Union Square2"}, type: "a", cat: "shopping", author: "506863d605b58e722a000001", desc: {"en"=>nil}, cost: 0.0, notes: {"en"=>"Take BART"}, dur: 30, views: 0, icon: nil, public: nil, protected: nil, address: "Union Square, San Francisco, CA", icon_filename: nil> MOPED: 127.0.0.1:27017 INSERT database=fixer_development collection=activities documents=[{"_id"=>"506863da05b58e722a00000c", "type"=>"a", "cat"=>"shopping", "cost"=>0.0, "dur"=>30, "views"=>0, "protected"=>nil, "title"=>{"en"=>"Shopping in Union Square2"}, "address"=>"Union Square, San Francisco, CA", "author"=>"506863d605b58e722a000001", "desc"=>{"en"=>nil}, "tags"=>["gumps", "macys", "nordstrom"], "notes"=>{"en"=>"Take BART"}, "coordinates"=>[-122.4074374, 37.7879938], "icon_filename"=>"images", "updated_at"=>2012-09-30 15:23:07 UTC, "created_at"=>2012-09-30 15:23:07 UTC, "contacts"=>[{"_id"=>"506863db05b58e722a00000d"}]}] flags=[] (0.3219ms)
And this:
a.contacts.build(name: CONTACT_NAME, sites: [ activity[:link] ]) puts "activity #{a.inspect}" a.save! # results (fail): activity #<Activity _id: 506863da05b58e722a00000c, _type: nil, created_at: nil, updated_at: nil, tags: ["gumps", "macys", "nordstrom"], title: {"en"=>"Shopping in Union Square2"}, type: "a", cat: "shopping", author: "506863d605b58e722a000001", desc: {"en"=>nil}, cost: 0.0, notes: {"en"=>"Take BART"}, dur: 30, views: 0, icon: nil, public: nil, protected: nil, address: "Union Square, San Francisco, CA", icon_filename: nil> MOPED: 127.0.0.1:27017 INSERT database=fixer_development collection=activities documents=[{"_id"=>"506863da05b58e722a00000c", "type"=>"a", "cat"=>"shopping", "cost"=>0.0, "dur"=>30, "views"=>0, "protected"=>nil, "title"=>{"en"=>"Shopping in Union Square2"}, "address"=>"Union Square, San Francisco, CA", "author"=>"506863d605b58e722a000001", "desc"=>{"en"=>nil}, "tags"=>["gumps", "macys", "nordstrom"], "notes"=>{"en"=>"Take BART"}, "coordinates"=>[-122.4074374, 37.7879938], "icon_filename"=>"images", "updated_at"=>2012-09-30 15:23:07 UTC, "created_at"=>2012-09-30 15:23:07 UTC, "contacts"=>[{"_id"=>"506863db05b58e722a00000d"}]}] flags=[] (0.3219ms)
When I avoid the method name approach to setting values and switch to hash-symbol notion it appears to work:
c = Contact.new c[:name] = CONTACT_NAME c[:sites] = [ activity[:link] ] puts "contact #{c.inspect}" a.contacts << c puts "activity #{a.inspect}" a.save! # results (success): contact #<Contact _id: 5068616d05b58e352a000010, _type: nil, salu: nil, name: "Jimmy Bag of Donuts", title: nil, phones: nil, email: nil, sites: ["http://www.unionsquareshop.com"]> activity #<Activity _id: 5068616d05b58e352a000011, _type: nil, created_at: nil, updated_at: nil, tags: ["gumps", "macys", "nordstrom"], title: {"en"=>"Shopping in Union Square4"}, type: "a", cat: "shopping", author: "5068616b05b58e352a000005", desc: {"en"=>nil}, cost: 0.0, notes: {"en"=>"Take BART"}, dur: 75, views: 0, icon: nil, public: nil, protected: nil, address: "Union Square, San Francisco, CA", icon_filename: nil> MOPED: 127.0.0.1:27017 INSERT database=fixer_development collection=activities documents=[{"_id"=>"5068616d05b58e352a000011", "type"=>"a", "cat"=>"shopping", "cost"=>0.0, "dur"=>75, "views"=>0, "protected"=>nil, "title"=>{"en"=>"Shopping in Union Square4"}, "address"=>"Union Square, San Francisco, CA", "author"=>"5068616b05b58e352a000005", "desc"=>{"en"=>nil}, "tags"=>["gumps", "macys", "nordstrom"], "notes"=>{"en"=>"Take BART"}, "coordinates"=>[-122.4074374, 37.7879938], "icon_filename"=>"images", "updated_at"=>2012-09-30 15:12:46 UTC, "created_at"=>2012-09-30 15:12:46 UTC, "contacts"=>[{"_id"=>"5068616d05b58e352a000010", "name"=>"Jimmy Bag of Donuts", "sites"=>["http://www.unionsquareshop.com"]}]}] flags=[] (0.3412ms)
Perhaps I'm not properly persisting the child contact? I've never had this problem with non-relational Mongoid classes. Did I miss something obvious?
I'm also not sure why inspect doesn't show the values I set in the new child contact object, but assuming this has something to do with dirty tracking since it is being persisted in the save call (in the final example that works).
I'm using the following:
ruby "1.9.3" gem 'rails', '3.2.8' gem 'bson', '1.7.0' gem 'bson_ext', '1.7.0' gem 'mongo', '1.7.0' gem 'mongoid', "~> 3.0.0"
UPDATE: I discovered that you said mongo, bson and bson_ext aren't needed. I removed those but this problem persists.
Thanks for any help. Please let me know if I can provide additional information.