Reputation: 666
I have an issue with mongoid / rails relations, I know that there are a lot of topics with this kind of issue, but I don't find any that help me .. I have these models :
class Project
include Mongoid::Document
belongs_to :owner, :class_name => 'User', inverse_of: :projects
has_many :members
end
class Member
include Mongoid::Document
belongs_to :project, inverse_of: :members
belongs_to :user
end
class User
include Mongoid::Document
has_many :projects, inverse_of: :user
end
When I try to record an user as a member, I have this error :
Mongoid::Errors::InverseNotFound (
message:
When adding a(n) User to Project#members, Mongoid could not determine the inverse foreign key to set. The attempted key was 'project_id'.
summary:
When adding a document to a relation, Mongoid attempts to link the newly added document to the base of the relation in memory, as well as set the foreign key to link them on the database side. In this case Mongoid could not determine what the inverse foreign key was.
resolution:
If an inverse is not required, like a belongs_to or has_and_belongs_to_many, ensure that :inverse_of => nil is set on the relation. If the inverse is needed, most likely the inverse cannot be figured out from the names of the relations and you will need to explicitly tell Mongoid on the relation what the inverse is.
Example:
class Lush
include Mongoid::Document
has_one :whiskey, class_name: "Drink", inverse_of: :alcoholic
end
class Drink
include Mongoid::Document
belongs_to :alcoholic, class_name: "Lush", inverse_of: :whiskey
end):
I don't understand why, I think something is wrong with the relations, and the inverses relation but I don't know how to fix this issue.
Upvotes: 2
Views: 1593
Reputation: 102026
class Project
include Mongoid::Document
belongs_to :owner, :class_name => 'User', inverse_of: :projects
has_many :members
has_many :users
end
But I don't think your modeling actually will accomplish what you want. In a relational database you would use an indirect association with a join table:
class User < ActiveRecord::Base
has_many :memberships
has_many :projects, through: :memberships
end
class Membership < ActiveRecord::Base
belongs_to :user
belongs_to :project
end
class Project < ActiveRecord::Base
has_many :memberships
has_many :members, through: :memberships,
source: :user
end
But over in Mongoland there are no joins so we we need to use a different approach which is embedding:
class Project
# ...
embeds_many :users
end
class User
# ...
embedded_in :project
end
Or you can fake an indirect association if you need to be able to add data to the intermediate model:
class Project
# ...
embeds_many :memberships
def members
Patient.in(id: memberships.pluck(:user_id))
end
end
class Membership
# ...
field :approved, type: Boolean
belongs_to :user
embedded_in :project
end
class User
# ...
def projects
Project.where("members.user_id" => id).all
end
end
Upvotes: 2