ar_loader 0.0.6 → 0.0.8

Sign up to get free protection for your applications and to get access to all the features.
Files changed (53) hide show
  1. data/LICENSE +9 -9
  2. data/README.markdown +268 -221
  3. data/Rakefile +76 -76
  4. data/lib/VERSION +1 -1
  5. data/lib/ar_loader.rb +87 -66
  6. data/lib/ar_loader/exceptions.rb +2 -0
  7. data/lib/{engine → ar_loader}/file_definitions.rb +353 -353
  8. data/lib/{engine → ar_loader}/mapping_file_definitions.rb +87 -87
  9. data/lib/ar_loader/method_detail.rb +257 -0
  10. data/lib/ar_loader/method_mapper.rb +213 -0
  11. data/lib/helpers/jruby/jexcel_file.rb +187 -0
  12. data/lib/{engine → helpers/jruby}/word.rb +79 -70
  13. data/lib/helpers/spree_helper.rb +85 -0
  14. data/lib/loaders/csv_loader.rb +87 -0
  15. data/lib/loaders/excel_loader.rb +132 -0
  16. data/lib/loaders/loader_base.rb +205 -73
  17. data/lib/loaders/spree/image_loader.rb +45 -41
  18. data/lib/loaders/spree/product_loader.rb +140 -91
  19. data/lib/to_b.rb +24 -24
  20. data/spec/csv_loader_spec.rb +27 -0
  21. data/spec/database.yml +19 -6
  22. data/spec/db/migrate/20110803201325_create_test_bed.rb +78 -0
  23. data/spec/excel_loader_spec.rb +113 -98
  24. data/spec/fixtures/BadAssociationName.xls +0 -0
  25. data/spec/fixtures/DemoNegativeTesting.xls +0 -0
  26. data/spec/fixtures/DemoTestModelAssoc.xls +0 -0
  27. data/spec/fixtures/ProjectsMultiCategories.xls +0 -0
  28. data/spec/fixtures/SimpleProjects.xls +0 -0
  29. data/spec/fixtures/SpreeProducts.xls +0 -0
  30. data/spec/fixtures/SpreeZoneExample.csv +5 -0
  31. data/spec/fixtures/SpreeZoneExample.xls +0 -0
  32. data/spec/loader_spec.rb +116 -0
  33. data/spec/logs/test.log +5000 -0
  34. data/spec/method_mapper_spec.rb +222 -0
  35. data/spec/models.rb +55 -0
  36. data/spec/spec_helper.rb +85 -18
  37. data/spec/spree_loader_spec.rb +223 -157
  38. data/tasks/config/seed_fu_product_template.erb +15 -15
  39. data/tasks/config/tidy_config.txt +12 -12
  40. data/tasks/db_tasks.rake +64 -64
  41. data/tasks/excel_loader.rake +63 -113
  42. data/tasks/file_tasks.rake +36 -37
  43. data/tasks/loader.rake +45 -0
  44. data/tasks/spree/image_load.rake +108 -107
  45. data/tasks/spree/product_loader.rake +49 -107
  46. data/tasks/word_to_seedfu.rake +166 -166
  47. metadata +66 -61
  48. data/lib/engine/jruby/jexcel_file.rb +0 -182
  49. data/lib/engine/jruby/method_mapper_excel.rb +0 -44
  50. data/lib/engine/method_detail.rb +0 -140
  51. data/lib/engine/method_mapper.rb +0 -157
  52. data/lib/engine/method_mapper_csv.rb +0 -28
  53. data/spec/db/migrate/20110803201325_create_testbed.rb +0 -25
