Does anyone know how to do a polymorphic association in Mongoid
that is of the relational favor but not the embedding one.
For instance this is my Assignment
model:
class Assignment
include Mongoid::Document
include Mongoid::Timestamps
field :user
field :due_at, :type => Time
referenced_in :assignable, :inverse_of => :assignment
end
that can have a polymorphic relationship with multiple models:
class Project
include Mongoid::Document
include Mongoid::Timestamps
field :name, :type => String
references_many :assignments
end
This throws an error saying unknown constant Assignable. When I change the reference
to embed
, this all works as documented in Mongoid's documentation, but I need it to be reference
.
Thanks!
Answering to an ancient post, but someone may find it useful.
Now there's also a polymorphic belongs_to
:
class Action
include Mongoid::Document
include Mongoid::Timestamps::Created
field :action, type: Symbol
belongs_to :subject, :polymorphic => true
end
class User
include Mongoid::Document
include Mongoid::Timestamps
field :username, type: String
has_many :actions, :as => :subject
end
class Company
include Mongoid::Document
include Mongoid::Timestamps
field :name, type: String
has_many :actions, :as => :subject
end
From Mongoid Google Group it looks like this is not supported. Here's the newest relevant post I found.
Anyway, this is not to hard to implement manually. Here's my polymorphic link called Subject.
Implementing inverse part of relation might be somewhat more complicated, especially because you will need same code across multiple classes.
class Notification
include Mongoid::Document
include Mongoid::Timestamps
field :type, :type => String
field :subject_type, :type => String
field :subject_id, :type => BSON::ObjectId
referenced_in :sender, :class_name => "User", :inverse_of => :sent_notifications
referenced_in :recipient, :class_name => "User", :inverse_of => :received_notifications
def subject
@subject ||= if subject_type && subject_id
subject_type.constantize.find(subject_id)
end
end
def subject=(subject)
self.subject_type = subject.class.name
self.subject_id = subject.id
end
end
Here's how you would implement Polymorphic Associations in Mongoid for a Comment
model that can belong to both a Post
and Event
model.
The Comment
Model:
class Comment
include Mongoid::Document
belongs_to :commentable, polymorphic: true
# ...
end
Post
/ Event
Models:
class Post
include Mongoid::Document
has_many :comments, as: :commentable
# ...
end
Using Concerns:
In Rails 4+, you can use the Concern pattern and create a new module called commentable
in app/models/concerns
:
module Commentable
extend ActiveSupport::Concern
included do
has_many :comments, as: :commentable
end
end
and just include
this module in your models:
class Post
include Mongoid::Document
include Commentable
# ...
end
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With