datashift 0.2.2 → 0.4.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (38) hide show
  1. data/README.markdown +15 -3
  2. data/VERSION +1 -1
  3. data/datashift.gemspec +11 -3
  4. data/lib/applications/jruby/jexcel_file.rb +10 -3
  5. data/lib/datashift.rb +25 -62
  6. data/lib/datashift/exceptions.rb +1 -0
  7. data/lib/datashift/logging.rb +58 -0
  8. data/lib/datashift/method_detail.rb +6 -45
  9. data/lib/datashift/method_details_manager.rb +54 -0
  10. data/lib/datashift/method_dictionary.rb +6 -1
  11. data/lib/datashift/method_mapper.rb +12 -5
  12. data/lib/datashift/populator.rb +46 -0
  13. data/lib/exporters/excel_exporter.rb +1 -1
  14. data/lib/generators/excel_generator.rb +48 -44
  15. data/lib/helpers/spree_helper.rb +14 -3
  16. data/lib/loaders/csv_loader.rb +9 -6
  17. data/lib/loaders/excel_loader.rb +5 -1
  18. data/lib/loaders/loader_base.rb +28 -14
  19. data/lib/loaders/spree/image_loader.rb +36 -34
  20. data/lib/loaders/spree/product_loader.rb +17 -7
  21. data/lib/thor/generate_excel.thor +35 -15
  22. data/lib/thor/import_excel.thor +84 -0
  23. data/lib/thor/spree/bootstrap_cleanup.thor +33 -0
  24. data/lib/thor/spree/products_images.thor +171 -0
  25. data/spec/datashift_spec.rb +19 -0
  26. data/spec/excel_exporter_spec.rb +3 -3
  27. data/spec/fixtures/datashift_Spree_db.sqlite +0 -0
  28. data/spec/fixtures/datashift_test_models_db.sqlite +0 -0
  29. data/spec/fixtures/spree/SpreeProductsDefaults.yml +15 -0
  30. data/spec/fixtures/spree/SpreeProductsMandatoryOnly.xls +0 -0
  31. data/spec/fixtures/spree/SpreeProductsWithImages.xls +0 -0
  32. data/spec/spec_helper.rb +2 -2
  33. data/spec/spree_generator_spec.rb +14 -0
  34. data/spec/spree_images_loader_spec.rb +73 -0
  35. data/spec/spree_loader_spec.rb +53 -19
  36. data/tasks/spree/image_load.rake +18 -13
  37. metadata +11 -3
  38. data/tasks/spree/product_loader.rake +0 -44
@@ -23,5 +23,24 @@ describe 'DataShift' do
23
23
  it "should provide root_path" do
24
24
  DataShift.root_path.should_not be_empty
25
25
  end
26
+
27
+ it "should provide a log" do
28
+ class Blah
29
+ include DataShift::Logging
30
+
31
+ def try_me
32
+ logger.info "hello datashift spec"
33
+ end
34
+ end
35
+
36
+
37
+ b = Blah.new()
38
+
39
+ b.logger.info "try me"
40
+
41
+ b.try_me
42
+
43
+
44
+ end
26
45
 
27
46
  end
@@ -38,7 +38,7 @@ if(Guards::jruby?)
38
38
  end
39
39
 
40
40
  it "should be able to create a new excel generator" do
41
- generator = ExcelGenerator.new( 'dummy.xls' )
41
+ generator = ExcelExporter.new( 'dummy.xls' )
42
42
 
43
43
  generator.should_not be_nil
44
44
  end
@@ -47,7 +47,7 @@ if(Guards::jruby?)
47
47
 
48
48
  expect = result_file('project_template_spec.xls')
49
49
 
50
- gen = ExcelGenerator.new( expect )
50
+ gen = ExcelExporter.new( expect )
51
51
 
52
52
  gen.generate(Project)
53
53
 
@@ -75,5 +75,5 @@ if(Guards::jruby?)
75
75
 
76
76
  end
77
77
  else
78
- puts "WARNING: skipped excel_generator_spec : Requires JRUBY - JExcelFile requires JAVA"
78
+ puts "WARNING: skipped excel_exporter_spec : Requires JRUBY - JExcelFile requires JAVA"
79
79
  end # jruby