@@ -1,15 +1,15 @@
1
- p = Product.seed( :name ) do |s|
2
- s.name = <%= @name %>
3
- s.available_on = '2009-09-01 09:00:00.0'
4
- s.meta_keywords = ['training', 'training']
5
- s.meta_description = ""
6
- s.description = '<%= @description %>'
7
- s.price = 0.00
8
- s.sku = '<%= @sku %>'
9
-
10
- s.is_physical = false
11
- s.is_private = false
12
-
13
- s.append_association :taxons, Taxon.find_by_name( 'Training' )
14
-
15
- end
1
+ p = Product.seed( :name ) do |s|
2
+ s.name = <%= @name %>
3
+ s.available_on = '2009-09-01 09:00:00.0'
4
+ s.meta_keywords = ['training', 'training']
5
+ s.meta_description = ""
6
+ s.description = '<%= @description %>'
7
+ s.price = 0.00
8
+ s.sku = '<%= @sku %>'
9
+
10
+ s.is_physical = false
11
+ s.is_private = false
12
+
13
+ s.append_association :taxons, Taxon.find_by_name( 'Training' )
14
+
15
+ end
@@ -1,13 +1,13 @@
1
- # Copyright:: (c) Autotelik Media Ltd 2011
2
- # Author :: Tom Statter
3
- # Date :: Aug 2010
4
- #
5
- # License:: Free, OpenSource... MIT ?
6
-
7
- # This is the best effort I've found so far to reduce the amount of MS cruft
8
- # to absolute minimum
9
- # ... but unfortunately these tags will NOT BE REMOVED completely - manual cleanup still required
10
-
11
- # TODO - add another ruby parse layer to strip these out completely
12
-
1
+ # Copyright:: (c) Autotelik Media Ltd 2011
2
+ # Author :: Tom Statter
3
+ # Date :: Aug 2010
4
+ #
5
+ # License:: Free, OpenSource... MIT ?
6
+
7
+ # This is the best effort I've found so far to reduce the amount of MS cruft
8
+ # to absolute minimum
9
+ # ... but unfortunately these tags will NOT BE REMOVED completely - manual cleanup still required
10
+
11
+ # TODO - add another ruby parse layer to strip these out completely
12
+
13
13
  new-empty-tags: o:smarttagtype, st1:placename, st1:place, st1:placetype
