Rails HABTM in Mongoid & Factory Girl

In Rails say you have a HABTM (N:N) relationship between two models


class User
has_and_belongs_to_many :posts
...........
end

class Post
has_and_belongs_to_many :users
.......
end

So what essentially it means is a Post can have many Authors and an Author can have multiple posts.
Now you want to test drive the thing by seeding test data in Factory Girl.

Here is an article for seeding data for 1:N relationships in Factory girl. But it doesn’t talk about HABTM relations.

I was playing around with factory girl and figured out a way to seed a post with authors.
Here is how you do it -


Factory.define :user, :class=>User do |user|
user.first_name "Alex"
user.last_name "Malcolm"
user.nick_name "Alexy"
user.email "alexy.m@gmail.com"
user.password "foobar"
user.password_confirmation "foobar"
user.role "author"
end

Factory.define :post do |post|
post.title "Foo Post"
post.content "Bar content"
end

Factory.define :post_with_author, :parent => :post do |post|
post.after_create { |p| Factory(:user, :posts => [p]) }
end

Now in your Test class do
@post = Factory(:post_with_author)

Factory girl would have inserted the User for you and then a Post and updated the relationship.

Btw I the code above was tested in Mongoid/MongoDB and not on Active Record. But since its working in Mongoid there is no reason I see why it won’t work with Active Record natively.

Another thing which I found with Mongoid/MongoDB and HABTM is that unlike Active Record you don’t need a Join Table like Users_Posts – the reason being MongoDB doesn’t support join queries. So you have to lump the join table into the respective models.

The Mongoid stores HABTM relation in back-end something like this

> db.users.find()
{ "_id" : ObjectId("4dc2010ea38c3d0b50000003"), "first_name" : "Alex", "last_name" : "Malcolm", "nick_name" : "Alexy", "post_ids" : [
ObjectId("4dc2012fa38c3d0b50000005"),
ObjectId("4dd1240ca38c3d104a000009"),
ObjectId("4dd12ff9a38c3d104a00000f")
], "role" : "author" }

That is in the Users model you have an array of post_ids and similarly in the Posts Model you will have an array of user_ids.

And finally if its on Active Record it may be preferable to have has_many :through instead of has_and_belongs_to_many relation as this post says.

About these ads

3 thoughts on “Rails HABTM in Mongoid & Factory Girl

  1. Thank you SO MUCH for this post. I have been banging my head against the Factory Wall (if you will) for at least a couple days, and you have set me FREEEEE!!!!

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s