Reputation: 5528
I have a embeds_many association and when I save the parent document the children are not being saved.
class User
include Mongoid::Document
embeds_many :user_missions
attr_accessible :user_missions_attributes
accepts_nested_attributes_for :user_missions, allow_destroy: true
end
class UserMission
include Mongoid::Document
embedded_in :user, :inverse_of => :user_missions
has_one :mission, autosave: true
validates_presence_of :mission
attr_accessible :mission_title
def mission_title
mission.try(:title)
end
def mission_title=(title)
self.mission = Mission.find_or_create_by(:title => title) if title.present?
end
end
Here is the spec I'm failing:
it "should save mission to user_mission when created" do
user_mission = UserMission.new
user = create(:user)
user.user_missions << user_mission
user_mission.mission_title = "Created Title"
user.save!
#user_mission.save!
User.first.user_missions[0].mission.title.should == "Created Title"
end
I get:
undefined method `title' for nil:NilClass
When I comment in the line #user_mission.save!
it works. The problem is I need this to work in a form and I thought Mongoid automatically saved embedded document's fields.
How do I get the parent User document to save the embedded UserMission's data?
Thanks
UPDATE
Here is the Mission model I forgot to add (wasn't sure if it was important):
class Mission
include Mongoid::Document
belongs_to :user_mission, :inverse_of => :mission
attr_accessible :title
field :title, type: String
validates_presence_of :title
field :lowercase_title
before_create :lower_title_case
field :description, type: String
private
def lower_title_case
self.lowercase_title = self.title.downcase
end
end
Upvotes: 1
Views: 3709
Reputation: 1096
AFAIK, embedded documents can't have referenced relations. So the calls to embedded_in
and has_one
are contradictory.
Other than that, have you tried reordering the lines in your test so that the user gets created first, and then you create user_misison
through the user?
user = create(:user)
user_mission = user.user_missions.new
user_mission.mission_title = "Created Title"
user.save!
It looks like what you're trying to do is similar to an SQL JOIN table. If this is what you're trying to achieve, it would be better to take advantage of Mongoid's awesome N-N referenced mapping (unless you need to store extra data in the 'join' collection). I'd do something like:
class User
include Mongoid::Document
has_and_belongs_to_many :missions
end
class Mission
include Mongoid::Document
has_and_belongs_to_many :users
end
If you want to create missions through users, then turn on autosave on the Mission side of the relation.
EDIT: After seeing your Mission model, I realize you're trying to directly reference UserMission (belongs_to :user_mission
), an embedded document, directly from your Mission model. Like I said earlier, not doable. You need some relation between the top level docs, User and Mission. You could probably get things to work by changing that line to:
has_many :users
and then changing has_one :mission
from the User model to:
belongs_to :mission
You won't be able to use autosave from the User side though.
EDIT: Corrected for proper way to show right way to do 1-n relation from users to missions.
Upvotes: 1