data/tasks/db_tasks.rake CHANGED
@@ -1,65 +1,65 @@
1
- # Author :: Tom Statter
2
- # Date :: Mar 2011
3
- #
4
- # License:: The MIT License (Free and OpenSource)
5
- #
6
- # About:: Additional Rake tasks useful when testing seeding DB via ARLoader
7
- #
8
- namespace :autotelik do
9
-
10
- namespace :db do
11
-
12
- SYSTEM_TABLE_EXCLUSION_LIST = ['schema_migrations']
13
-
14
- desc "Purge the current database"
15
- task :purge, :exclude_system_tables, :needs => [:environment] do |t, args|
16
- require 'highline/import'
17
-
18
- if(RAILS_ENV == 'production')
19
- agree("WARNING: In Production database, REALLY PURGE ? [y]:")
20
- end
21
-
22
- config = ActiveRecord::Base.configurations[RAILS_ENV || 'development']
23
- case config['adapter']
24
- when "mysql", "jdbcmysql"
25
- ActiveRecord::Base.establish_connection(config)
26
- ActiveRecord::Base.connection.tables.each do |table|
27
- next if(args[:exclude_system_tables] && SYSTEM_TABLE_EXCLUSION_LIST.include?(table) )
28
- puts "purging table: #{table}"
29
- ActiveRecord::Base.connection.execute("TRUNCATE #{table}")
30
- end
31
- when "sqlite","sqlite3"
32
- dbfile = config["database"] || config["dbfile"]
33
- File.delete(dbfile) if File.exist?(dbfile)
34
- when "sqlserver"
35
- dropfkscript = "#{config["host"]}.#{config["database"]}.DP1".gsub(/\\/,'-')
36
- `osql -E -S #{config["host"]} -d #{config["database"]} -i db\\#{dropfkscript}`
37
- `osql -E -S #{config["host"]} -d #{config["database"]} -i db\\#{RAILS_ENV}_structure.sql`
38
- when "oci", "oracle"
39
- ActiveRecord::Base.establish_connection(config)
40
- ActiveRecord::Base.connection.structure_drop.split(";\n\n").each do |ddl|
41
- ActiveRecord::Base.connection.execute(ddl)
42
- end
43
- when "firebird"
44
- ActiveRecord::Base.establish_connection(config)
45
- ActiveRecord::Base.connection.recreate_database!
46
- else
47
- raise "Task not supported by '#{config["adapter"]}'"
48
- end
49
- end
50
-
51
- desc "Clear database and optional directories such as assets, then run db:seed"
52
- task :seed_again, :assets, :needs => [:environment] do |t, args|
53
-
54
- Rake::Task['autotelik:db:purge'].invoke( true ) # i.e ENV['exclude_system_tables'] = true
55
-
56
- if(args[:assets])
57
- assets = "#{Rails.root}/public/assets"
58
- FileUtils::rm_rf(assets) if(File.exists?(assets))
59
- end
60
-
61
- Rake::Task['db:seed'].invoke
62
- end
63
-
64
- end # db
1
+ # Author :: Tom Statter
2
+ # Date :: Mar 2011
3
+ #
4
+ # License:: The MIT License (Free and OpenSource)
5
+ #
6
+ # About:: Additional Rake tasks useful when testing seeding DB via ARLoader
7
+ #
8
+ namespace :autotelik do
9
+
10
+ namespace :db do
11
+
12
+ SYSTEM_TABLE_EXCLUSION_LIST = ['schema_migrations']
13
+
14
+ desc "Purge the current database"
15
+ task :purge, :exclude_system_tables, :needs => [:environment] do |t, args|
16
+ require 'highline/import'
17
+
18
+ if(RAILS_ENV == 'production')
19
+ agree("WARNING: In Production database, REALLY PURGE ? [y]:")
20
+ end
21
+
22
+ config = ActiveRecord::Base.configurations[RAILS_ENV || 'development']
23
+ case config['adapter']
24
+ when "mysql", "jdbcmysql"
25
+ ActiveRecord::Base.establish_connection(config)
26
+ ActiveRecord::Base.connection.tables.each do |table|
27
+ next if(args[:exclude_system_tables] && SYSTEM_TABLE_EXCLUSION_LIST.include?(table) )
28
+ puts "purging table: #{table}"
29
+ ActiveRecord::Base.connection.execute("TRUNCATE #{table}")
30
+ end
31
+ when "sqlite","sqlite3"
32
+ dbfile = config["database"] || config["dbfile"]
33
+ File.delete(dbfile) if File.exist?(dbfile)
34
+ when "sqlserver"
35
+ dropfkscript = "#{config["host"]}.#{config["database"]}.DP1".gsub(/\\/,'-')
36
+ `osql -E -S #{config["host"]} -d #{config["database"]} -i db\\#{dropfkscript}`
37
+ `osql -E -S #{config["host"]} -d #{config["database"]} -i db\\#{RAILS_ENV}_structure.sql`
38
+ when "oci", "oracle"
39
+ ActiveRecord::Base.establish_connection(config)
40
+ ActiveRecord::Base.connection.structure_drop.split(";\n\n").each do |ddl|
41
+ ActiveRecord::Base.connection.execute(ddl)
42
+ end
43
+ when "firebird"
44
+ ActiveRecord::Base.establish_connection(config)
45
+ ActiveRecord::Base.connection.recreate_database!
46
+ else
47
+ raise "Task not supported by '#{config["adapter"]}'"
48
+ end
49
+ end
50
+
51
+ desc "Clear database and optional directories such as assets, then run db:seed"
52
+ task :seed_again, :assets, :needs => [:environment] do |t, args|
53
+
54
+ Rake::Task['autotelik:db:purge'].invoke( true ) # i.e ENV['exclude_system_tables'] = true
55
+
56
+ if(args[:assets])
57
+ assets = "#{Rails.root}/public/assets"
58
+ FileUtils::rm_rf(assets) if(File.exists?(assets))
59
+ end
60
+
61
+ Rake::Task['db:seed'].invoke
62
+ end
63
+
64
+ end # db
65
65
  end # autotelik
