datashift 0.1.0 → 0.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/.document +5 -5
- data/LICENSE.txt +26 -26
- data/README.markdown +305 -303
- data/README.rdoc +19 -19
- data/Rakefile +93 -93
- data/VERSION +1 -1
- data/datashift-0.1.0.gem +0 -0
- data/datashift.gemspec +152 -136
- data/lib/applications/jruby/jexcel_file.rb +408 -408
- data/lib/applications/jruby/word.rb +79 -79
- data/lib/datashift.rb +152 -152
- data/lib/datashift/exceptions.rb +11 -11
- data/lib/datashift/file_definitions.rb +353 -353
- data/lib/datashift/mapping_file_definitions.rb +87 -87
- data/lib/datashift/method_detail.rb +275 -275
- data/lib/datashift/method_dictionary.rb +209 -209
- data/lib/datashift/method_mapper.rb +90 -90
- data/lib/generators/csv_generator.rb +36 -36
- data/lib/generators/excel_generator.rb +122 -122
- data/lib/generators/generator_base.rb +13 -13
- data/lib/helpers/core_ext/to_b.rb +24 -24
- data/lib/helpers/spree_helper.rb +153 -155
- data/lib/java/poi-3.7/LICENSE +507 -507
- data/lib/java/poi-3.7/NOTICE +21 -21
- data/lib/java/poi-3.7/RELEASE_NOTES.txt +115 -115
- data/lib/loaders/csv_loader.rb +98 -98
- data/lib/loaders/excel_loader.rb +155 -155
- data/lib/loaders/loader_base.rb +420 -420
- data/lib/loaders/spreadsheet_loader.rb +136 -136
- data/lib/loaders/spree/image_loader.rb +63 -64
- data/lib/loaders/spree/product_loader.rb +248 -250
- data/public/spree/products/large/DEMO_001_ror_bag.jpeg +0 -0
- data/public/spree/products/large/DEMO_002_Powerstation.jpg +0 -0
- data/public/spree/products/large/DEMO_003_ror_mug.jpeg +0 -0
- data/public/spree/products/mini/DEMO_001_ror_bag.jpeg +0 -0
- data/public/spree/products/mini/DEMO_002_Powerstation.jpg +0 -0
- data/public/spree/products/mini/DEMO_003_ror_mug.jpeg +0 -0
- data/public/spree/products/original/DEMO_001_ror_bag.jpeg +0 -0
- data/public/spree/products/original/DEMO_002_Powerstation.jpg +0 -0
- data/public/spree/products/original/DEMO_003_ror_mug.jpeg +0 -0
- data/public/spree/products/product/DEMO_001_ror_bag.jpeg +0 -0
- data/public/spree/products/product/DEMO_002_Powerstation.jpg +0 -0
- data/public/spree/products/product/DEMO_003_ror_mug.jpeg +0 -0
- data/public/spree/products/small/DEMO_001_ror_bag.jpeg +0 -0
- data/public/spree/products/small/DEMO_002_Powerstation.jpg +0 -0
- data/public/spree/products/small/DEMO_003_ror_mug.jpeg +0 -0
- data/spec/csv_loader_spec.rb +30 -30
- data/spec/datashift_spec.rb +26 -26
- data/spec/db/migrate/20110803201325_create_test_bed.rb +85 -85
- data/spec/excel_exporter_spec.rb +78 -78
- data/spec/excel_generator_spec.rb +78 -78
- data/spec/excel_loader_spec.rb +223 -223
- data/spec/file_definitions.rb +141 -141
- data/spec/fixtures/ProjectsDefaults.yml +29 -29
- data/spec/fixtures/config/database.yml +27 -24
- data/spec/fixtures/datashift_Spree_db.sqlite +0 -0
- data/spec/fixtures/interact_models_db.sqlite +0 -0
- data/spec/fixtures/negative/SpreeProdMiss1Mandatory.csv +4 -4
- data/spec/fixtures/negative/SpreeProdMissManyMandatory.csv +4 -4
- data/spec/fixtures/spree/SpreeProducts.csv +4 -4
- data/spec/fixtures/spree/SpreeProductsMultiColumn.csv +4 -4
- data/spec/fixtures/spree/SpreeProductsSimple.csv +4 -4
- data/spec/fixtures/spree/SpreeProductsWithImages.csv +4 -0
- data/spec/fixtures/spree/SpreeZoneExample.csv +5 -5
- data/spec/fixtures/test_model_defs.rb +57 -57
- data/spec/loader_spec.rb +120 -120
- data/spec/method_dictionary_spec.rb +242 -242
- data/spec/method_mapper_spec.rb +41 -41
- data/spec/spec_helper.rb +116 -116
- data/spec/spree_generator_spec.rb +64 -64
- data/spec/spree_loader_spec.rb +324 -327
- data/spec/spree_method_mapping_spec.rb +214 -214
- data/tasks/config/seed_fu_product_template.erb +15 -15
- data/tasks/config/tidy_config.txt +12 -12
- data/tasks/db_tasks.rake +65 -65
- data/tasks/excel_generator.rake +78 -78
- data/tasks/file_tasks.rake +36 -36
- data/tasks/import/csv.rake +49 -49
- data/tasks/import/excel.rake +71 -71
- data/tasks/spree/image_load.rake +108 -108
- data/tasks/spree/product_loader.rake +43 -43
- data/tasks/word_to_seedfu.rake +166 -166
- data/test/helper.rb +18 -18
- data/test/test_interact.rb +7 -7
- metadata +22 -3
- data/spec/fixtures/interact_spree_db.sqlite +0 -0
data/spec/method_mapper_spec.rb
CHANGED
@@ -1,42 +1,42 @@
|
|
1
|
-
# Copyright:: (c) Autotelik Media Ltd 2011
|
2
|
-
# Author :: Tom Statter
|
3
|
-
# Date :: Aug 2011
|
4
|
-
# License:: MIT
|
5
|
-
#
|
6
|
-
# Details:: Specs for MethodMapper aspect of Active Record Loader
|
7
|
-
# MethodMapper provides the bridge between 'strings' e.g column headings
|
8
|
-
# and a classes different types of assignment operators
|
9
|
-
#
|
10
|
-
require File.dirname(__FILE__) + '/spec_helper'
|
11
|
-
|
12
|
-
describe 'Method Mapping' do
|
13
|
-
|
14
|
-
before(:all) do
|
15
|
-
db_connect( 'test_file' ) # , test_memory, test_mysql
|
16
|
-
|
17
|
-
# load our test model definitions - Project etc
|
18
|
-
require ifixture_file('test_model_defs')
|
19
|
-
|
20
|
-
migrate_up
|
21
|
-
end
|
22
|
-
|
23
|
-
before(:each) do
|
24
|
-
MethodDictionary.clear
|
25
|
-
|
26
|
-
MethodDictionary.find_operators( Project )
|
27
|
-
MethodDictionary.find_operators( Milestone )
|
28
|
-
|
29
|
-
|
30
|
-
MethodDictionary.build_method_details( Project )
|
31
|
-
MethodDictionary.build_method_details( Milestone )
|
32
|
-
|
33
|
-
end
|
34
|
-
|
35
|
-
it "should find a set of methods based on a list of column names" do
|
36
|
-
pending("key API - map column headers to set of methods")
|
37
|
-
|
38
|
-
@method_mapper.map_inbound_to_methods( load_object_class, @headers )
|
39
|
-
end
|
40
|
-
|
41
|
-
|
1
|
+
# Copyright:: (c) Autotelik Media Ltd 2011
|
2
|
+
# Author :: Tom Statter
|
3
|
+
# Date :: Aug 2011
|
4
|
+
# License:: MIT
|
5
|
+
#
|
6
|
+
# Details:: Specs for MethodMapper aspect of Active Record Loader
|
7
|
+
# MethodMapper provides the bridge between 'strings' e.g column headings
|
8
|
+
# and a classes different types of assignment operators
|
9
|
+
#
|
10
|
+
require File.dirname(__FILE__) + '/spec_helper'
|
11
|
+
|
12
|
+
describe 'Method Mapping' do
|
13
|
+
|
14
|
+
before(:all) do
|
15
|
+
db_connect( 'test_file' ) # , test_memory, test_mysql
|
16
|
+
|
17
|
+
# load our test model definitions - Project etc
|
18
|
+
require ifixture_file('test_model_defs')
|
19
|
+
|
20
|
+
migrate_up
|
21
|
+
end
|
22
|
+
|
23
|
+
before(:each) do
|
24
|
+
MethodDictionary.clear
|
25
|
+
|
26
|
+
MethodDictionary.find_operators( Project )
|
27
|
+
MethodDictionary.find_operators( Milestone )
|
28
|
+
|
29
|
+
|
30
|
+
MethodDictionary.build_method_details( Project )
|
31
|
+
MethodDictionary.build_method_details( Milestone )
|
32
|
+
|
33
|
+
end
|
34
|
+
|
35
|
+
it "should find a set of methods based on a list of column names" do
|
36
|
+
pending("key API - map column headers to set of methods")
|
37
|
+
|
38
|
+
@method_mapper.map_inbound_to_methods( load_object_class, @headers )
|
39
|
+
end
|
40
|
+
|
41
|
+
|
42
42
|
end
|
data/spec/spec_helper.rb
CHANGED
@@ -1,117 +1,117 @@
|
|
1
|
-
require 'erb'
|
2
|
-
require 'yaml'
|
3
|
-
|
4
|
-
require File.dirname(__FILE__) + '/../lib/datashift'
|
5
|
-
|
6
|
-
include DataShift
|
7
|
-
|
8
|
-
#.# Copyright:: (c) Autotelik Media Ltd 2011
|
9
|
-
# Author :: Tom Statter
|
10
|
-
# Date :: Aug 2011
|
11
|
-
# License:: MIT
|
12
|
-
#
|
13
|
-
# Details:: Spec Helper for Active Record Loader
|
14
|
-
#
|
15
|
-
#
|
16
|
-
# We are not setup as a Rails project so need to mimic an active record database setup so
|
17
|
-
# we have some AR models top test against. Create an in memory database from scratch.
|
18
|
-
#
|
19
|
-
$DataShiftFixturePath = File.join(File.dirname(__FILE__), 'fixtures')
|
20
|
-
$DataShiftDatabaseYml = File.join($DataShiftFixturePath, 'config/database.yml')
|
21
|
-
|
22
|
-
module DataShift
|
23
|
-
|
24
|
-
|
25
|
-
def db_connect( env = 'test_file', version = nil)
|
26
|
-
|
27
|
-
version ? gem('activerecord', version) : gem('activerecord')
|
28
|
-
|
29
|
-
require 'active_record'
|
30
|
-
|
31
|
-
# Some active record stuff seems to rely on the RAILS_ENV being set ?
|
32
|
-
|
33
|
-
ENV['RAILS_ENV'] = env
|
34
|
-
|
35
|
-
configuration = {}
|
36
|
-
|
37
|
-
configuration[:database_configuration] = YAML::load( ERB.new(IO.read($DataShiftDatabaseYml)).result )
|
38
|
-
db = configuration[:database_configuration][ env ]
|
39
|
-
|
40
|
-
puts "Setting DB Config - #{db.inspect}"
|
41
|
-
ActiveRecord::Base.configurations = db
|
42
|
-
|
43
|
-
#ActiveRecord::Base.logger = Logger.new(STDOUT)
|
44
|
-
|
45
|
-
require 'logger'
|
46
|
-
logdir = File.dirname(__FILE__) + '/logs'
|
47
|
-
FileUtils.mkdir_p(logdir) unless File.exists?(logdir)
|
48
|
-
ActiveRecord::Base.logger = Logger.new(logdir + '/
|
49
|
-
|
50
|
-
@ilog = ActiveRecord::Base.logger
|
51
|
-
|
52
|
-
puts "Connecting to DB"
|
53
|
-
ActiveRecord::Base.establish_connection( db )
|
54
|
-
|
55
|
-
|
56
|
-
#
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
def db_clear
|
64
|
-
[Project, Milestone, Category, Version, LoaderRelease].each {|x| x.delete_all}
|
65
|
-
end
|
66
|
-
|
67
|
-
def load_in_memory
|
68
|
-
load "#{Rails.root}/db/schema.rb"
|
69
|
-
end
|
70
|
-
|
71
|
-
def migrate_up
|
72
|
-
ActiveRecord::Migrator.up( File.dirname(__FILE__) + '/db/migrate')
|
73
|
-
end
|
74
|
-
|
75
|
-
def results_path
|
76
|
-
File.join($DataShiftFixturePath, 'results')
|
77
|
-
end
|
78
|
-
|
79
|
-
def results_clear
|
80
|
-
begin FileUtils.rm_rf(results_path); rescue; end
|
81
|
-
|
82
|
-
FileUtils.mkdir(results_path) unless File.exists?(results_path);
|
83
|
-
end
|
84
|
-
|
85
|
-
# Return location of an expected results file and ensure tree clean before test
|
86
|
-
def result_file( name )
|
87
|
-
expect = File.join(results_path, name)
|
88
|
-
|
89
|
-
begin FileUtils.rm(expect); rescue; end
|
90
|
-
|
91
|
-
expect
|
92
|
-
end
|
93
|
-
|
94
|
-
def ifixture_file( name )
|
95
|
-
File.join($DataShiftFixturePath, name)
|
96
|
-
end
|
97
|
-
|
98
|
-
end
|
99
|
-
|
100
|
-
|
101
|
-
RSpec.configure do |config|
|
102
|
-
# config.use_transactional_fixtures = true
|
103
|
-
# config.use_instantiated_fixtures = false
|
104
|
-
# config.fixture_path = RAILS_ROOT + '/spec/fixtures'
|
105
|
-
|
106
|
-
# You can declare fixtures for each behaviour like this:
|
107
|
-
# describe "...." do
|
108
|
-
# fixtures :table_a, :table_b
|
109
|
-
#
|
110
|
-
# Alternatively, if you prefer to declare them only once, you can
|
111
|
-
# do so here, like so ...
|
112
|
-
#
|
113
|
-
# config.global_fixtures = :table_a, :table_b
|
114
|
-
#
|
115
|
-
# If you declare global fixtures, be aware that they will be declared
|
116
|
-
# for all of your examples, even those that don't use them.
|
1
|
+
require 'erb'
|
2
|
+
require 'yaml'
|
3
|
+
|
4
|
+
require File.dirname(__FILE__) + '/../lib/datashift'
|
5
|
+
|
6
|
+
include DataShift
|
7
|
+
|
8
|
+
#.# Copyright:: (c) Autotelik Media Ltd 2011
|
9
|
+
# Author :: Tom Statter
|
10
|
+
# Date :: Aug 2011
|
11
|
+
# License:: MIT
|
12
|
+
#
|
13
|
+
# Details:: Spec Helper for Active Record Loader
|
14
|
+
#
|
15
|
+
#
|
16
|
+
# We are not setup as a Rails project so need to mimic an active record database setup so
|
17
|
+
# we have some AR models top test against. Create an in memory database from scratch.
|
18
|
+
#
|
19
|
+
$DataShiftFixturePath = File.join(File.dirname(__FILE__), 'fixtures')
|
20
|
+
$DataShiftDatabaseYml = File.join($DataShiftFixturePath, 'config/database.yml')
|
21
|
+
|
22
|
+
module DataShift
|
23
|
+
|
24
|
+
|
25
|
+
def db_connect( env = 'test_file', version = nil)
|
26
|
+
|
27
|
+
version ? gem('activerecord', version) : gem('activerecord')
|
28
|
+
|
29
|
+
require 'active_record'
|
30
|
+
|
31
|
+
# Some active record stuff seems to rely on the RAILS_ENV being set ?
|
32
|
+
|
33
|
+
ENV['RAILS_ENV'] = env
|
34
|
+
|
35
|
+
configuration = {}
|
36
|
+
|
37
|
+
configuration[:database_configuration] = YAML::load( ERB.new(IO.read($DataShiftDatabaseYml)).result )
|
38
|
+
db = configuration[:database_configuration][ env ]
|
39
|
+
|
40
|
+
puts "Setting DB Config - #{db.inspect}"
|
41
|
+
ActiveRecord::Base.configurations = db
|
42
|
+
|
43
|
+
#ActiveRecord::Base.logger = Logger.new(STDOUT)
|
44
|
+
|
45
|
+
require 'logger'
|
46
|
+
logdir = File.dirname(__FILE__) + '/logs'
|
47
|
+
FileUtils.mkdir_p(logdir) unless File.exists?(logdir)
|
48
|
+
ActiveRecord::Base.logger = Logger.new(logdir + '/datashift_spec.log')
|
49
|
+
|
50
|
+
@ilog = ActiveRecord::Base.logger
|
51
|
+
|
52
|
+
puts "Connecting to DB"
|
53
|
+
ActiveRecord::Base.establish_connection( db )
|
54
|
+
|
55
|
+
# See errors #<NameError: uninitialized constant RAILS_CACHE> when doing save (AR without Rails)
|
56
|
+
# so copied this from ... Rails::Initializer.initialize_cache
|
57
|
+
Object.const_set "RAILS_CACHE", ActiveSupport::Cache.lookup_store( :memory_store )
|
58
|
+
|
59
|
+
@ilog.info "Connected to DB - #{ActiveRecord::Base.connection.inspect}"
|
60
|
+
end
|
61
|
+
|
62
|
+
# These are our test models with associations
|
63
|
+
def db_clear
|
64
|
+
[Project, Milestone, Category, Version, LoaderRelease].each {|x| x.delete_all}
|
65
|
+
end
|
66
|
+
|
67
|
+
def load_in_memory
|
68
|
+
load "#{Rails.root}/db/schema.rb"
|
69
|
+
end
|
70
|
+
|
71
|
+
def migrate_up
|
72
|
+
ActiveRecord::Migrator.up( File.dirname(__FILE__) + '/db/migrate')
|
73
|
+
end
|
74
|
+
|
75
|
+
def results_path
|
76
|
+
File.join($DataShiftFixturePath, 'results')
|
77
|
+
end
|
78
|
+
|
79
|
+
def results_clear
|
80
|
+
begin FileUtils.rm_rf(results_path); rescue; end
|
81
|
+
|
82
|
+
FileUtils.mkdir(results_path) unless File.exists?(results_path);
|
83
|
+
end
|
84
|
+
|
85
|
+
# Return location of an expected results file and ensure tree clean before test
|
86
|
+
def result_file( name )
|
87
|
+
expect = File.join(results_path, name)
|
88
|
+
|
89
|
+
begin FileUtils.rm(expect); rescue; end
|
90
|
+
|
91
|
+
expect
|
92
|
+
end
|
93
|
+
|
94
|
+
def ifixture_file( name )
|
95
|
+
File.join($DataShiftFixturePath, name)
|
96
|
+
end
|
97
|
+
|
98
|
+
end
|
99
|
+
|
100
|
+
|
101
|
+
RSpec.configure do |config|
|
102
|
+
# config.use_transactional_fixtures = true
|
103
|
+
# config.use_instantiated_fixtures = false
|
104
|
+
# config.fixture_path = RAILS_ROOT + '/spec/fixtures'
|
105
|
+
|
106
|
+
# You can declare fixtures for each behaviour like this:
|
107
|
+
# describe "...." do
|
108
|
+
# fixtures :table_a, :table_b
|
109
|
+
#
|
110
|
+
# Alternatively, if you prefer to declare them only once, you can
|
111
|
+
# do so here, like so ...
|
112
|
+
#
|
113
|
+
# config.global_fixtures = :table_a, :table_b
|
114
|
+
#
|
115
|
+
# If you declare global fixtures, be aware that they will be declared
|
116
|
+
# for all of your examples, even those that don't use them.
|
117
117
|
end
|
@@ -1,65 +1,65 @@
|
|
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 generator 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 'excel_generator'
|
16
|
-
|
17
|
-
include DataShift
|
18
|
-
|
19
|
-
describe 'SpreeLoader' do
|
20
|
-
|
21
|
-
before(:all) do
|
22
|
-
|
23
|
-
# we are not a Spree project, nor is it practical to externally generate
|
24
|
-
# a complete Spree application for testing so we implement a mini migrate/boot of our own
|
25
|
-
Spree.load() # require Spree gems
|
26
|
-
|
27
|
-
# key to YAML db e.g test_memory, test_mysql
|
28
|
-
db_connect( 'test_spree_standalone' )
|
29
|
-
|
30
|
-
Spree.boot # create a sort-of Spree app
|
31
|
-
|
32
|
-
Spree.migrate_up # create an sqlite Spree database on the fly
|
33
|
-
end
|
34
|
-
|
35
|
-
before do
|
36
|
-
end
|
37
|
-
|
38
|
-
it "should export any Spree model to .xls spreedsheet" do
|
39
|
-
|
40
|
-
expect = result_file('optionstypes_export_spec.xls')
|
41
|
-
|
42
|
-
gen = ExcelGenerator.new(expect)
|
43
|
-
|
44
|
-
items = OptionType.all
|
45
|
-
|
46
|
-
gen.export(items)
|
47
|
-
|
48
|
-
File.exists?(expect).should be_true
|
49
|
-
end
|
50
|
-
|
51
|
-
it "should export a Spree model and associations to .xls spreedsheet" do
|
52
|
-
|
53
|
-
expect = result_file('shiprates_export_spec.xls')
|
54
|
-
|
55
|
-
gen = ExcelGenerator.new(expect)
|
56
|
-
|
57
|
-
items = OptionType.all
|
58
|
-
|
59
|
-
gen.export_with_associations(OptionType, items)
|
60
|
-
|
61
|
-
File.exists?(expect).should be_true
|
62
|
-
|
63
|
-
end
|
64
|
-
|
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 generator 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 'excel_generator'
|
16
|
+
|
17
|
+
include DataShift
|
18
|
+
|
19
|
+
describe 'SpreeLoader' do
|
20
|
+
|
21
|
+
before(:all) do
|
22
|
+
|
23
|
+
# we are not a Spree project, nor is it practical to externally generate
|
24
|
+
# a complete Spree application for testing so we implement a mini migrate/boot of our own
|
25
|
+
Spree.load() # require Spree gems
|
26
|
+
|
27
|
+
# key to YAML db e.g test_memory, test_mysql
|
28
|
+
db_connect( 'test_spree_standalone' )
|
29
|
+
|
30
|
+
Spree.boot # create a sort-of Spree app
|
31
|
+
|
32
|
+
Spree.migrate_up # create an sqlite Spree database on the fly
|
33
|
+
end
|
34
|
+
|
35
|
+
before do
|
36
|
+
end
|
37
|
+
|
38
|
+
it "should export any Spree model to .xls spreedsheet" do
|
39
|
+
|
40
|
+
expect = result_file('optionstypes_export_spec.xls')
|
41
|
+
|
42
|
+
gen = ExcelGenerator.new(expect)
|
43
|
+
|
44
|
+
items = OptionType.all
|
45
|
+
|
46
|
+
gen.export(items)
|
47
|
+
|
48
|
+
File.exists?(expect).should be_true
|
49
|
+
end
|
50
|
+
|
51
|
+
it "should export a Spree model and associations to .xls spreedsheet" do
|
52
|
+
|
53
|
+
expect = result_file('shiprates_export_spec.xls')
|
54
|
+
|
55
|
+
gen = ExcelGenerator.new(expect)
|
56
|
+
|
57
|
+
items = OptionType.all
|
58
|
+
|
59
|
+
gen.export_with_associations(OptionType, items)
|
60
|
+
|
61
|
+
File.exists?(expect).should be_true
|
62
|
+
|
63
|
+
end
|
64
|
+
|
65
65
|
end
|
data/spec/spree_loader_spec.rb
CHANGED
@@ -1,328 +1,325 @@
|
|
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
|
-
before(:all) do
|
22
|
-
|
23
|
-
# key to YAML db e.g test_memory, test_mysql
|
24
|
-
db_connect( 'test_spree_standalone' )
|
25
|
-
|
26
|
-
# See errors #<NameError: uninitialized constant RAILS_CACHE> when doing save (AR without Rails)
|
27
|
-
# so copied this from ... Rails::Initializer.initialize_cache
|
28
|
-
Object.const_set "RAILS_CACHE", ActiveSupport::Cache.lookup_store( :memory_store )
|
29
|
-
|
30
|
-
RAILS_CACHE = ActiveSupport::Cache.lookup_store( :memory_store )
|
31
|
-
|
32
|
-
# we are not a Spree project, nor is it practical to externally generate
|
33
|
-
# a complete Spree application for testing so we implement a mini migrate/boot of our own
|
34
|
-
Spree.load() # require Spree gems
|
35
|
-
Spree.boot # create a sort-of Spree app
|
36
|
-
|
37
|
-
Spree.migrate_up # create an sqlite Spree database on the fly
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
$
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
@product_loader.
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
p
|
123
|
-
|
124
|
-
p.
|
125
|
-
p.
|
126
|
-
p.
|
127
|
-
p.
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
Product.
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
p.
|
165
|
-
|
166
|
-
p.
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
v
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
|
201
|
-
|
202
|
-
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
|
207
|
-
|
208
|
-
|
209
|
-
|
210
|
-
|
211
|
-
|
212
|
-
|
213
|
-
|
214
|
-
|
215
|
-
|
216
|
-
|
217
|
-
|
218
|
-
|
219
|
-
|
220
|
-
|
221
|
-
|
222
|
-
|
223
|
-
|
224
|
-
|
225
|
-
|
226
|
-
|
227
|
-
p3.
|
228
|
-
|
229
|
-
|
230
|
-
|
231
|
-
|
232
|
-
|
233
|
-
|
234
|
-
|
235
|
-
|
236
|
-
|
237
|
-
|
238
|
-
|
239
|
-
|
240
|
-
|
241
|
-
|
242
|
-
|
243
|
-
|
244
|
-
|
245
|
-
|
246
|
-
|
247
|
-
|
248
|
-
|
249
|
-
|
250
|
-
|
251
|
-
|
252
|
-
|
253
|
-
|
254
|
-
|
255
|
-
|
256
|
-
|
257
|
-
Product.
|
258
|
-
|
259
|
-
|
260
|
-
|
261
|
-
|
262
|
-
|
263
|
-
|
264
|
-
|
265
|
-
|
266
|
-
|
267
|
-
|
268
|
-
|
269
|
-
|
270
|
-
|
271
|
-
|
272
|
-
|
273
|
-
|
274
|
-
|
275
|
-
|
276
|
-
|
277
|
-
|
278
|
-
|
279
|
-
|
280
|
-
|
281
|
-
|
282
|
-
|
283
|
-
|
284
|
-
|
285
|
-
|
286
|
-
|
287
|
-
|
288
|
-
|
289
|
-
|
290
|
-
|
291
|
-
|
292
|
-
|
293
|
-
|
294
|
-
|
295
|
-
|
296
|
-
|
297
|
-
|
298
|
-
|
299
|
-
|
300
|
-
|
301
|
-
|
302
|
-
|
303
|
-
|
304
|
-
|
305
|
-
|
306
|
-
|
307
|
-
|
308
|
-
|
309
|
-
|
310
|
-
|
311
|
-
|
312
|
-
|
313
|
-
|
314
|
-
|
315
|
-
|
316
|
-
|
317
|
-
|
318
|
-
|
319
|
-
|
320
|
-
|
321
|
-
|
322
|
-
|
323
|
-
|
324
|
-
|
325
|
-
expect {@product_loader.perform_load($SpreeNegativeFixturePath + '/SpreeProdMiss1Mandatory.csv', :mandatory => 'sku' )}.to raise_error(DataShift::MissingMandatoryError)
|
326
|
-
end
|
327
|
-
|
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
|
+
before(:all) do
|
22
|
+
|
23
|
+
# key to YAML db e.g test_memory, test_mysql
|
24
|
+
db_connect( 'test_spree_standalone' )
|
25
|
+
|
26
|
+
# See errors #<NameError: uninitialized constant RAILS_CACHE> when doing save (AR without Rails)
|
27
|
+
# so copied this from ... Rails::Initializer.initialize_cache
|
28
|
+
Object.const_set "RAILS_CACHE", ActiveSupport::Cache.lookup_store( :memory_store )
|
29
|
+
|
30
|
+
RAILS_CACHE = ActiveSupport::Cache.lookup_store( :memory_store )
|
31
|
+
|
32
|
+
# we are not a Spree project, nor is it practical to externally generate
|
33
|
+
# a complete Spree application for testing so we implement a mini migrate/boot of our own
|
34
|
+
Spree.load() # require Spree gems
|
35
|
+
Spree.boot # create a sort-of Spree app
|
36
|
+
|
37
|
+
Spree.migrate_up # create an sqlite Spree database on the fly
|
38
|
+
|
39
|
+
$SpreeFixturePath = File.join($DataShiftFixturePath, 'spree')
|
40
|
+
|
41
|
+
$SpreeNegativeFixturePath = File.join($DataShiftFixturePath, 'negative')
|
42
|
+
end
|
43
|
+
|
44
|
+
def spree_fix( source)
|
45
|
+
File.join($SpreeFixturePath, source)
|
46
|
+
end
|
47
|
+
|
48
|
+
before(:each) do
|
49
|
+
|
50
|
+
MethodDictionary.clear
|
51
|
+
MethodDictionary.find_operators( Product )
|
52
|
+
|
53
|
+
# Reset main tables - TODO should really purge properly, or roll back a transaction
|
54
|
+
[OptionType, OptionValue, Product, Property, Variant, Taxonomy, Taxon, Zone].each { |x| x.delete_all }
|
55
|
+
|
56
|
+
Product.count.should == 0
|
57
|
+
|
58
|
+
Taxon.count.should == 0
|
59
|
+
|
60
|
+
# want to test both lookup and dynamic creation - this Taxonomy should be found, rest created
|
61
|
+
root = Taxonomy.create( :name => 'Paintings' )
|
62
|
+
Taxon.create( :name => 'Landscape', :taxonomy => root )
|
63
|
+
|
64
|
+
Taxon.count.should == 2
|
65
|
+
|
66
|
+
|
67
|
+
@product_loader = DataShift::Spree::ProductLoader.new
|
68
|
+
end
|
69
|
+
|
70
|
+
|
71
|
+
it "should process a simple .xls spreadsheet" do
|
72
|
+
|
73
|
+
Zone.delete_all
|
74
|
+
|
75
|
+
loader = ExcelLoader.new(Zone)
|
76
|
+
|
77
|
+
loader.perform_load( spree_fix('SpreeZoneExample.xls') )
|
78
|
+
|
79
|
+
loader.loaded_count.should == Zone.count
|
80
|
+
end
|
81
|
+
|
82
|
+
it "should process a simple csv file" do
|
83
|
+
|
84
|
+
Zone.delete_all
|
85
|
+
|
86
|
+
loader = CsvLoader.new(Zone)
|
87
|
+
|
88
|
+
loader.perform_load( spree_fix('SpreeZoneExample.csv') )
|
89
|
+
|
90
|
+
loader.loaded_count.should == Zone.count
|
91
|
+
end
|
92
|
+
|
93
|
+
|
94
|
+
# Loader should perform identically regardless of source, whether csv, .xls etc
|
95
|
+
|
96
|
+
it "should load basic Products .xls via Spree loader", :focus => true do
|
97
|
+
test_basic_product('SpreeProductsSimple.xls')
|
98
|
+
end
|
99
|
+
|
100
|
+
it "should load basic Products from .csv via Spree loader" do
|
101
|
+
test_basic_product('SpreeProductsSimple.csv')
|
102
|
+
end
|
103
|
+
|
104
|
+
it "should raise an error for unsupported file types" do
|
105
|
+
lambda { test_basic_product('SpreeProductsSimple.xml') }.should raise_error UnsupportedFileType
|
106
|
+
end
|
107
|
+
|
108
|
+
def test_basic_product( source )
|
109
|
+
|
110
|
+
@product_loader.perform_load( spree_fix(source), :mandatory => ['sku', 'name', 'price'] )
|
111
|
+
|
112
|
+
Product.count.should == 3
|
113
|
+
|
114
|
+
@product_loader.failed_objects.size.should == 0
|
115
|
+
@product_loader.loaded_objects.size.should == 3
|
116
|
+
|
117
|
+
@product_loader.loaded_count.should == Product.count
|
118
|
+
|
119
|
+
p = Product.first
|
120
|
+
|
121
|
+
p.sku.should == "SIMPLE_001"
|
122
|
+
p.price.should == 345.78
|
123
|
+
p.name.should == "Simple Product for AR Loader"
|
124
|
+
p.description.should == "blah blah"
|
125
|
+
p.cost_price.should == 320.00
|
126
|
+
p.option_types.should have_exactly(1).items
|
127
|
+
p.count_on_hand.should == 12
|
128
|
+
|
129
|
+
Product.last.option_types.should have_exactly(2).items
|
130
|
+
Product.last.count_on_hand.should == 23
|
131
|
+
end
|
132
|
+
|
133
|
+
|
134
|
+
# Operation and results should be identical when loading multiple associations
|
135
|
+
# if using either single column embedded syntax, or one column per entry.
|
136
|
+
|
137
|
+
it "should load Products and create Variants from single column" do
|
138
|
+
test_variants_creation('SpreeProducts.xls')
|
139
|
+
end
|
140
|
+
|
141
|
+
|
142
|
+
it "should load Products and create Variants from multiple column" do
|
143
|
+
test_variants_creation('SpreeProductsMultiColumn.xls')
|
144
|
+
end
|
145
|
+
|
146
|
+
def test_variants_creation( source )
|
147
|
+
@product_loader.perform_load( spree_fix(source), :mandatory => ['sku', 'name', 'price'] )
|
148
|
+
|
149
|
+
expected_multi_column_variants
|
150
|
+
end
|
151
|
+
|
152
|
+
|
153
|
+
def expected_multi_column_variants
|
154
|
+
|
155
|
+
# 3 MASTER products, 11 VARIANTS
|
156
|
+
Product.count.should == 3
|
157
|
+
Variant.count.should == 14
|
158
|
+
|
159
|
+
p = Product.first
|
160
|
+
|
161
|
+
p.sku.should == "DEMO_001"
|
162
|
+
|
163
|
+
p.sku.should == "DEMO_001"
|
164
|
+
p.price.should == 399.99
|
165
|
+
p.description.should == "blah blah"
|
166
|
+
p.cost_price.should == 320.00
|
167
|
+
|
168
|
+
Product.all.select {|m| m.is_master.should == true }
|
169
|
+
|
170
|
+
p.variants.should have_exactly(3).items
|
171
|
+
|
172
|
+
Variant.all[1].sku.should == "DEMO_001_0"
|
173
|
+
Variant.all[1].price.should == 399.99
|
174
|
+
|
175
|
+
v = p.variants[0]
|
176
|
+
|
177
|
+
v.sku.should == "DEMO_001_0"
|
178
|
+
v.price.should == 399.99
|
179
|
+
v.count_on_hand.should == 12
|
180
|
+
|
181
|
+
p.variants[1].count_on_hand.should == 6
|
182
|
+
p.variants[2].count_on_hand.should == 7
|
183
|
+
|
184
|
+
Variant.last.price.should == 50.34
|
185
|
+
Variant.last.count_on_hand.should == 18
|
186
|
+
|
187
|
+
@product_loader.failed_objects.size.should == 0
|
188
|
+
end
|
189
|
+
|
190
|
+
|
191
|
+
# Operation and results should be identical when loading multiple associations
|
192
|
+
# if using either single column embedded syntax, or one column per entry.
|
193
|
+
|
194
|
+
it "should load Products and multiple Properties from single column" do
|
195
|
+
test_properties_creation( 'SpreeProducts.xls' )
|
196
|
+
end
|
197
|
+
|
198
|
+
it "should load Products and multiple Properties from multiple column" do
|
199
|
+
test_properties_creation( 'SpreeProductsMultiColumn.xls' )
|
200
|
+
end
|
201
|
+
|
202
|
+
def test_properties_creation( source )
|
203
|
+
|
204
|
+
# want to test both lookup and dynamic creation - this Prop should be found, rest created
|
205
|
+
Property.create( :name => 'test_pp_001', :presentation => 'Test PP 001' )
|
206
|
+
|
207
|
+
Property.count.should == 1
|
208
|
+
|
209
|
+
@product_loader.perform_load( spree_fix(source), :mandatory => ['sku', 'name', 'price'] )
|
210
|
+
|
211
|
+
expected_multi_column_properties
|
212
|
+
|
213
|
+
end
|
214
|
+
|
215
|
+
def expected_multi_column_properties
|
216
|
+
Property.count.should == 4
|
217
|
+
|
218
|
+
Product.first.properties.should have_exactly(1).items
|
219
|
+
|
220
|
+
p3 = Product.all.last
|
221
|
+
|
222
|
+
p3.properties.should have_exactly(3).items
|
223
|
+
|
224
|
+
p3.properties.should include Property.find_by_name('test_pp_002')
|
225
|
+
|
226
|
+
# Test the optional text value got set on assigned product property
|
227
|
+
p3.product_properties.select {|p| p.value == 'Example free value' }.should have_exactly(1).items
|
228
|
+
|
229
|
+
end
|
230
|
+
|
231
|
+
# Operation and results should be identical when loading multiple associations
|
232
|
+
# if using either single column embedded syntax, or one column per entry.
|
233
|
+
|
234
|
+
it "should load Products and multiple Taxons from single column" do
|
235
|
+
test_taxon_creation( 'SpreeProducts.xls' )
|
236
|
+
end
|
237
|
+
|
238
|
+
it "should load Products and multiple Taxons from multiple columns" do
|
239
|
+
test_taxon_creation( 'SpreeProductsMultiColumn.xls' )
|
240
|
+
end
|
241
|
+
|
242
|
+
def test_taxon_creation( source )
|
243
|
+
|
244
|
+
@product_loader.perform_load( spree_fix(source), :mandatory => ['sku', 'name', 'price'] )
|
245
|
+
|
246
|
+
expected_multi_column_taxons
|
247
|
+
end
|
248
|
+
|
249
|
+
def expected_multi_column_taxons
|
250
|
+
|
251
|
+
Taxonomy.count.should == 4
|
252
|
+
Taxon.count.should == 5
|
253
|
+
|
254
|
+
Product.first.taxons.should have_exactly(2).items
|
255
|
+
Product.last.taxons.should have_exactly(1).items
|
256
|
+
|
257
|
+
p2 = Product.all[1]
|
258
|
+
|
259
|
+
p2.taxons.should have_exactly(3).items
|
260
|
+
|
261
|
+
t = Taxon.find_by_name('Oils')
|
262
|
+
|
263
|
+
t.should_not be_nil
|
264
|
+
|
265
|
+
p2.taxons.collect( &:id ).should include(t.id)
|
266
|
+
|
267
|
+
end
|
268
|
+
|
269
|
+
it "should load Products with associated image", :img => true do
|
270
|
+
|
271
|
+
@product_loader.perform_load( spree_fix('SpreeProductsWithImages.csv'), :mandatory => ['sku', 'name', 'price'] )
|
272
|
+
|
273
|
+
p = Product.find_by_name("Demo Product for AR Loader")
|
274
|
+
|
275
|
+
p.images.should have_exactly(1).items
|
276
|
+
end
|
277
|
+
|
278
|
+
|
279
|
+
# REPEAT THE WHOLE TEST SUITE VIA CSV
|
280
|
+
|
281
|
+
it "should load Products from single column csv as per .xls" do
|
282
|
+
test_variants_creation('SpreeProducts.csv')
|
283
|
+
|
284
|
+
expected_multi_column_properties
|
285
|
+
|
286
|
+
expected_multi_column_taxons
|
287
|
+
end
|
288
|
+
|
289
|
+
|
290
|
+
it "should load Products from multiple column csv as per .xls" do
|
291
|
+
test_variants_creation('SpreeProductsMultiColumn.csv')
|
292
|
+
|
293
|
+
expected_multi_column_properties
|
294
|
+
|
295
|
+
expected_multi_column_taxons
|
296
|
+
end
|
297
|
+
|
298
|
+
it "should load Products with assoicated image" do
|
299
|
+
test_variants_creation('SpreeProductsMultiColumn.csv')
|
300
|
+
|
301
|
+
expected_multi_column_properties
|
302
|
+
|
303
|
+
expected_multi_column_taxons
|
304
|
+
end
|
305
|
+
|
306
|
+
|
307
|
+
it "should raise exception when mandatory columns missing from .xls", :ex => true do
|
308
|
+
expect {@product_loader.perform_load($SpreeNegativeFixturePath + '/SpreeProdMissManyMandatory.xls', :mandatory => ['sku', 'name', 'price'] )}.to raise_error(DataShift::MissingMandatoryError)
|
309
|
+
end
|
310
|
+
|
311
|
+
|
312
|
+
it "should raise exception when single mandatory column missing from .xls", :ex => true do
|
313
|
+
expect {@product_loader.perform_load($SpreeNegativeFixturePath + '/SpreeProdMiss1Mandatory.xls', :mandatory => 'sku' )}.to raise_error(DataShift::MissingMandatoryError)
|
314
|
+
end
|
315
|
+
|
316
|
+
it "should raise exception when mandatory columns missing from .csv", :ex => true do
|
317
|
+
expect {@product_loader.perform_load($SpreeNegativeFixturePath + '/SpreeProdMissManyMandatory.csv', :mandatory => ['sku', 'name', 'price'] )}.to raise_error(DataShift::MissingMandatoryError)
|
318
|
+
end
|
319
|
+
|
320
|
+
|
321
|
+
it "should raise exception when single mandatory column missing from .csv", :ex => true do
|
322
|
+
expect {@product_loader.perform_load($SpreeNegativeFixturePath + '/SpreeProdMiss1Mandatory.csv', :mandatory => 'sku' )}.to raise_error(DataShift::MissingMandatoryError)
|
323
|
+
end
|
324
|
+
|
328
325
|
end
|