@@ -0,0 +1,15 @@
1
+ ## YAML Template.
2
+
3
+ # Format is :
4
+ # --- !ruby/object:ActiveRecordModel
5
+ # :datashift_defaults
6
+ # key: value
7
+ #
8
+
9
+ Spree::Product:
10
+ datashift_defaults:
11
+ available_on: Time.now.to_s(:db)
12
+ cost_price: 1.0
13
+ meta_description: 'super duper meta desc.'
14
+ meta_keywords: 'techno dubstep d&b'
15
+
data/spec/spec_helper.rb CHANGED
@@ -5,7 +5,7 @@ require File.dirname(__FILE__) + '/../lib/datashift'
5
5
 
6
6
  include DataShift
7
7
 
8
- #.# Copyright:: (c) Autotelik Media Ltd 2011
8
+ # Copyright:: (c) Autotelik Media Ltd 2011
9
9
  # Author :: Tom Statter
10
10
  # Date :: Aug 2011
11
11
  # License:: MIT
@@ -128,7 +128,7 @@ module SpecHelper
128
128
  @Taxon_klass.delete_all
129
129
  @zone_klass.delete_all
130
130
 
131
- %w{OptionType OptionValue Property ProductProperty Variant Taxonomy}.each do |k|
131
+ %w{Image OptionType OptionValue Property ProductProperty Variant Taxonomy}.each do |k|
132
132
  instance_variable_set("@#{k}_klass", SpreeHelper::get_spree_class(k))
133
133
  instance_variable_get("@#{k}_klass").delete_all
134
134
  end
@@ -75,4 +75,18 @@ describe 'SpreeLoader' do
75
75
 
76
76
  end
77
77
 
78
+ it "should be able to exclude single associations from template" do
79
+
80
+ expect = result_file('product_and_assoc_export_spec.xls')
81
+
82
+ excel = ExcelGenerator.new(expect)
83
+
84
+ excel.generate_with_associations(@klass, :exclude => :has_many)
85
+
86
+ File.exists?(expect).should be_true
87
+
88
+ puts "You can check results manually in file #{expect}"
89
+
90
+ end
91
+
78
92
  end
@@ -0,0 +1,73 @@
1
+ # Copyright:: (c) Autotelik Media Ltd 2011
2
+ # Author :: Tom Statter
3
+ # Date :: Summer 2011
4
+ #
5
+ # License:: MIT - Free, OpenSource
6
+ #
7
+ # Details:: Specification for Spree aspect of datashift gem.
8
+ #
9
+ # Provides Loaders and rake tasks specifically tailored for uploading or exporting
10
+ # Spree Products, associations and Images
11
+ #
12
+ require File.dirname(__FILE__) + '/spec_helper'
13
+
14
+ require 'spree_helper'
15
+ require 'product_loader'
16
+
17
+ include DataShift
18
+
19
+ describe 'SpreeLoader' do
20
+
21
+
22
+ before(:all) do
23
+ SpecHelper::before_all_spree
24
+ end
25
+
26
+ before(:each) do
27
+
28
+ begin
29
+
30
+ include SpecHelper
31
+ extend SpecHelper
32
+
33
+ before_each_spree
34
+
35
+ @klass.count.should == 0
36
+
37
+ MethodDictionary.clear
38
+ MethodDictionary.find_operators( @klass )
39
+
40
+ @product_loader = DataShift::SpreeHelper::ProductLoader.new
41
+ rescue => e
42
+ puts e.inspect
43
+ puts e.backtrace
44
+ end
45
+ end
46
+
47
+
48
+ it "should load Products with associated image" do
49
+
50
+ @product_loader.perform_load( SpecHelper::spree_fixture('SpreeProductsWithImages.csv'), :mandatory => ['sku', 'name', 'price'] )
51
+
52
+ p = @klass.find_by_name("Demo Product for AR Loader")
53
+
54
+ p.name.should == "Demo Product for AR Loader"
55
+ p.images.should have_exactly(1).items
56
+
57
+ @klass.all.each {|p| p.images.should have_exactly(1).items }
58
+ end
59
+
60
+
61
+ it "should be able to assign Images to preloaded Products" do
62
+
63
+ @product_loader.perform_load( SpecHelper::spree_fixture('SpreeProductsMultiColumn.csv'), :mandatory => ['sku', 'name', 'price'] )
64
+
65
+ @Image_klass.all.size.should == 0
66
+
67
+ @klass.all.each {|p| p.images.should have_exactly(0).items }
68
+
69
+ loader = DataShift::SpreeHelper::ImageLoader.new
70
+
71
+ end
72
+
73
+ end
@@ -83,12 +83,16 @@ describe 'SpreeLoader' do
83
83
  test_basic_product('SpreeProductsSimple.xls')