@@ -1,114 +1,64 @@
1
- # Copyright:: (c) Autotelik Media Ltd 2011
2
- # Author :: Tom Statter
3
- # Date :: Feb 2011
4
- # License:: TBD. Free, Open Source. MIT ?
5
- #
6
- # REQUIRES: JRuby
7
- #
8
- # Usage::
9
- # => jruby -S rake autotelik:excel_load model=<active record class> input=<file.xls>
10
- # => jruby -S rake autotelik:excel_load model=<active record class> input=C:\MyProducts.xlsverbose=true
11
- #
12
- namespace :autotelik do
13
-
14
- desc "Populate a model's table in db with data from .xls (Excel) file"
15
- task :excel_load, :model, :loader, :input, :verbose, :needs => :environment do |t, args|
16
-
17
- raise "USAGE: jruby -S rake excel_load input=excel_file.xls" unless args[:input]
18
- raise "ERROR: Cannot process without AR Model - please supply model=<Class>" unless args[:model]
19
- raise "ERROR: Could not find file #{args[:input]}" unless File.exists?(args[:input])
20
-
21
- begin
22
- klass = Kernel.const_get(args[:model])
23
- rescue NameError
24
- raise "ERROR: No such AR Model found - please check model=<Class>"
25
- end
26
-
27
- begin
28
- require "#{args[:model]}_loader"
29
-
30
- loader_klass = Kernel.const_get("#{args[:model]}Loader")
31
-
32
- loader = loader_klass.new(klass)
33
- rescue
34
- puts "INFO: No specific #{args[:model]}Loader found using generic loader"
35
- loader = LoaderBase.new(klass)
36
- end
37
-
38
- require 'method_mapper_excel'
39
-
40
- @method_mapper = MethodMapperExcel.new(args[:input], klass)
41
-
42
- @excel = @method_mapper.excel
43
-
44
- if(args[:verbose])
45
- puts "Loading from Excel file: #{args[:input]}"
46
- puts "Processing #{@excel.num_rows} rows"
47
- end
48
-
49
- # Process spreadsheet and create model instances
50
-
51
- klass.transaction do
52
- @loaded_objects = []
53
-
54
- (1..@excel.num_rows).collect do |row|
55
-
56
- data_row = @excel.sheet.getRow(row)
57
- break if data_row.nil?
58
-
59
- @assoc_classes = {}
60
-
61
- # TODO - Smart sorting of column processing order ....
62
- # Does not currently ensure mandatory columns (for valid?) processed first but model needs saving
63
- # before associations can be processed so user should ensure mandatory columns are prior to associations
64
-
65
- contains_data = false
66
-
67
- # Iterate over the columns method_mapper found in Excel,
68
- # pulling data out of associated column
69
- @method_mapper.methods.each_with_index do |method_map, col|
70
-
71
- value = @excel.value(data_row, col)
72
-
73
- # Excel num_rows seems to return all 'visible' rows so,
74
- # we have to manually detect when actual data ends, this isn't very smart but
75
- # currently got no better idea than ending once we hit the first completely empty row
76
-
77
- contains_data = true if(value.to_s.empty?)
78
-
79
- puts "VALUE #{value.class}"
80
- puts "VALUE #{value} #{value.inspect}"
81
-
82
- loader.process(method_map, @excel.value(data_row, col))
83
-
84
- begin
85
- loader.load_object.save if( loader.load_object.valid? && loader.load_object.new_record? )
86
- rescue
87
- raise "Error processing row"
88
- end
89
- end
90
-
91
- break unless contains_data
92
-
93
- loaded_object = loader.load_object
94
-
95
- # TODO - handle when it's not valid ?
96
- # Process rest and dump out an exception list of Products
97
- #unless(product.valid?)
98
- #end
99
-
100
- puts "SAVING ROW #{row} : #{loaded_object.inspect}" if args[:verbose]
101
-
102
- unless(loaded_object.save)
103
- puts loaded_object.errors.inspect
104
- puts loaded_object.errors.full_messages.inspect
105
- raise "Error Saving : #{loaded_object.inspect}"
106
- else
107
- @loaded_objects << loaded_object
108
- end
109
- end
110
- end # TRANSACTION
111
-
112
- end
113
-
1
+ # Copyright:: (c) Autotelik Media Ltd 2011
2
+ # Author :: Tom Statter
3
+ # Date :: Feb 2011
4
+ # License:: TBD. Free, Open Source. MIT ?
5
+ #
6
+ # REQUIRES: JRuby
7
+ #
8
+ # Usage::
9
+ #
10
+ # In Rakefile:
11
+ #
12
+ # require 'ar_loader'
13
+ #
14
+ # ArLoader::load_tasks
15
+ #
16
+ # Cmd Line:
17
+ #
18
+ # => jruby -S rake ar_loader:excel model=<active record class> input=<file.xls>
19
+ # => jruby -S rake ar_loader:excel model=<active record class> input=C:\MyProducts.xlsverbose=true
20
+ #
21
+ require 'ar_loader'
22
+ require 'excel_loader'
23
+
24
+ namespace :ar_loader do
25
+
26
+ desc "Populate a model's table in db with data from .xls (Excel) file"
27
+
28
+ task :excel, [:model, :loader, :input, :verbose] => [:environment] do |t, args|
29
+
30
+ # in familiar ruby style args seems to have been become empty using this new style for rake 0.9.2
31
+ # whatever format i try, on both Win and OSX .. so had to revert back to ENV
32
+ model = ENV['model']
33
+ input = ENV['input']
34
+
35
+ raise "USAGE: jruby -S rake ar_loader:excel input=excel_file.xls model=<Class>" unless(input)
36
+ raise "ERROR: Cannot process without AR Model - please supply model=<Class>" unless(model)
37
+ raise "ERROR: Could not find file #{args[:input]}" unless File.exists?(input)
38
+
39
+ begin
40
+ klass = Kernel.const_get(model)
41
+ rescue NameError
42
+ raise "ERROR: No such AR Model found - check valid model supplied via model=<Class>"
43
+ end
44
+
45
+ if(ENV['loader'])
46
+ begin
47
+ loader_klass = Kernel.const_get(ENV['loader'])
48
+
49
+ loader = loader_klass.new(klass)
50
+
51
+ puts "INFO: Using loader : #{loader.class}"
52
+ rescue
53
+ puts "INFO: No specific #{model}Loader found - using generic ExcelLoader"
54
+ loader = ARLoader::ExcelLoader.new(klass)
55
+ end
56
+ else
57
+ puts "INFO: No Loader specified - using generic ExcelLoader"
58
+ loader = ARLoader::ExcelLoader.new(klass)
59
+ end
60
+
61
+ loader.load(input)
62
+ end
63
+
114
64
  end
