Home > Software design >  Rails seed - Pass variable from one seed file to another
Rails seed - Pass variable from one seed file to another

Time:05-11

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)
  • Related