84
84
  end
85
85
 
86
- it "should load basic Products from .csv via Spree loader" do
86
+ it "should load basic Products from .csv via Spree loader", :csv => true do
87
87
  test_basic_product('SpreeProductsSimple.csv')
88
88
  end
89
89
 
90
+ it "should raise an error for missing file" do
91
+ lambda { test_basic_product('SpreeProductsSimple.txt') }.should raise_error BadFile
92
+ end
93
+
90
94
  it "should raise an error for unsupported file types" do
91
- lambda { test_basic_product('SpreeProductsSimple.xml') }.should raise_error UnsupportedFileType
95
+ lambda { test_basic_product('SpreeProductsDefaults.yml') }.should raise_error UnsupportedFileType
92
96
  end
93
97
 
94
98
  def test_basic_product( source )
@@ -116,6 +120,53 @@ describe 'SpreeLoader' do
116
120
  @klass.last.count_on_hand.should == 23
117
121
  end
118
122
 
123
+
124
+ it "should support default values for Spree Products loader", :fail => true do
125
+
126
+ @expected_time = Time.now.to_s(:db)
127
+
128
+ @product_loader.set_default_value('available_on', @expected_time)
129
+ @product_loader.set_default_value('cost_price', 1.0 )
130
+ @product_loader.set_default_value('meta_description', 'super duper meta desc.' )
131
+ @product_loader.set_default_value('meta_keywords', 'techno dubstep d&b' )
132
+
133
+
134
+ @product_loader.set_prefix('sku', 'SPEC_')
135
+
136
+ test_default_values
137
+
138
+ end
139
+
140
+ it "should support default values from config for Spree Products loader", :fail => true do
141
+
142
+ @product_loader.configure_from( SpecHelper::spree_fixture('SpreeProductsDefaults.yml') )
143
+
144
+ @product_loader.set_prefix('sku', 'SPEC_')
145
+
146
+ test_default_values
147
+
148
+ end
149
+
150
+ def test_default_values
151
+ @product_loader.perform_load( SpecHelper::spree_fixture('SpreeProductsMandatoryOnly.xls'), :mandatory => ['sku', 'name', 'price'] )
152
+
153
+ @klass.count.should == 3
154
+
155
+ @product_loader.failed_objects.size.should == 0
156
+ @product_loader.loaded_objects.size.should == 3
157
+
158
+ p = @klass.first
159
+
160
+ p.sku.should == "SPEC_SIMPLE_001"
161
+
162
+ @klass.all { |p|
163
+ p.sku.should.include "SPEC_"
164
+ p.cost_price = 1.0
165
+ p.available_on.should == @expected_time
166
+ p.meta_description.should == 'super duper meta desc.'
167
+ p.meta_keywords.should == 'techno dubstep d&b'
168
+ }
169
+ end
119
170
 
120
171
  # Operation and results should be identical when loading multiple associations
121
172
  # if using either single column embedded syntax, or one column per entry.
@@ -304,15 +355,6 @@ describe 'SpreeLoader' do
304
355
 
305
356
 
306
357
  end
307
-
308
- it "should load Products with associated image", :img => true do
309
- pending("embedded images")
310
- @product_loader.perform_load( SpecHelper::spree_fixture('SpreeProductsWithImages.csv'), :mandatory => ['sku', 'name', 'price'] )
311
-
312
- p = @klass.find_by_name("Demo Product for AR Loader")
313
-
314
- p.images.should have_exactly(1).items
315
- end
316
358
 
317
359
 
318
360
  # REPEAT THE WHOLE TEST SUITE VIA CSV
@@ -334,14 +376,6 @@ describe 'SpreeLoader' do
334
376
  expected_multi_column_taxons
335
377
  end
336
378
 
337
- it "should load Products with assoicated image" do
338
- test_variants_creation('SpreeProductsMultiColumn.csv')
339
-
340
- expected_multi_column_properties
341
-
342
- expected_multi_column_taxons
343
- end
344
-
345
379
 
