Skip to content

Instantly share code, notes, and snippets.

@wtnabe
Created December 15, 2010 08:42
Show Gist options
  • Save wtnabe/741783 to your computer and use it in GitHub Desktop.
Save wtnabe/741783 to your computer and use it in GitHub Desktop.
import seed data from .csv or .yml for Rails 2.3.4+

Rails SeedImporter

  1. Put this code at #{Rails.root}/db/seeds.rb
  2. type rake db:setup

Limitation

It supports only `id' primary key.

# -*- mode: ruby; coding: utf-8 -*-
class SeedImporter
def initialize
@model = nil
@with_id = false
@dragonfly_fields = []
@paperclip_fields = []
end
def run
Dir.glob( File.join( seed_dir, '**/*.{yml,csv}' ) ).sort.each { |seed|
send( "import_#{File.extname( seed )[1..-1]}_seed", seed )
}
end
def seed_dir
ENV['SEED_DIR'] || File.dirname(__FILE__) + '/seeds'
end
def fcsv_opts
{ :headers => true,
:header_converters => :downcase }
end
def import_csv_seed( file )
init_model( file, '.csv' )
FasterCSV.table( file, fcsv_opts ) { |csv|
@with_id = csv.headers.include?( 'id' )
}
if ( @with_id )
_import_csv( file ) { |row| create_and_save_with_id( row.to_hash ) }
else
_import_csv( file ) { |row| create_and_save( row.to_hash ) }
end
end
def _import_csv( file, &block )
FasterCSV.open( file, fcsv_opts ).each { |csv| block.call( csv ) }
end
def import_yml_seed( file )
init_model( file, '.yml' )
YAML.load_file( file ).each_pair { |k, v|
if ( v.has_key?( 'id' ) )
create_and_save_with_id( v )
else
create_and_save( v )
end
}
end
def to_model( file, suffix )
File.basename( file, suffix ).sub( /\A[0-9]+(_\.)?/, '' ).classify
end
def init_model( file, suffix )
@model = Object.const_get( to_model( file, suffix ) )
init_file_fields
end
def create_and_save( data )
save( create( data ) )
end
def create_and_save_with_id( data )
record = create( data )
record['id'] = data['id']
save( record )
end
def create( data )
attach_file_when_need( data )
end
def attach_file_when_need( data )
record = @model.new( data )
if ( @dragonfly_fields.size > 0 )
@dragonfly_fields.each { |e|
col = e.to_s
file = data[e] || data[e.to_s]
path = File.join( seed_dir, file )
record.send( "#{col}=",
open( path ).read ) if file and File.exist?( path )
}
end
if ( @paperclip_fields.size > 0 )
@paperclip_fields.each { |e|
col = e.to_s
file = data[e] || data[e.to_s]
path = File.join( seed_dir, file )
record.send( "#{col}=",
open( path ) ) if file and File.exist?( path )
}
end
record
end
def save( record )
begin
record.save!
rescue => e
p record
p record.errors
raise e
end
end
def init_file_fields
if ( defined? ::Dragonfly )
@dragonfly_fields =
if @model.respond_to? :dragonfly_apps_for_attributes # v0.8
@model.dragonfly_apps_for_attributes.keys
elsif @model.respond_to? :dragonfly_attachment_classes # v0.9
@model.dragonfly_attachment_classes.map { |c|
c.attribute
}
end
end
if ( defined? ::Paperclip )
@paperclip_fields = @model.attachment_definitions.keys if @model.attachment_definitions
end
end
end
SeedImporter.new.run
@greyblake
Copy link

You can use fast_seeder(https://github.com/greyblake/fast_seeder) as well. It support number of DB adapters.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment