Matthew
Matthew

Reputation: 15642

Mongoid and embedding tags

I have a few models that each have tags. Say for example, a User and a Post. Both should have embedded tags I think.
The user's embedded tags are their "favorites" and a post's tags are tags that have to do with the post.

I'm using Mongoid, and I can't figure out how to have a Tag model where I can find all the tags (These tags aren't embedded, I want a separate collection of all available tags).

When a user tries to add a tag, it is checked against Tag.all to make sure it exists. If it does, then it should be embedded in the User model.

I can't figure out how to embed Tag models in more than one model (User and Post) or how to embed Tag models as well as retrieve them like normal (I get the error: Access to the collection for Tag is not allowed since it is an embedded document, please access a collection from the root document.).

Ideas? Am I designing this totally wrong? I don't need complicated queries like "Retrieve all users who have the example tag", so I figured that I should embed to be more efficient.

Upvotes: 3

Views: 499

Answers (3)

Gary Murakami
Gary Murakami

Reputation: 3402

My solution is to have a Registry model that embeds_many tags, then to have an instance that has the registered tags that is checked before adding to a user or post. This is essentially the same as Ron's answer, but without overloading User.

Upvotes: 1

Ron
Ron

Reputation: 1166

Well, the first step is to make a tag a polymorphic embed.

class User
  embeds_many :tags, :as => :taggable
end

class Post
  embeds_many :tags, :as => :taggable
end

class Tag
  embedded_in :taggable, :polymorphic => true
end

You could perhaps then have an instance of a user or a post that contains all tags available. And then instead of calling .all on the Tag class, you can call it on your instance

available_user = User.new
available_user.tags << Tag.new
available_user.tags.all

Upvotes: 3

Samy Dindane
Samy Dindane

Reputation: 18706

First of all, the error you get when you try to get embedded tags is normal, that's not possible with actual MongoDB versions.

I'm not an expert, but I can suggest you a workable solution: use embedded tags for User and Post, and create a Tag collection that you'll use for indexing purposes.

  • When a user tries to add a tag: call Tag.all
    • If the tag doesn't exist: create it in both User and Tag
    • If it does, simply embedded it in User.

The same goes for Post.

Upvotes: 0

Related Questions