346
380
  it "should raise exception when mandatory columns missing from .xls", :ex => true do
347
381
  expect {@product_loader.perform_load($SpreeNegativeFixturePath + '/SpreeProdMissManyMandatory.xls', :mandatory => ['sku', 'name', 'price'] )}.to raise_error(DataShift::MissingMandatoryError)
@@ -14,7 +14,8 @@ namespace :datashift do
14
14
 
15
15
  namespace :spree do
16
16
 
17
- desc "Populate the DB with images.\nDefault location db/image_seeds, or specify :input=<path> or dir under db/image_seeds with :folder"
17
+ #DEPRECATED FOTR THOR
18
+ #desc "Populate the DB with images.\nDefault location db/image_seeds, or specify :input=<path> or dir under db/image_seeds with :folder"
18
19
  # :dummy => dummy run without actual saving to DB
19
20
  task :images, [:input, :folder, :dummy, :sku, :skip_if_no_assoc, :skip_if_loaded, :model] => :environment do |t, args|
20
21
 
@@ -30,33 +31,37 @@ namespace :datashift do
30
31
  @image_cache = File.join(@image_cache, args[:folder]) if(args[:folder])
31
32
  end
32
33
 
33
- attachment_klazz = Product
34
+
35
+ attachment_klazz = SpreeHelper::get_spree_class('Product' )
36
+ sku_klazz = SpreeHelper::get_spree_class('Variant' )
34
37
 
35
- begin
36
- attachment_klazz = Kernel.const_get(args[:model]) if(args[:model])
37
- rescue NameError
38
- attachment_klazz = Product
39
- end
38
+ # TODO generalise for any paperclip project, for now just Spree
39
+ #begin
40
+ # attachment_klazz = Kernel.const_get(args[:model]) if(args[:model])
41
+ # rescue NameError
42
+ # raise "Could not find contant for model #{args[:model]}"
43
+ #end
40
44
 
41
45
  image_loader = ImageLoader.new
42
46
 
43
- if(File.exists? @image_cache )
47
+ if(File.directory? @image_cache )
44
48
  puts "Loading images from #{@image_cache}"
45
49
 
46
50
  missing_records = []
47
- Dir.glob("#{@image_cache}/*.{jpg,png,gif}") do |image_name|
51
+ Dir.glob("#{@image_cache}/**/*.{jpg,png,gif}") do |image_name|
48
52
 
49
- puts "Processing #{image_name} : #{File.exists?(image_name)}"
50
53
  base_name = File.basename(image_name, '.*')
51
-
54
+
55
+ puts "Processing #{base_name} : #{File.exists?(image_name)}"
56
+
52
57
  record = nil
53
- if(attachment_klazz == Product && args[:sku])
58
+ if(args[:sku])
54
59
  sku = base_name.slice!(/\w+/)
55
60
  sku.strip!
56
61
  base_name.strip!
57
62
 
58
63
  puts "Looking fo SKU #{sku}"
59
- record = Variant.find_by_sku(sku)
64
+ record = sku_klazz.find_by_sku(sku)
60
65
  if record
61
66
  record = record.product # SKU stored on Variant but we want it's master Product
62
67
  else
metadata CHANGED
@@ -2,7 +2,7 @@
2
2
  name: datashift
3
3
  version: !ruby/object:Gem::Version
4
4
  prerelease:
5
- version: 0.2.2
5
+ version: 0.4.0
6
6
  platform: ruby
7
7
  authors:
8
8
  - Thomas Statter
@@ -10,7 +10,7 @@ autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
12
 
13
- date: 2012-03-05 00:00:00 Z
13
+ date: 2012-03-12 00:00:00 Z
14
14
  dependencies: []
15
15
 
16
16
  description: A suite of tools to move data between ActiveRecord models,databases,applications like Excel/Open Office, files and projects including Spree
@@ -36,11 +36,14 @@ files:
36
36
  - lib/datashift.rb
37
37
  - lib/datashift/exceptions.rb
38
38
  - lib/datashift/file_definitions.rb
39
+ - lib/datashift/logging.rb
39
40
  - lib/datashift/mapping_file_definitions.rb
40
41
  - lib/datashift/method_detail.rb
42
+ - lib/datashift/method_details_manager.rb
41
43
  - lib/datashift/method_dictionary.rb
