Question

I have two models as below:

class Tag
  include Mongoid::Document
  include Mongoid::Timestamps
  belongs_to :group
end

class Group
  include Mongoid::Document
  include Mongoid::Timestamps

  has_one :user_tag, :class_name => 'Tag', :foreign_key => "user_tag_id", :inverse_of => nil
  has_one :tag_tag, :class_name => 'Tag', :foreign_key => "tag_tag_id", :inverse_of => nil
  has_one :group_tag, :class_name => 'Tag', :foreign_key => "group_tag_id", :inverse_of => nil
end

But this and other attempts haven't seemed to yield the desired result of having 3 different types of Group separately referencable. Any help would be very much appreciated!

Was it helpful?

Solution

I think that the following does what you want, albeit with three additional trivial models/subclasses. My attempts to do this with just the Tag class and no subclasses ran into collisions and other issues with the inverse relationship, even when loosening restrictions with polymorphism. Maybe the three additional trivial subclasses are OK for your purposes? Note that the tag data is still stored in the one 'tag' collection as specified by the 'store_in' method.

app/models/group.rb

class Group
  include Mongoid::Document
  include Mongoid::Timestamps
  field :name, type: String

  has_one :user_tag
  has_one :tag_tag
  has_one :group_tag
end

app/models/tag.rb

class Tag
  include Mongoid::Document
  include Mongoid::Timestamps
  field :text, type: String

  belongs_to :group
  store_in collection: 'tag'
end

app/models/group_tag.rb

class GroupTag < Tag
end

app/models/tag_tag.r

class TagTag < Tag
end

app/models/user_tag.rb

class UserTag < Tag
end

test/unit/group_test.rb

require 'test_helper'
require 'pp'

class GroupTest < ActiveSupport::TestCase
  def setup
    Mongoid.default_session.drop
  end
  test '0. mongoid version' do
    puts "\nMongoid::VERSION:#{Mongoid::VERSION}\nMoped::VERSION:#{Moped::VERSION}"
  end
  test 'multiple tag references' do
    group = Group.create(name: 'my group')
    group.user_tag = UserTag.create(text: 'user tag')
    group.tag_tag = TagTag.create(text: 'tag tag')
    group.group_tag = GroupTag.create(text: 'group tag')
    assert_equal(1, Group.count)
    assert_equal(3, Tag.count)
    puts
    puts "Group:"
    pp Group.all.to_a
    puts "Tag:"
    pp Tag.all.to_a
    puts "collections: #{Mongoid.default_session.collection_names.inspect}"
  end
end

rake test

Run options:

Running tests:

[1/2] GroupTest#test_0._mongoid_version
Mongoid::VERSION:3.1.6
Moped::VERSION:1.5.2
[2/2] GroupTest#test_multiple_tag_references
Group:
[#<Group _id: 53f242b27f11ba5f31000001, created_at: 2014-08-18 18:15:14 UTC, updated_at: 2014-08-18 18:15:14 UTC, name: "my group">]
Tag:
[#<UserTag _id: 53f242b27f11ba5f31000002, created_at: 2014-08-18 18:15:14 UTC, updated_at: 2014-08-18 18:15:14 UTC, text: "user tag", group_id: "53f242b27f11ba5f31000001", _type: "UserTag">,
 #<TagTag _id: 53f242b27f11ba5f31000003, created_at: 2014-08-18 18:15:14 UTC, updated_at: 2014-08-18 18:15:14 UTC, text: "tag tag", group_id: "53f242b27f11ba5f31000001", _type: "TagTag">,
 #<GroupTag _id: 53f242b27f11ba5f31000004, created_at: 2014-08-18 18:15:14 UTC, updated_at: 2014-08-18 18:15:14 UTC, text: "group tag", group_id: "53f242b27f11ba5f31000001", _type: "GroupTag">]
collections: ["groups", "tag"]
Finished tests in 0.527855s, 3.7889 tests/s, 3.7889 assertions/s.
2 tests, 2 assertions, 0 failures, 0 errors, 0 skips
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top