Монгоидная реляционная полиморфная ассоциация - PullRequest
5 голосов
/ 30 сентября 2010

Кто-нибудь знает, как сделать полиморфную ассоциацию в Mongoid, имеющую реляционную пользу, но не встраивающую.

Например, это моя Assignment модель:

class Assignment
  include Mongoid::Document
  include Mongoid::Timestamps

  field :user
  field :due_at, :type => Time

  referenced_in :assignable, :inverse_of => :assignment
end

, которая может иметь полиморфную связь с несколькими моделями:

class Project
  include Mongoid::Document
  include Mongoid::Timestamps

  field :name, :type => String

  references_many :assignments
end

Выдает ошибку, сообщающую неизвестную константу Assignable. Когда я изменяю reference на embed, все это работает, как описано в документации Mongoid , но мне нужно, чтобы оно было reference.

Спасибо!

Ответы [ 3 ]

20 голосов
/ 05 марта 2012

Отвечая на древний пост, но кто-то может найти его полезным.

Теперь есть и полиморфный 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
4 голосов
/ 27 декабря 2010

Похоже, что из Mongoid Google Group это не поддерживается. Вот новейший соответствующий пост Я нашел.

В любом случае, это не сложно реализовать вручную. Вот моя полиморфная ссылка под названием Тема.

Реализация обратной части отношения может быть несколько более сложной, особенно потому, что вам понадобится один и тот же код для нескольких классов.

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
1 голос
/ 03 марта 2017

Rails 4 +

Вот как вы бы реализовали Полиморфные ассоциации in Mongoid для модели Comment, которая может принадлежать как Post, так и *Модель 1009 *.

Модель Comment:

class Comment
  include Mongoid::Document
  belongs_to :commentable, polymorphic: true

  # ...
end

Post / Event Модели:

class Post
  include Mongoid::Document
  has_many :comments, as: :commentable

  # ...
end

ИспользованиеПроблемы:

В Rails 4+ вы можете использовать шаблон Concern и создать новый модуль с именем commentable в app/models/concerns:

module Commentable
  extend ActiveSupport::Concern

  included do
    has_many :comments, as: :commentable
  end
end

и просто includeэтот модуль в ваших моделях:

class Post
  include Mongoid::Document
  include Commentable

  # ...
end
...