How to set up a Rake task for seeding

2019-04-10 04:51发布

问题:

(This is really a newbie question about Rake & Rails & dependencies in general. Trying to wrap my head around how all this fits together)

Basically, I want a Rake task that acts like seed.rb but is called separately. It adds test data for the development environment, while my seed.rb provides basic data for all environments.

The script, family_seed.rb, uses FactoryGirl to generate some records. It looks like this:

require File.expand_path('../../config/environment', __FILE__)
require './spec/factories'

Family.delete_all
Member.delete_all
zinsser = Factory.create(:family, :last_name=>'Zinsser', :first_name=>'Carl', :sim_id => '500')
blackburn = Factory.create(:family, :last_name=>'Blackburn', :first_name=>'Greg', :sim_id => '501')

It runs fine with bundle exec "ruby db/family_seeds.rb", but my question is how to set it up with Rake. Should the whole thing be placed inside a Rake task? How could I, instead, set up a task that would call the script, while ensuring that the Rails development environment is available when it runs? I'm trying not just to get the job done, but to do it in a "right" way.

回答1:

One way to approach this would be to create a class or module in lib (this makes it easier to write tests for, and makes the code more reusable):

require '../spec/factories'

class FamilySeed

  def self.seed
    raise "Don't run this in production!" if Rails.env.production?

    Family.delete_all
    Member.delete_all
    zinsser = Factory.create(:family, :last_name=>'Zinsser', :first_name=>'Carl', :sim_id => '500')
    blackburn = Factory.create(:family, :last_name=>'Blackburn', :first_name=>'Greg', :sim_id => '501')
  end

end

How to create the rake task:

require 'family_seed'

namespace :seed do
  task :families => :environment do
    FamilySeed.seed
  end
end

I'd be careful with allowing things like Family.delete_all and Member.delete_all to be too freely used. You could easily shoot yourself in the foot later on by calling something you didn't mean to on a production db.

How to run the rake task:

Run it in your command like with the following:

bundle exec rake seed:families


回答2:

Create a rake task and require :environment

task :delete_all => :environement do
  require Rails.root.join('spec/factories')
  Family.delete_all
  Member.delete_all
  zinsser = Factory.create(:family, :last_name=>'Zinsser', :first_name=>'Carl', :sim_id => '500')
  blackburn = Factory.create(:family, :last_name=>'Blackburn', :first_name=>'Greg', :sim_id => '501')
end

After you can run this task rake delete_all