Учетверенные вложенные дочерние элементы в FactoryGirl

#ruby-on-rails #ruby #capybara #factory-bot #rspec-rails

#ruby-on-rails #ruby #capybara #завод-бот #rspec-rails

Вопрос:

Я пытаюсь создать фиктивные данные с помощью FactoryGirl.

У пользователя много сообщений, у сообщения много видео, у видео много комментариев. Комментарий принадлежит видео и пользователю. Видео принадлежит сообщению и пользователю. Сообщение принадлежит пользователю.

Я хотел бы создать не менее 20 пользователей, у каждого из которых было не менее 10 сообщений, у каждого сообщения было не менее 1 видео, у каждого видео было не менее 1 комментария.

На данный момент у меня есть следующие фабрики, однако, похоже, я не могу заставить видео или комментарии работать.

спецификация/фабрики/комментарии.rb

 FactoryGirl.define do
  factory :comment do
    sequence(:body) { |n| "#{n}body" }
    video
    user
  end
end
  

спецификация/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(:build) do |post|
        create(:video, post: post)
      end
    end
  end
end
  

спецификация/фабрики/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@website.com" }
    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
  

спецификация/фабрики/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" }
    embed_id { "#{url}.split('=').last" }
    post
    user

    trait :with_comments do
      after(:build) do |video|
        create(:comment, video: video)
      end
    end
  end
end
  

Ответ №1:

Я думаю, что на фабриках hook должен быть after(:create) вместо after(:build) , например:

 after(:create) do |video|
  create(:comment, video: video)
end
  

Вот все обновленные фабрики:

спецификация/фабрики/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@website.com" }
    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
  

спецификация/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
  

спецификация/фабрики/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
  

спецификация/фабрики/комментарии.rb

 FactoryGirl.define do
  factory :comment do
    sequence(:body) { |n| "#{n}body" }
    video
  end
end
  

И тест RSpec, чтобы убедиться, что настройка factories работает:

 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
  

Вот весь код —https://github.com/shhavel/stackoverflow_question_40136020