@@ -1,38 +1,37 @@
1
- # Copyright:: (c) Autotelik Media Ltd 2011
2
- # Author :: Tom Statter
3
- # Date :: Feb 2011
4
- # License:: MIT. Free, Open Source.
5
- #
6
- # Usage:: rake autotelik:file_rename input=/blah image_load input=path_to_images
7
- #
8
-
9
- namespace :autotelik do
10
-
11
- desc "copy or mv a folder of files, consistently renaming in the process"
12
- task :file_rename, :input, :offset, :prefix, :width, :commit, :mv do |t, args|
13
- raise "USAGE: rake file_rename input='C:\blah' [offset=n prefix='str' width=n]" unless args[:input] && File.exists?(args[:input])
14
- width = args[:width] || 2
15
-
16
- action = args[:mv] ? 'mv' : 'cp'
17
-
18
- cache = args[:input]
19
-
20
- if(File.exists?(cache) )
21
- puts "Renaming files from #{cache}"
22
- Dir.glob(File.join(cache, "*")) do |name|
23
- path, base_name = File.split(name)
24
- id = base_name.slice!(/\w+/)
25
-
26
- id = id.to_i + args[:offset].to_i if(args[:offset])
27
- id = "%0#{width}d" % id.to_i if(args[:width])
28
- id = args[:prefix] + id.to_s if(args[:prefix])
29
-
30
- destination = File.join(path, "#{id}#{base_name}")
31
- puts "ACTION: #{action} #{name} #{destination}"
32
-
33
- File.send( action, name, destination) if args[:commit]
34
- end
35
- end
36
- end
37
-
1
+ # Copyright:: (c) Autotelik Media Ltd 2011
2
+ # Author :: Tom Statter
3
+ # Date :: Feb 2011
4
+ # License:: MIT
5
+ #
6
+ # Usage:: rake ar_loader:file_rename input=/blah image_load input=path_to_images
7
+ #
8
+ namespace :ar_loader do
9
+
10
+ desc "copy or mv a folder of files, consistently renaming in the process"
11
+ task :file_rename, :input, :offset, :prefix, :width, :commit, :mv do |t, args|
12
+ raise "USAGE: rake file_rename input='C:\blah' [offset=n prefix='str' width=n]" unless args[:input] && File.exists?(args[:input])
13
+ width = args[:width] || 2
14
+
15
+ action = args[:mv] ? 'mv' : 'cp'
16
+
17
+ cache = args[:input]
18
+
19
+ if(File.exists?(cache) )
20
+ puts "Renaming files from #{cache}"
21
+ Dir.glob(File.join(cache, "*")) do |name|
22
+ path, base_name = File.split(name)
23
+ id = base_name.slice!(/\w+/)
24
+
25
+ id = id.to_i + args[:offset].to_i if(args[:offset])
26
+ id = "%0#{width}d" % id.to_i if(args[:width])
27
+ id = args[:prefix] + id.to_s if(args[:prefix])
28
+
29
+ destination = File.join(path, "#{id}#{base_name}")
30
+ puts "ACTION: #{action} #{name} #{destination}"
31
+
32
+ File.send( action, name, destination) if args[:commit]
33
+ end
34
+ end
35
+ end
36
+
38
37
  end
