I have an app with multiple models seeding. To better handling seeds I would like to split one big file to multiple sub-seed files. In the original process I used variables to reference objects, like:
fruit = Category.create(id: '123', name: 'Fruit', ...)
and then
apple = Product.create(id: '012', name: 'apple', category: fruit)
, where fruit
is the category created before this line.
If i split the creation of categories
and products
in 2 files, how do i pass fruit
as variable to the other seed?
I tought it would be accessible, but unfortunately i get
NameError: undefined local variable or method `fruit' for main:Object
CodePudding user response:
Variables cannot be passed across files like this in Ruby. My recommended way to accomplish your goal is to utilize the ActiveRecord relationship between Category and Product.
# ../seeds/categories.rb
## notice that i removed the assignment of the id column, ActiveRecord will do that automatically for you!
Category.create(name: 'Fruit', ...)
Category.create(name: 'Vegetable', ...)
Category.create(name: 'Carb', ...)
# ../seeds/products.rb
## query for and store the categories
fruit_category = Category.find_by(name: 'Fruit')
veg_category = Category.find_by(name: 'Vegetable')
carb_category = Category.find_by(name: 'Carb')
## assign these to variables if they need to be used later in this file
Product.create(name: 'apple', category: fruit_category)
Product.create(name: 'banana', category: fruit_category)
Product.create(name: 'broccoli', category: veg_category)
Product.create(name: 'spinach', category: veg_category)
Product.create(name: 'rice', category: carb_category)
Product.create(name: 'bread', category: carb_category)
CodePudding user response:
You would be use the FactoryBot to generate the seeds. This is the way to simplificate this process.
First, add gem factory_bot_rails
:
# Gemfile
...
group :development, :test do
...
gem 'factory_bot_rails', '~> 6.1'
...
define factories:
# spec/factories/categories.rb
# frozen_string_literal: true
FactoryBot.define do
factory :category do
sequence(:name) { |n| "#{n}_th_category" }
...
# spec/factories/products.rb
FactoryBot.define do
factory :product do
sequence(:name) { |n| "#{n}_th_product" }
category
...
And then, you can use factories in seeds and specs:
# db/seeds/development.rb
include FactoryBot::Syntax::Methods
fruits_category = create(:category, name: 'Fruit')
product = create(:product, name: 'apple', category: fruits_category)