Mongoid HABTM relationships across embedded documents

287 views Asked by At

I'm trying to create a Mongoid N-N reference association between two embedded documents in Rails 4 however I'm finding it difficult to get my head round how this is done.

I started by adding the HABTM association to the relevant models below (Track and Option) but of course I'm getting the error saying this isn't allowed because they're both embedded.

class Brief
  embeds_many :tracks
end

class Track
  embedded_in :brief
  has_and_belongs_to_many :options
end

and

class Category
  embeds_many :options
end

class Option
  field :name, type: String
  field :track_ids, type: Array
  embedded_in :category
  has_and_belongs_to_many :tracks

  def parent
    self.category
  end

  def tracks
    self.parent.tracks.where(:option_id => self.id)
  end
end

I completely understand why this is and know I need to reference the parent documents but here is where I run into trouble.

Ive been trying to add track ids to the track_ids via the console array but I end up getting the same error as before:

"Problem: Referencing a(n) Track document from the Option document via a relational association is not allowed since the Track is embedded. Summary: In order to properly access a(n) Track from Option the reference would need to go through the root document of Track. In a simple case this would require Mongoid to store an extra foreign key for the root, in more complex cases where Track is multiple levels deep a key would need to be stored for each parent up the hierarchy."

I would be happy to store the extra foreign key but I have no idea how and in what format. If anybody can point me in the right direction I would appreciate it.

1

There are 1 answers

1
ilan berci On BEST ANSWER

The reason you are getting the error is because of the logic below. If you are going to need to represent many-to-many relations, do not use a document model to store your state. Use a relational one

===

You can't represent a many to many relation without an association/reference table/object. If you don't have a reference table, then your update to either end could cause an infinite update as all your relations (and then their relations) will be touched (and possibly re-saved)

For example,

Track 1, => Option 1, 2, 3

Option 1, => Track 1, 2, 3

Track 2, => Option 1, 2

Option 2, => Track 1, 2

Track 3, => Option 1, 3, 4

Option 3, => Track 1, 3, 4

Now let's go ahead and edit Track 1,

1) update Track 1

2) Causes update in options 1, 2, 3

3) option 1 caused re=update of track 1, (infinite repeat of 1,2,3)

4) option 2 causes update of Tracks 1, 2 (infinite repeat again)

5) etc...