42
44
  - lib/datashift/method_mapper.rb
43
45
  - lib/datashift/model_mapper.rb
46
+ - lib/datashift/populator.rb
44
47
  - lib/exporters/csv_exporter.rb
45
48
  - lib/exporters/excel_exporter.rb
46
49
  - lib/exporters/exporter_base.rb
@@ -72,6 +75,9 @@ files:
72
75
  - lib/loaders/spree/image_loader.rb
73
76
  - lib/loaders/spree/product_loader.rb
74
77
  - lib/thor/generate_excel.thor
78
+ - lib/thor/import_excel.thor
79
+ - lib/thor/spree/bootstrap_cleanup.thor
80
+ - lib/thor/spree/products_images.thor
75
81
  - public/spree/products/large/DEMO_001_ror_bag.jpeg
76
82
  - public/spree/products/large/DEMO_002_Powerstation.jpg
77
83
  - public/spree/products/large/DEMO_003_ror_mug.jpeg
@@ -122,6 +128,8 @@ files:
122
128
  - spec/fixtures/simple_template_spec.xls
123
129
  - spec/fixtures/spree/SpreeProducts.csv
124
130
  - spec/fixtures/spree/SpreeProducts.xls
131
+ - spec/fixtures/spree/SpreeProductsDefaults.yml
132
+ - spec/fixtures/spree/SpreeProductsMandatoryOnly.xls
125
133
  - spec/fixtures/spree/SpreeProductsMultiColumn.csv
126
134
  - spec/fixtures/spree/SpreeProductsMultiColumn.xls
127
135
  - spec/fixtures/spree/SpreeProductsSimple.csv
@@ -137,6 +145,7 @@ files:
137
145
  - spec/spec_helper.rb
138
146
  - spec/spree_exporter_spec.rb
139
147
  - spec/spree_generator_spec.rb
148
+ - spec/spree_images_loader_spec.rb
140
149
  - spec/spree_loader_spec.rb
141
150
  - spec/spree_method_mapping_spec.rb
142
151
  - tasks/config/seed_fu_product_template.erb
@@ -146,7 +155,6 @@ files:
146
155
  - tasks/import/csv.rake
147
156
  - tasks/import/excel.rake
148
157
  - tasks/spree/image_load.rake
149
- - tasks/spree/product_loader.rake
150
158
  - tasks/word_to_seedfu.rake
151
159
  - test/helper.rb
152
160
  - test/test_interact.rb
@@ -1,44 +0,0 @@
1
- # Copyright:: (c) Autotelik Media Ltd 2011
2
- # Author :: Tom Statter
3
- # Date :: Feb 2011
4
- # License:: MIT. Free, Open Source.
5
- #
6
- # REQUIRES: JRuby access to Java
7
- #
8
- # Usage::
9
- #
10
- # e.g. => jruby -S rake datashift:spree:products input=vendor/extensions/autotelik/fixtures/SiteSpreadsheetInfo.xls
11
- # => jruby -S rake datashift:spree:products input=C:\MyProducts.xls verbose=true
12
- #
13
- require 'datashift'
14
-
15
- namespace :datashift do
16
-
17
- namespace :spree do
18
-
19
- desc "Populate Spree Product/Variant data from .xls (Excel) or CSV file"
20
- task :products, [:input, :verbose, :sku_prefix] => :environment do |t, args|
21
-
22
- input = ENV['input']
23
-
24
- raise "USAGE: jruby -S rake datashift:spree:products input=excel_file.xls" unless input
25
- raise "ERROR: Could not find file #{args[:input]}" unless File.exists?(input)
26
-
27
- require 'product_loader'
28
-
29
- # COLUMNS WITH DEFAULTS - TODO create YAML configuration file to drive defaults etc
30
-
31
- loader = DataShift::ProductLoader.new
32
-
33
- loader.set_default_value('available_on', Time.now.to_s(:db) )
34
- loader.set_default_value('cost_price', 0.0 )
35
-
36
- loader.set_prefix('sku', args[:sku_prefix] ) if(args[:sku_prefix])
37
-
38
- puts "Loading from file: #{input}"
39
-
40
- loader.perform_load(input, :mandatory => ['sku', 'name', 'price'] )
41
- end
42
- end
43
-
44
- end