I'm trying to create dummy data with FactoryGirl.
User has many posts, post has many videos, video has many comments. Comment belong to video and user. Video belongs to post and user. Post belongs to user.
I would like to create at least 20 users, each with at least 10 posts, each post with at least 1 video, each video with at least 1 comment.
Thus far I have the following factories however I can't seem to get the videos or comments to work.
FactoryGirl.define do
factory :comment do
sequence(:body) { |n| "#{n}body" }
video
user
end
end
FactoryGirl.define do
factory :post do
sequence(:title) { |n| "#{n}title" }
date Date.today.strftime('%m/%d/%Y')
body Faker::Lorem.paragraph(3)
tags Faker::Lorem.words(4)
user
trait :with_videos do
after(:build) do |post|
create(:video, post: post)
end
end
end
end
FactoryGirl.define do
factory :user do
first_name Faker::Name.first_name
last_name Faker::Name.last_name
sequence(:username) { |n| "#{n}username" }
sequence(:email) { |n| "#{n}[email protected]" }
phone Faker::PhoneNumber.phone_number
password Faker::Internet.password(6, 20)
country Faker::Address.country
state Faker::Address.state_abbr
city Faker::Address.city
zip Faker::Address.zip
seeking_coach true
accept_email true
accept_phone true
end
end
FactoryGirl.define do
factory :video do
sequence(:title) { |n| "#{n}title" }
sequence(:url) { |n| "https://www.youtube.com/watch?v=tYm_#{n}2oCVdSM" }
embed_id { "#{url}.split('=').last" }
post
user
trait :with_comments do
after(:build) do |video|
create(:comment, video: video)
end
end
end
end
I think in factories hook should be after(:create)
instead of after(:build)
, e.g.:
after(:create) do |video|
create(:comment, video: video)
end
Here is all updated factories:
spec/factories/users.rb
FactoryGirl.define do
factory :user do
first_name Faker::Name.first_name
last_name Faker::Name.last_name
sequence(:username) { |n| "#{n}username" }
sequence(:email) { |n| "#{n}[email protected]" }
phone Faker::PhoneNumber.phone_number
password Faker::Internet.password(6, 20)
country Faker::Address.country
state Faker::Address.state_abbr
city Faker::Address.city
zip Faker::Address.zip
seeking_coach true
accept_email true
accept_phone true
trait :with_10_posts do
after(:create) do |user|
create_list(:post, 10, :with_videos, user: user)
end
end
end
end
spec/factories/posts.rb
FactoryGirl.define do
factory :post do
sequence(:title) { |n| "#{n}title" }
date Date.today.strftime('%m/%d/%Y')
body Faker::Lorem.paragraph(3)
tags Faker::Lorem.words(4)
user
trait :with_videos do
after(:create) do |post|
create(:video, :with_comments, post: post)
end
end
end
end
spec/factories/videos.rb
FactoryGirl.define do
factory :video do
sequence(:title) { |n| "#{n}title" }
sequence(:url) { |n| "https://www.youtube.com/watch?v=tYm_#{n}2oCVdSM" }
post
trait :with_comments do
after(:create) do |video|
create(:comment, video: video)
end
end
end
end
spec/factories/comments.rb
FactoryGirl.define do
factory :comment do
sequence(:body) { |n| "#{n}body" }
video
end
end
And RSpec test to ensure that factories setup works:
describe 'Factories' do
it 'creates 20 users, each with at least 10 posts, each post with at least 1 video, each video with at least 1 comment' do
FactoryGirl.create_list(:user, 20, :with_10_posts)
expect(User.count).to eq(20)
user = User.take
expect(user.posts.count).to be >= 10
post = user.posts.take
expect(post.videos.count).to be >= 1
video = post.videos.take
expect(video.comments.count).to be >= 1
end
end
Here is all the code - https://github.com/shhavel/stackoverflow_question_40136020