data/tasks/loader.rake ADDED
@@ -0,0 +1,45 @@
1
+ # Copyright:: (c) Autotelik Media Ltd 2011
2
+ # Author :: Tom Statter
3
+ # Date :: Aug 2011
4
+ # License:: MIT
5
+ #
6
+ # Usage::
7
+ #
8
+ # In Rakefile:
9
+ #
10
+ # require 'ar_loader'
11
+ #
12
+ # ArLoader::load_tasks
13
+ #
14
+ # Cmd Line:
15
+ #
16
+ # => jruby -S rake ar_loader:csv model=<active record class> input=<file.csv>
17
+ #
18
+ namespace :ar_loader do
19
+
20
+ desc "Populate a model's table in db with data from CSV file"
21
+ task :csv, [:model, :loader, :input, :verbose] => [:environment] do |t, args|
22
+
23
+ # in familiar ruby style args seems to have been become empty with rake 0.9.2 whatever i try
24
+ # so had to revert back to ENV
25
+ model = ENV['model']
26
+ input = ENV['input']
27
+
28
+ raise "USAGE: jruby -S rake ar_loader:excel input=excel_file.xls model=<Class>" unless(input)
29
+ raise "ERROR: Cannot process without AR Model - please supply model=<Class>" unless(model)
30
+ raise "ERROR: Could not find file #{args[:input]}" unless File.exists?(input)
31
+
32
+ begin
33
+ klass = Kernel.const_get(model)
34
+ rescue NameError
35
+ raise "ERROR: No such AR Model found - check valid model supplied via model=<Class>"
36
+ end
37
+
38
+ puts "INFO: Using CSV loader"
39
+
40
+ loader = CsvLoader.new(klass)
41
+
42
+ loader.load(input)
43
+ end
44
+
45
+ end