如何在Rails中用其他表数据填充数据库种子?拆分后失效
Hey Rachel, great question—splitting seed files is such a smart call for keeping your code organized, but the variable scope snag you’re hitting is super common. Let’s break down why this happened and how to fix it.
Why the Split Broke Your Seeds
When you split seeds into separate files, each one runs in its own isolated scope. The currencies variable you built in your original single file only existed in that one scope—your user seed file has no way to access it, which is why you’re seeing errors.
Solution 1: Query Existing Currency Records (Most Recommended)
Instead of relying on a shared variable, have your user seed fetch the already-created Currency records directly from the database. This is clean, avoids scope headaches, and works as long as currencies are seeded before users.
First, split your seeds into dedicated files:
# db/seeds/currencies.rb # Create all your currency records first 10.times { FactoryBot.create(:currency) }
# db/seeds/users.rb # Pull existing currencies from the database available_currencies = Currency.all # Create users with a randomly selected currency 50.times { FactoryBot.create(:user, currency: available_currencies.sample) }
Then, make sure your main db/seeds.rb loads them in the correct order:
# db/seeds.rb # Load currencies first, then users to ensure data exists require_relative 'seeds/currencies' require_relative 'seeds/users'
Solution 2: Pass Variables via Methods
If you prefer to keep the variable approach (maybe you need to tweak the currency set before using it), you can define a method in your user seed that accepts the currencies array as an argument.
Main seed file:
# db/seeds.rb # Create currencies and store them in a variable currencies = [] 10.times { currencies << FactoryBot.create(:currency) } # Load the user seed and pass the variable require_relative 'seeds/users' create_users(currencies)
User seed file:
# db/seeds/users.rb # Define a method that accepts the currencies array def create_users(currencies) 50.times { FactoryBot.create(:user, currency: currencies.sample) } end
Solution 3: Use a Global Variable (Not Recommended)
You could use a global variable to share the currencies array, but this is generally bad practice—it pollutes the global scope and can lead to unexpected behavior later. That said, here’s how it would work if you absolutely need it:
# db/seeds/currencies.rb # Create a global variable for currencies $currencies = [] 10.times { $currencies << FactoryBot.create(:currency) }
# db/seeds/users.rb # Access the global variable to pick a currency 50.times { FactoryBot.create(:user, currency: $currencies.sample) }
Stick to Solutions 1 or 2 whenever possible—they’re way more maintainable.
Key Note: Seed Order Matters
No matter which approach you choose, make sure your currency seed runs before the user seed. Explicitly requiring them in order in db/seeds.rb is the safest way to guarantee this, instead of trusting alphabetical filename ordering.
内容的提问来源于stack exchange,提问作者Rachel

