datashift 0.4.3 → 0.5.0

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/VERSION CHANGED
@@ -1 +1 @@
1
- 0.4.3
1
+ 0.5.0
data/datashift.gemspec CHANGED
@@ -5,11 +5,11 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = "datashift"
8
- s.version = "0.4.3"
8
+ s.version = "0.5.0"
9
9
 
10
10
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
11
  s.authors = ["Thomas Statter"]
12
- s.date = "2012-03-31"
12
+ s.date = "2012-05-08"
13
13
  s.description = "A suite of tools to move data between ActiveRecord models,databases,applications like Excel/Open Office, files and projects including Spree"
14
14
  s.email = "rubygems@autotelik.co.uk"
15
15
  s.extra_rdoc_files = [
@@ -24,6 +24,7 @@ Gem::Specification.new do |s|
24
24
  "README.rdoc",
25
25
  "Rakefile",
26
26
  "VERSION",
27
+ "datashift-0.5.0.gem",
27
28
  "datashift.gemspec",
28
29
  "lib/applications/jruby/jexcel_file.rb",
29
30
  "lib/applications/jruby/word.rb",
@@ -68,6 +69,7 @@ Gem::Specification.new do |s|
68
69
  "lib/loaders/spreadsheet_loader.rb",
69
70
  "lib/loaders/spree/image_loader.rb",
70
71
  "lib/loaders/spree/product_loader.rb",
72
+ "lib/thor/export_excel.thor",
71
73
  "lib/thor/generate_excel.thor",
72
74
  "lib/thor/import_excel.thor",
73
75
  "lib/thor/spree/bootstrap_cleanup.thor",
@@ -92,6 +94,7 @@ Gem::Specification.new do |s|
92
94
  "sandbox/config/database.yml",
93
95
  "sandbox/config/environment.rb",
94
96
  "sandbox/config/environments/development.rb",
97
+ "spec/Gemfile",
95
98
  "spec/csv_loader_spec.rb",
96
99
  "spec/datashift_spec.rb",
97
100
  "spec/db/migrate/20110803201325_create_test_bed.rb",
@@ -113,13 +116,13 @@ Gem::Specification.new do |s|
113
116
  "spec/fixtures/images/DEMO_002_Powerstation.jpg",
114
117
  "spec/fixtures/images/DEMO_003_ror_mug.jpeg",
115
118
  "spec/fixtures/images/DEMO_004_ror_ringer.jpeg",
116
- "spec/fixtures/interact_models_db.sqlite",
117
119
  "spec/fixtures/negative/SpreeProdMiss1Mandatory.csv",
118
120
  "spec/fixtures/negative/SpreeProdMiss1Mandatory.xls",
119
121
  "spec/fixtures/negative/SpreeProdMissManyMandatory.csv",
120
122
  "spec/fixtures/negative/SpreeProdMissManyMandatory.xls",
121
123
  "spec/fixtures/simple_export_spec.xls",
122
124
  "spec/fixtures/simple_template_spec.xls",
125
+ "spec/fixtures/spree/SpreeProductImages.xls",
123
126
  "spec/fixtures/spree/SpreeProducts.csv",
124
127
  "spec/fixtures/spree/SpreeProducts.xls",
125
128
  "spec/fixtures/spree/SpreeProductsDefaults.yml",
@@ -142,6 +145,7 @@ Gem::Specification.new do |s|
142
145
  "spec/spree_images_loader_spec.rb",
143
146
  "spec/spree_loader_spec.rb",
144
147
  "spec/spree_method_mapping_spec.rb",
148
+ "spec/thor_spec.rb",
145
149
  "tasks/config/seed_fu_product_template.erb",
146
150
  "tasks/config/tidy_config.txt",
147
151
  "tasks/export/excel_generator.rake",
@@ -123,7 +123,7 @@ if(DataShift::Guards::jruby?)
123
123
  # Process each row. (type is org.apache.poi.hssf.usermodel.HSSFRow)
124
124
 
125
125
  def each_row
126
- @sheet.rowIterator.each { |row| yield row }
126
+ @sheet.rowIterator.each { |row| @row = row; yield row }
127
127
  end
128
128
 
129
129
  # Create new row, bring index in line with POI usage (our 1 is their 0)
@@ -150,7 +150,9 @@ if(DataShift::Guards::jruby?)
150
150
  create_row(1)
151
151
  return if headers.empty?
152
152
 
153
- set_row(1, 1, headers)
153
+ headers.each_with_index do |datum, i|
154
+ @row.createCell(i, excel_cell_type(datum)).setCellValue(datum)
155
+ end
154
156
  end
155
157
 
156
158
  # Populate a row of cells with data in an array
@@ -13,10 +13,11 @@ module DataShift
13
13
  # Stores MethodDetails for a class mapped by type
14
14
  class MethodDetailsManager
15
15
 
16
- attr_reader :method_details
16
+ attr_reader :method_details, :method_details_list
17
+ attr_reader :managed_class_name
17
18
 
18
19
  def initialize( klass )
19
- @parent_class = klass
20
+ @managed_class_name = klass.name
20
21
  @method_details = {}
21
22
  @method_details_list = {}
22
23
  end
@@ -49,6 +50,10 @@ module DataShift
49
50
  @method_details_list[type.to_sym]
50
51
  end
51
52
 
53
+ def all_available_operators
54
+ method_details_list.values.flatten.collect(&:operator)
55
+ end
56
+
52
57
  end
53
58
 
54
59
  end
@@ -114,13 +114,13 @@ module DataShift
114
114
  # If not nil, returned method can be used directly in for example klass.new.send( call, .... )
115
115
  #
116
116
  def self.find_method_detail( klass, external_name )
117
- operator = nil
118
117
 
119
- # TODO - should we raise error to warn find_operators never called ?
120
118
  md_mgr = method_details_mgrs[klass] || MethodDetailsManager.new( klass )
121
119
 
120
+ # md_mgr.all_available_operators.each { |l| puts "DEBUG: Mapped Method : #{l.inspect}" }
121
+
122
122
  name = external_name.to_s
123
-
123
+
124
124
  # TODO - check out regexp to do this work better plus Inflections ??
125
125
  # Want to be able to handle any of ["Count On hand", 'count_on_hand', "Count OnHand", "COUNT ONHand" etc]
126
126
  [
@@ -61,6 +61,7 @@ module DataShift
61
61
  end
62
62
 
63
63
  x, lookup = name.split(MethodMapper::column_delim)
64
+ #puts "DEBUG: Find Method Detail for #{x}"
64
65
  md = MethodDictionary::find_method_detail( klass, x )
65
66
 
66
67
  # TODO be nice if we could cheeck that the assoc on klass responds to the specified
@@ -67,39 +67,39 @@ module DataShift
67
67
  puts "work_list : [#{work_list.inspect}]"
68
68
 
69
69
  details_mgr = MethodDictionary.method_details_mgrs[klass]
70
-
70
+
71
+
72
+ data = []
73
+ # For each type belongs has_one, has_many etc find the operators
74
+ # and create headers, then for each record call those operators
71
75
  work_list.each do |op_type|
76
+
72
77
  list_for_class_and_op = details_mgr.get_list(op_type)
73
78
 
74
79
  next if(list_for_class_and_op.nil? || list_for_class_and_op.empty?)
75
- #if(work_list.include?(md.operator_type))
76
- #each do |mdtype|
77
- #end
78
- #if(MethodDictionary.respond_to?("#{mdtype}_for") )
79
- # method_details = MethodDictionary.send("#{mdtype}_for", klass)
80
+
81
+ # method_details = MethodDictionary.send("#{mdtype}_for", klass)
80
82
 
81
- list_for_class_and_op.each {|md| headers << "#{md.operator}" }
82
- #else
83
- # puts "ERROR : Unknown option in :with [#{mdtype}]"
83
+ list_for_class_and_op.each do |md|
84
+ headers << "#{md.operator}"
85
+ items.each do |i|
86
+ data << i.send( md.operator )
87
+ end
84
88
 
85
- end
89
+ end
86
90
 
87
- excel.set_headers( headers )
88
-
89
- data = []
91
+ excel.set_headers( headers )
90
92
 
91
- items.each do |record|
92
-
93
- MethodMapper.method_details[klass].each do |method_detail|
94
- if(method_detail.operator_type == :assignment)
95
- data << record.send( method_detail.operator )
96
- end
93
+
94
+ row_index = 1
95
+
96
+ items.each do |datum|
97
+ excel.create_row(row_index += 1)
98
+ excel.ar_to_xls_row(1, datum)
97
99
  end
100
+
101
+ excel.save( filename() )
98
102
  end
99
-
100
- excel.set_row(2,1,items)
101
-
102
- excel.save( filename() )
103
103
  end
104
104
  end # ExcelGenerator
105
105
 
@@ -3,22 +3,19 @@
3
3
  # Date :: Aug 2011
4
4
  # License:: MIT
5
5
  #
6
- # Details:: Spree Helper mixing in Support for testing or loading Rails Spree e-commerce.
6
+ # Details:: Spree Helper for Product Loading.
7
7
  #
8
- # The Spree version you want to test should be picked up from the Gemfile
8
+ # Utils to try to manage different Spree versions seamlessly.
9
+ #
10
+ # Spree Helper for RSpec testing, enables mixing in Support for
11
+ # testing or loading Rails Spree e-commerce.
12
+ #
13
+ # The Spree version you want to test should be picked up from spec/Gemfile
9
14
  #
10
15
  # Since datashift gem is not a Rails app or a Spree App, provides utilities to internally
11
16
  # create a Spree Database, and to load Spree components, enabling standalone testing.
12
17
  #
13
- # => Has been tested with 0.7
14
- #
15
- # # => TODO - Can we move to a Gemfile/bunlder
16
- # require 'rubygems'
17
- # gemfile = File.expand_path("<%= gemfile_path %>", __FILE__)
18
- #
19
- # ENV['BUNDLE_GEMFILE'] = gemfile
20
- # require 'bundler'
21
- # Bundler.setup
18
+ # => Has been tested with 0.11.2, 0.7, 1.0.0
22
19
  #
23
20
  # => TODO - See if we can improve DB creation/migration ....
24
21
  # N.B Some or all of Spree Tests may fail very first time run,
@@ -52,8 +49,12 @@ module DataShift
52
49
  end
53
50
  end
54
51
 
52
+ def self.version
53
+ Gem.loaded_specs['spree'] ? Gem.loaded_specs['spree'].version.version : "0.0.0"
54
+ end
55
+
55
56
  def self.is_namespace_version
56
- Gem.loaded_specs['spree'].version.version.to_f >= 1
57
+ SpreeHelper::version.to_f >= 1
57
58
  end
58
59
 
59
60
  def self.lib_root
@@ -79,7 +80,9 @@ module DataShift
79
80
  # => Will chdir into the sandbox to load environment as need to mimic being at root of a rails project
80
81
  # chdir back after environment loaded
81
82
 
82
- def self.boot( database_env )
83
+ # gem('rails', '3.2.3')
84
+
85
+ def self.boot( database_env)#, rails_version = '3.1.3' )
83
86
 
84
87
  if( ! is_namespace_version )
85
88
  db_connect( database_env )
@@ -88,14 +91,12 @@ module DataShift
88
91
  @dslog.info "Booted Spree using pre 1.0.0 version"
89
92
  else
90
93
 
91
- # TODO as Spree versions moves how do we best track reqd Rails version
92
- # parse the gemspec of the core Gemfile ?
93
-
94
- gem('rails', '3.1.3')
94
+
95
+ #em('rails', rails_version)
95
96
 
96
- db_connect( database_env, '3.1.3' )
97
+ db_connect( database_env )#, rails_version )
97
98
 
98
- @dslog.info "Booting Spree using post 1.0.0 version"
99
+ @dslog.info "Booting Spree using version #{SpreeHelper::version}"
99
100
 
100
101
  require 'rails/all'
101
102
 
@@ -111,7 +112,7 @@ module DataShift
111
112
 
112
113
  Dir.chdir( store_path )
113
114
 
114
- @dslog.info "Booted Spree using post 1.0.0 version"
115
+ @dslog.info "Booted Spree using version #{SpreeHelper::version}"
115
116
  end
116
117
  end
117
118
 
@@ -16,6 +16,9 @@ module DataShift
16
16
 
17
17
  include DataShift::Logging
18
18
 
19
+ # Options :
20
+ # strict : Raise exception if any column cannot be mapped
21
+
19
22
  def perform_csv_load(file_name, options = {})
20
23
 
21
24
  require "csv"
@@ -32,7 +35,7 @@ module DataShift
32
35
  map_headers_to_operators( @parsed_file.shift, options[:strict] , @mandatory )
33
36
 
34
37
  unless(@method_mapper.missing_methods.empty?)
35
- puts "WARNING: Following column headings could not be mapped : #{@method_mapper.missing_methods.inspect}"
38
+ logger.error("Following column headings could not be mapped :\n#{@method_mapper.missing_methods.inspect}")
36
39
  raise MappingDefinitionError, "ERROR: Missing mappings for #{@method_mapper.missing_methods.size} column headings"
37
40
  end
38
41
 
@@ -113,10 +113,29 @@ module DataShift
113
113
  reset(object)
114
114
  end
115
115
 
116
+
117
+ # Based on filename call appropriate loading function
118
+ # Currently supports :
119
+ # Excel/Open Office files saved as .xls
120
+ # CSV files
121
+ #
122
+ # OPTIONS :
123
+ # strict : Raise exception if any column cannot be mapped
124
+
125
+ def perform_load( file_name, options = {} )
116
126
 
117
- # kinda the derived classes interface - best way in Ruby ?
118
- def perform_load( input, options = {} )
119
- raise "WARNING- ABSTRACT METHOD CALLED - Please implement perform_load()"
127
+ raise DataShift::BadFile, "Cannot load #{file_name} file not found." unless(File.exists?(file_name))
128
+
129
+ ext = File.extname(file_name)
130
+
131
+ if(ext.casecmp('.xls') == 0)
132
+ raise DataShift::BadRuby, "Please install and use JRuby for loading .xls files" unless(Guards::jruby?)
133
+ perform_excel_load(file_name, options)
134
+ elsif(ext.casecmp('.csv') == 0)
135
+ perform_csv_load(file_name, options)
136
+ else
137
+ raise DataShift::UnsupportedFileType, "#{ext} files not supported - Try .csv or OpenOffice/Excel .xls"
138
+ end
120
139
  end
121
140
 
122
141
 
@@ -126,7 +145,7 @@ module DataShift
126
145
  # This is then available through @method_mapper.method_details.each
127
146
  #
128
147
  # Options:
129
- # strict : report any header values that can't be mapped as an error
148
+ # strict : Raise an exception of any headers can't be mapped to an attribute/association
130
149
  #
131
150
  def map_headers_to_operators( headers, strict, mandatory = [])
132
151
  @headers = headers
@@ -134,6 +153,7 @@ module DataShift
134
153
  begin
135
154
  method_details = @method_mapper.map_inbound_to_methods( load_object_class, @headers )
136
155
  rescue => e
156
+ puts e.inspect
137
157
  logger.error("Failed to map header row to set of database operators : #{e.inspect}")
138
158
  raise MappingDefinitionError, "Failed to map header row to set of database operators"
139
159
  end
@@ -51,7 +51,9 @@ module DataShift
51
51
  class ImageLoader < LoaderBase
52
52
 
53
53
  include DataShift::ImageLoading
54
-
54
+ include DataShift::CsvLoading
55
+ include DataShift::ExcelLoading
56
+
55
57
  def initialize(image = nil)
56
58
  puts SpreeHelper::get_spree_class('Image')
57
59
 
@@ -43,16 +43,20 @@ module DataShift
43
43
  # Currently supports :
44
44
  # Excel/Open Office files saved as .xls
45
45
  # CSV files
46
+ #
47
+ # OPTIONS :
48
+ # strict : Raise exception if any column cannot be mapped
49
+
46
50
  def perform_load( file_name, options = {} )
47
51
 
48
52
  raise DataShift::BadFile, "Cannot load #{file_name} file not found." unless(File.exists?(file_name))
49
53
 
50
54
  ext = File.extname(file_name)
51
55
 
52
- if(ext == '.xls')
56
+ if(ext.casecmp('.xls') == 0)
53
57
  raise DataShift::BadRuby, "Please install and use JRuby for loading .xls files" unless(Guards::jruby?)
54
58
  perform_excel_load(file_name, options)
55
- elsif(ext == '.csv')
59
+ elsif(ext.casecmp('.csv') == 0)
56
60
  perform_csv_load(file_name, options)
57
61
  else
58
62
  raise DataShift::UnsupportedFileType, "#{ext} files not supported - Try .csv or OpenOffice/Excel .xls"
@@ -182,16 +186,35 @@ module DataShift
182
186
  ovname.strip!
183
187
  ov = @@option_value_klass.find_or_create_by_name_and_option_type_id(ovname, option_type.id)
184
188
  if ov
185
- variant = @@variant_klass.create( :product => @load_object, :sku => "#{@load_object.sku}_#{i}", :price => @load_object.price, :available_on => @load_object.available_on)
186
- #puts "DEBUG: Created New Variant: #{variant.inspect}"
187
- variant.option_values << ov
189
+ begin
190
+ # This one line seems to works for 1.1.0 - 3.2 but not 1.0.0 - 3.1 ??
191
+ if(SpreeHelper::version.to_f >= 1.1)
192
+ variant = @load_object.variants.create( :sku => "#{@load_object.sku}_#{i}", :price => @load_object.price, :available_on => @load_object.available_on)
193
+ else
194
+ variant = @@variant_klass.create( :product => @load_object, :sku => "#{@load_object.sku}_#{i}", :price => @load_object.price, :available_on => @load_object.available_on)
195
+ #if(variant.valid?)
196
+ # variant.save
197
+ # @load_object.variants << variant
198
+
199
+ #else
200
+ #puts "WARNING: For Option #{ovname} - Variant creation failed #{variant.errors.inspect}"
201
+ end
202
+ variant.option_values << ov
203
+ rescue => e
204
+ puts "Failed to create a Variant for Product #{@load_object.name}"
205
+ puts e.inspect
206
+ puts e.backtrace
207
+ end
208
+
209
+ logger.debug "Created New Variant: #{variant.inspect}"
210
+
188
211
  else
189
212
  puts "WARNING: Option #{ovname} NOT FOUND - No Variant created"
190
213
  end
191
214
  end
192
215
 
193
216
  #puts "DEBUG Load Object now has Variants : #{@load_object.variants.inspect}"
194
- @load_object.reload
217
+ @load_object.reload unless @load_object.new_record?
195
218
  #puts "DEBUG Load Object now has Variants : #{@load_object.variants.inspect}"
196
219
  end
197
220
 
@@ -212,6 +235,7 @@ module DataShift
212
235
  img_path, alt_text = image.split(LoaderBase::name_value_delim)
213
236
 
214
237
  image = create_image(@@image_klass, img_path, @load_object, :alt => alt_text)
238
+ logger.debug("Product assigned an Image : #{image.inspect}")
215
239
  end
216
240
 
217
241
  end
@@ -233,10 +257,20 @@ module DataShift
233
257
 
234
258
  unless property
235
259
  property = @@property_klass.create( :name => pname, :presentation => pname.humanize)
260
+ logger.debug "Created New Property #{property.inspect}"
236
261
  end
237
262
 
238
263
  if(property)
239
- @load_object.product_properties << @@product_property_klass.create( :property => property, :value => pvalue)
264
+ if(SpreeHelper::version.to_f >= 1.1)
265
+ # Property now protected from mass assignment
266
+ x = @@product_property_klass.new( :value => pvalue )
267
+ x.property = property
268
+ x.save
269
+ logger.debug "Created New ProductProperty #{x.inspect}"
270
+ @load_object.product_properties << x
271
+ else
272
+ @load_object.product_properties << @@product_property_klass.create( :property => property, :value => pvalue)
273
+ end
240
274
  else
241
275
  puts "WARNING: Property #{pname} NOT found - Not set Product"
242
276
  end
@@ -246,20 +280,6 @@ module DataShift
246
280
  end
247
281
 
248
282
  # Nested tree structure support ..
249
- #
250
- # ... inside of main loop
251
- # the_taxons = []
252
- # taxon_col.split(/[\r\n]+/).each do |chain|
253
- # taxon = nil
254
- # names = chain.split(/\s*>\s*/)
255
- # names.each do |name|
256
- # taxon = Taxon.find_or_create_by_name_and_parent_id_and_taxonomy_id(name, taxon && taxon.id, main_taxonomy.id)
257
- # end
258
- # the_taxons << taxon
259
- # end
260
- # p.taxons = the_taxons
261
-
262
-
263
283
  # TAXON FORMAT
264
284
  # name|name>child>child|name
265
285
 
@@ -302,7 +322,7 @@ module DataShift
302
322
 
303
323
  unique_list = taxons.compact.uniq - (@load_object.taxons || [])
304
324
 
305
- #puts "DEBUG: Taxon nms to add #{unique_list.collect(&:name).inspect}"
325
+ logger.debug("Product assigned to Taxons : #{unique_list.collect(&:name).inspect}")
306
326
  @load_object.taxons << unique_list unless(unique_list.empty?)
307
327
  end
308
328
 
@@ -0,0 +1,74 @@
1
+ # Copyright:: (c) Autotelik Media Ltd 2012
2
+ # Author :: Tom Statter
3
+ # Date :: April 2012
4
+ # License:: MIT.
5
+ #
6
+ # Usage::
7
+ #
8
+ # To pull Datashift commands into your main application :
9
+ #
10
+ # require 'datashift'
11
+ #
12
+ # DataShift::load_commands
13
+ #
14
+ # Cmd Line:
15
+ #
16
+ # => bundle exec thor datashift:export:excel -m <active record class> -r <output_template.xls> -a
17
+ #
18
+ require 'datashift'
19
+
20
+ # Note, not DataShift, case sensitive, create namespace for command line : datashift
21
+ module Datashift
22
+
23
+
24
+ class Export < Thor
25
+
26
+ include DataShift::Logging
27
+
28
+ desc "excel", "export any active record model (with optional associations)"
29
+ method_option :model, :aliases => '-m', :required => true, :desc => "The active record model to export"
30
+ method_option :result, :aliases => '-r', :required => true, :desc => "Create template of model in supplied file"
31
+ method_option :assoc, :aliases => '-a', :type => :boolean, :desc => "Include all associations in the template"
32
+ method_option :exclude, :aliases => '-e', :type => :array, :desc => "Use with -a : Exclude association types. Any from #{DataShift::MethodDetail::supported_types_enum.to_a.inspect}"
33
+
34
+ def excel()
35
+
36
+ # TODO - We're assuming run from a rails app/top level dir...
37
+ # ...can we make this more robust ? e.g what about when using active record but not in Rails app,
38
+ require File.expand_path('config/environment.rb')
39
+
40
+ require 'excel_exporter'
41
+
42
+ model = options[:model]
43
+ result = options[:result]
44
+
45
+ logger.info "Datashift: Start Excel export to #{result}"
46
+
47
+ begin
48
+ # support modules e.g "Spree::Property")
49
+ klass = ModelMapper::class_from_string(model) #Kernel.const_get(model)
50
+ rescue NameError => e
51
+ puts e
52
+ raise "ERROR: No such Model [#{model}] found - check valid model supplied via -model <Class>"
53
+ end
54
+
55
+ begin
56
+ gen = DataShift::ExcelExporter.new(result)
57
+
58
+ if(options[:assoc])
59
+ opts = (options[:exclude]) ? {:exclude => options[:exclude]} : {}
60
+ logger.info("Datashift: Exporting with associations")
61
+ gen.generate_with_associations(klass, opts)
62
+ else
63
+ gen.generate(klass)
64
+ end
65
+ rescue => e
66
+ puts e
67
+ puts e.backtrace
68
+ puts "Warning: Error during export, data may be incomplete"
69
+ end
70
+
71
+ end
72
+ end
73
+
74
+ end
@@ -12,6 +12,7 @@
12
12
 
13
13
  # Note, not DataShift, case sensitive, create namespace for command line : datashift
14
14
  module Datashift
15
+
15
16
 
16
17
  class Spree < Thor
17
18
 
@@ -24,7 +25,7 @@ module Datashift
24
25
  method_option :verbose, :aliases => '-v', :type => :boolean, :desc => "Verbose logging"
25
26
  method_option :config, :aliases => '-c', :type => :string, :desc => "Configuration file containg defaults or over rides in YAML"
26
27
 
27
- def products() #, [:input, :verbose, :sku_prefix] => :environment do |t, args|
28
+ def products()
28
29
 
29
30
  # TODO - We're assuming run from a rails app/top level dir...
30
31
  # ...can we make this more robust ? e.g what about when using active record but not in Rails app,
data/spec/Gemfile ADDED
@@ -0,0 +1,18 @@
1
+ source 'https://rubygems.org'
2
+
3
+ gem 'rspec' # Behavior Driven Development (BDD) for Ruby
4
+ gem 'rspec-core' # RSpec runner and example groups.
5
+ gem 'rspec-expectations' # RSpec matchers for should and should_not.
6
+ gem 'rspec-mocks' # RSpec test double framework with stubbing and mocking.
7
+ gem 'rspec-rails' # RSpec version 2.x for Rails version 3.x.
8
+ gem 'activerecord-jdbcsqlite3-adapter'
9
+
10
+ # DEFINE WHICH VERSIONS WE WANT TO TEST WITH
11
+
12
+ #gem 'rails', '3.2.3'
13
+ #gem 'spree', '1.1.0'
14
+
15
+ gem 'rails', '3.1.3'
16
+ gem 'spree', '1.0.0'
17
+
18
+
@@ -9,7 +9,7 @@ require File.dirname(__FILE__) + '/spec_helper'
9
9
 
10
10
  if(Guards::jruby?)
11
11
  require 'erb'
12
- require 'excel_generator'
12
+ require 'excel_exporter'
13
13
 
14
14
  include DataShift
15
15
 
@@ -37,37 +37,36 @@ if(Guards::jruby?)
37
37
  MethodDictionary.find_operators( @assoc_klazz )
38
38
  end
39
39
 
40
- it "should be able to create a new excel generator" do
40
+ it "should be able to create a new excel exporter" do
41
41
  generator = ExcelExporter.new( 'dummy.xls' )
42
42
 
43
43
  generator.should_not be_nil
44
44
  end
45
45
 
46
- it "should generate template .xls file from model" do
46
+ it "should export a model to .xls file" do
47
47
 
48
- expect = result_file('project_template_spec.xls')
48
+ expect = result_file('project_export_spec.xls')
49
49
 
50
50
  gen = ExcelExporter.new( expect )
51
51
 
52
- gen.generate(Project)
52
+ gen.export(Project)
53
53
 
54
54
  File.exists?(expect).should be_true
55
55
 
56
56
  puts "Can manually check file @ #{expect}"
57
57
  end
58
58
 
59
- it "should export a simple model to .xls spreedsheet" do
59
+ it "should export a model and associations to .xls file" do
60
60
 
61
61
  Project.create( :value_as_string => 'Value as Text', :value_as_boolean => true, :value_as_double => 75.672)
62
- #001 Demo string blah blah 2011-02-14 1.00 320.00
63
62
 
64
- expect= result_file('simple_export_spec.xls')
63
+ expect= result_file('project_plus_assoc_export_spec.xls')
65
64
 
66
- gen = ExcelGenerator.new(expect)
65
+ gen = ExcelExporter.new(expect)
67
66
 
68
67
  items = Project.all
69
68
 
70
- gen.export(items)
69
+ gen.export_with_associations(Project, items)
71
70
 
72
71
  File.exists?(expect).should be_true
73
72
 
@@ -56,18 +56,13 @@ if(Guards::jruby?)
56
56
  puts "Can manually check file @ #{expect}"
57
57
  end
58
58
 
59
- it "should export a simple model to .xls spreedsheet" do
59
+ it "should genrate a complex template .xls file from model" do
60
60
 
61
- Project.create( :value_as_string => 'Value as Text', :value_as_boolean => true, :value_as_double => 75.672)
62
- #001 Demo string blah blah 2011-02-14 1.00 320.00
63
-
64
- expect= result_file('simple_export_spec.xls')
61
+ expect= result_file('project_plus_assoc_template_spec.xls')
65
62
 
66
63
  gen = ExcelGenerator.new(expect)
67
64
 
68
- items = Project.all
69
-
70
- gen.export(items)
65
+ gen.generate_with_associations(Project)
71
66
 
72
67
  File.exists?(expect).should be_true
73
68
 
data/spec/spec_helper.rb CHANGED
@@ -1,5 +1,5 @@
1
- require 'erb'
2
- require 'yaml'
1
+
2
+ require 'stringio'
3
3
 
4
4
  require File.dirname(__FILE__) + '/../lib/datashift'
5
5
 
@@ -14,17 +14,21 @@ include DataShift
14
14
  #
15
15
  #
16
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.
17
+ # we have some AR models to test against. Create an in memory database from scratch.
18
18
  #
19
19
  $DataShiftFixturePath = File.join(File.dirname(__FILE__), 'fixtures')
20
20
  $DataShiftDatabaseYml = File.join($DataShiftFixturePath, 'config/database.yml')
21
21
 
22
22
  module DataShift
23
23
 
24
- def db_connect( env = 'test_file', version = nil)
24
+ def db_connect( env = 'test_file')
25
+
26
+ gemfile = File.join(DataShift::root_path, 'spec', 'Gemfile')
27
+
28
+ ENV['BUNDLE_GEMFILE'] = gemfile
29
+ require 'bundler'
30
+ Bundler.setup
25
31
 
26
- version ? gem('activerecord', version) : gem('activerecord')
27
-
28
32
  require 'active_record'
29
33
 
30
34
  # Some active record stuff seems to rely on the RAILS_ENV being set ?
@@ -41,13 +45,13 @@ module DataShift
41
45
 
42
46
  #dbtype = Rails.configuration.database_configuration[Rails.env]['adapter'].to_sym
43
47
 
44
- #ActiveRecord::Base.logger = Logger.new(STDOUT)
45
-
46
48
  require 'logger'
47
49
  logdir = File.dirname(__FILE__) + '/logs'
48
50
  FileUtils.mkdir_p(logdir) unless File.exists?(logdir)
49
51
  ActiveRecord::Base.logger = Logger.new(logdir + '/datashift_spec.log')
50
52
 
53
+ # Anyway to direct one logger to another ????? ... Logger.new(STDOUT)
54
+
51
55
  @dslog = ActiveRecord::Base.logger
52
56
 
53
57
  puts "Connecting to DB"
@@ -57,6 +61,8 @@ module DataShift
57
61
  # so copied this from ... Rails::Initializer.initialize_cache
58
62
  Object.const_set "RAILS_CACHE", ActiveSupport::Cache.lookup_store( :memory_store )
59
63
 
64
+ puts "Connected to DB"
65
+
60
66
  @dslog.info "Connected to DB - #{ActiveRecord::Base.connection.inspect}"
61
67
  end
62
68
 
@@ -100,6 +106,8 @@ end
100
106
 
101
107
  module SpecHelper
102
108
 
109
+ # VERSIONS of Spree (1.1.0.rc1, 1.0.0, 0.11.2)
110
+
103
111
  $SpreeFixturePath = File.join($DataShiftFixturePath, 'spree')
104
112
  $SpreeNegativeFixturePath = File.join($DataShiftFixturePath, 'negative')
105
113
 
@@ -108,11 +116,14 @@ module SpecHelper
108
116
  end
109
117
 
110
118
  def self.before_all_spree
119
+
111
120
  # we are not a Spree project, nor is it practical to externally generate
112
121
  # a complete Spree application for testing so we implement a mini migrate/boot of our own
113
- SpreeHelper.load() # require Spree gems
114
- SpreeHelper.boot( 'test_spree_standalone' ) # key to YAML db e.g test_memory, test_mysql
122
+ SpreeHelper.load()
123
+ SpreeHelper.boot('test_spree_standalone') # key to YAML db e.g test_memory, test_mysql
115
124
 
125
+ puts "Testing Spree standalone - version #{SpreeHelper::version}"
126
+
116
127
  SpreeHelper.migrate_up # create an sqlite Spree database on the fly
117
128
  end
118
129
 
@@ -136,6 +147,19 @@ module SpecHelper
136
147
 
137
148
  end
138
149
 
150
+ def capture(stream)
151
+ begin
152
+ stream = stream.to_s
153
+ eval "$#{stream} = StringIO.new"
154
+ yield
155
+ result = eval("$#{stream}").string
156
+ ensure
157
+ eval("$#{stream} = #{stream.upcase}")
158
+ end
159
+
160
+ result
161
+ end
162
+
139
163
  RSpec.configure do |config|
140
164
  # config.use_transactional_fixtures = true
141
165
  # config.use_instantiated_fixtures = false
@@ -12,7 +12,7 @@
12
12
  require File.dirname(__FILE__) + '/spec_helper'
13
13
 
14
14
  require 'spree_helper'
15
- require 'excel_generator'
15
+ require 'excel_exporter'
16
16
 
17
17
  include DataShift
18
18
 
@@ -20,6 +20,7 @@ describe 'SpreeLoader' do
20
20
 
21
21
  before(:all) do
22
22
  SpecHelper::before_all_spree
23
+ results_clear()
23
24
  end
24
25
 
25
26
  before do
@@ -29,36 +30,38 @@ describe 'SpreeLoader' do
29
30
 
30
31
  before_each_spree # inits tests, cleans DB setups model types
31
32
 
33
+ @Taxon_klass.delete_all
34
+
32
35
  # Create some test data
33
36
  root = @Taxonomy_klass.create( :name => 'Paintings' )
34
37
 
35
- @Taxon_klass.create( :name => 'Landscape', :taxonomy => root )
36
- @Taxon_klass.create( :name => 'Sea', :taxonomy => root )
38
+ @Taxon_klass.create( :name => 'Landscape', :description => "Nice paintings", :taxonomy_id => root.id )
39
+ @Taxon_klass.create( :name => 'Sea', :description => "Waves and sand", :taxonomy_id => root.id )
37
40
 
38
41
  end
39
42
 
40
43
  it "should export any Spree model to .xls spreedsheet" do
41
44
 
42
- expect = result_file('taxonomy_export_spec.xls')
45
+ expect = result_file('taxon_export_spec.xls')
43
46
 
44
- gen = ExcelGenerator.new(expect)
47
+ exporter = ExcelExporter.new(expect)
45
48
 
46
- items = @Taxonomy_klass.all
49
+ items = @Taxon_klass.all
47
50
 
48
- gen.export(items)
51
+ exporter.export(items)
49
52
 
50
53
  File.exists?(expect).should be_true
51
54
  end
52
55
 
53
56
  it "should export a Spree model and associations to .xls spreedsheet" do
54
57
 
55
- expect = result_file('taxonomy_and_assoc_export_spec.xls')
58
+ expect = result_file('taxon_and_assoc_export_spec.xls')
56
59
 
57
- gen = ExcelGenerator.new(expect)
60
+ exporter = ExcelExporter.new(expect)
58
61
 
59
- items = @Taxonomy_klass.all
62
+ items = @Taxon_klass.all
60
63
 
61
- gen.generate_with_associations(@Taxonomy_klass, items)
64
+ exporter.export_with_associations(@Taxon_klass, items)
62
65
 
63
66
  File.exists?(expect).should be_true
64
67
 
@@ -24,7 +24,7 @@ describe 'SpreeLoader' do
24
24
 
25
25
  before do
26
26
 
27
- include SpecHelper
27
+ #include SpecHelper
28
28
  extend SpecHelper
29
29
 
30
30
  before_each_spree # inits tests, cleans DB setups model types
@@ -45,29 +45,45 @@ describe 'SpreeLoader' do
45
45
  end
46
46
 
47
47
 
48
- it "should load Products with associated image" do
48
+ it "should load Products with associated image from CSV" do
49
+
50
+ # In >= 1.1.0 Image moved to master Variant from Product
51
+ if(SpreeHelper::version.to_f < 1.1)
49
52
 
50
- @product_loader.perform_load( SpecHelper::spree_fixture('SpreeProductsWithImages.csv'), :mandatory => ['sku', 'name', 'price'] )
53
+ @product_loader.perform_load( SpecHelper::spree_fixture('SpreeProductsWithImages.csv'), :mandatory => ['sku', 'name', 'price'] )
51
54
 
52
- p = @klass.find_by_name("Demo Product for AR Loader")
55
+ p = @klass.find_by_name("Demo Product for AR Loader")
53
56
 
54
- p.name.should == "Demo Product for AR Loader"
55
- p.images.should have_exactly(1).items
57
+ p.name.should == "Demo Product for AR Loader"
58
+ p.images.should have_exactly(1).items
56
59
 
57
- @klass.all.each {|p| p.images.should have_exactly(1).items }
60
+ @klass.all.each {|p| p.images.should have_exactly(1).items }
61
+ end
58
62
  end
59
63
 
60
64
 
61
- it "should be able to assign Images to preloaded Products" do
65
+ it "should load Products with associated image", :fail => true do
66
+
67
+ if(SpreeHelper::version.to_f < 1.1)
68
+ @product_loader.perform_load( SpecHelper::spree_fixture('SpreeProductsWithImages.xls'), :mandatory => ['sku', 'name', 'price'] )
69
+
70
+ p = @klass.find_by_name("Demo Product for AR Loader")
62
71
 
63
- @product_loader.perform_load( SpecHelper::spree_fixture('SpreeProductsMultiColumn.csv'), :mandatory => ['sku', 'name', 'price'] )
64
-
65
- @Image_klass.all.size.should == 0
72
+ p.name.should == "Demo Product for AR Loader"
73
+ p.images.should have_exactly(1).items
66
74
 
67
- @klass.all.each {|p| p.images.should have_exactly(0).items }
75
+ @klass.all.each {|p| p.images.should have_exactly(1).items }
76
+ end
77
+ end
78
+
79
+ it "should be able to assign Images to preloaded Products" do
68
80
 
81
+ @Image_klass.all.size.should == 0
82
+
69
83
  loader = DataShift::SpreeHelper::ImageLoader.new
70
84
 
85
+ loader.perform_load( SpecHelper::spree_fixture('SpreeProductImages.xls') )
86
+
71
87
  end
72
88
 
73
89
  end
@@ -32,17 +32,19 @@ describe 'SpreeLoader' do
32
32
 
33
33
  before_each_spree
34
34
 
35
- @klass.count.should == 0
35
+ @Product_klass.count.should == 0
36
36
  @Taxon_klass.count.should == 0
37
37
  @Variant_klass.count.should == 0
38
38
 
39
39
  MethodDictionary.clear
40
- MethodDictionary.find_operators( @klass )
40
+ MethodDictionary.find_operators( @Product_klass )
41
41
 
42
42
  # want to test both lookup and dynamic creation - this Taxonomy should be found, rest created
43
43
  root = @Taxonomy_klass.create( :name => 'Paintings' )
44
44
 
45
- @Taxon_klass.create( :name => 'Landscape', :taxonomy => root )
45
+ t = @Taxon_klass.new( :name => 'Landscape' )
46
+ t.taxonomy = root
47
+ t.save
46
48
 
47
49
  @Taxon_klass.count.should == 2
48
50
 
@@ -99,14 +101,14 @@ describe 'SpreeLoader' do
99
101
 
100
102
  @product_loader.perform_load( SpecHelper::spree_fixture(source), :mandatory => ['sku', 'name', 'price'] )
101
103
 
102
- @klass.count.should == 3
104
+ @Product_klass.count.should == 3
103
105
 
104
106
  @product_loader.failed_objects.size.should == 0
105
107
  @product_loader.loaded_objects.size.should == 3
106
108
 
107
- @product_loader.loaded_count.should == @klass.count
109
+ @product_loader.loaded_count.should == @Product_klass.count
108
110
 
109
- p = @klass.first
111
+ p = @Product_klass.first
110
112
 
111
113
  p.sku.should == "SIMPLE_001"
112
114
  p.price.should == 345.78
@@ -116,7 +118,7 @@ describe 'SpreeLoader' do
116
118
  p.option_types.should have_exactly(1).items
117
119
  p.option_types.should have_exactly(1).items
118
120
  p.count_on_hand.should == 12
119
- @klass.last.count_on_hand.should == 23
121
+ @Product_klass.last.count_on_hand.should == 23
120
122
  end
121
123
 
122
124
 
@@ -149,16 +151,16 @@ describe 'SpreeLoader' do
149
151
  def test_default_values
150
152
  @product_loader.perform_load( SpecHelper::spree_fixture('SpreeProductsMandatoryOnly.xls'), :mandatory => ['sku', 'name', 'price'] )
151
153
 
152
- @klass.count.should == 3
154
+ @Product_klass.count.should == 3
153
155
 
154
156
  @product_loader.failed_objects.size.should == 0
155
157
  @product_loader.loaded_objects.size.should == 3
156
158
 
157
- p = @klass.first
159
+ p = @Product_klass.first
158
160
 
159
161
  p.sku.should == "SPEC_SIMPLE_001"
160
162
 
161
- @klass.all { |p|
163
+ @Product_klass.all { |p|
162
164
  p.sku.should.include "SPEC_"
163
165
  p.cost_price = 1.0
164
166
  p.available_on.should == @expected_time
@@ -180,7 +182,7 @@ describe 'SpreeLoader' do
180
182
  end
181
183
 
182
184
  def test_variants_creation( source )
183
- @klass.count.should == 0
185
+ @Product_klass.count.should == 0
184
186
  @Variant_klass.count.should == 0
185
187
 
186
188
  @product_loader.perform_load( SpecHelper::spree_fixture(source), :mandatory => ['sku', 'name', 'price'] )
@@ -192,10 +194,10 @@ describe 'SpreeLoader' do
192
194
  def expected_multi_column_variants
193
195
 
194
196
  # 3 MASTER products, 11 VARIANTS
195
- @klass.count.should == 3
197
+ @Product_klass.count.should == 3
196
198
  @Variant_klass.count.should == 14
197
199
 
198
- p = @klass.first
200
+ p = @Product_klass.first
199
201
 
200
202
  p.sku.should == "DEMO_001"
201
203
 
@@ -204,7 +206,7 @@ describe 'SpreeLoader' do
204
206
  p.description.should == "blah blah"
205
207
  p.cost_price.should == 320.00
206
208
 
207
- @klass.all.select {|m| m.is_master.should == true }
209
+ @Product_klass.all.select {|m| m.is_master.should == true }
208
210
 
209
211
 
210
212
  # mime_type:jpeg mime_type:PDF mime_type:PNG
@@ -281,12 +283,12 @@ describe 'SpreeLoader' do
281
283
 
282
284
  def expected_multi_column_properties
283
285
  # 3 MASTER products, 11 VARIANTS
284
- @klass.count.should == 3
286
+ @Product_klass.count.should == 3
285
287
  @Variant_klass.count.should == 14
286
288
 
287
- @klass.first.properties.should have_exactly(1).items
289
+ @Product_klass.first.properties.should have_exactly(1).items
288
290
 
289
- p3 = @klass.all.last
291
+ p3 = @Product_klass.all.last
290
292
 
291
293
  p3.properties.should have_exactly(3).items
292
294
 
@@ -304,7 +306,7 @@ describe 'SpreeLoader' do
304
306
  # Operation and results should be identical when loading multiple associations
305
307
  # if using either single column embedded syntax, or one column per entry.
306
308
 
307
- it "should load Products and multiple Taxons from single column", :taxon => true do
309
+ it "should load Products and multiple Taxons from single column", :taxons => true do
308
310
  test_taxon_creation( 'SpreeProducts.xls' )
309
311
  end
310
312
 
@@ -329,7 +331,7 @@ describe 'SpreeLoader' do
329
331
  #puts @Taxonomy_klass.all.collect( &:name).inspect
330
332
  #puts @Taxon_klass.all.collect( &:name).inspect
331
333
 
332
- # Paintings alreadyexisted and had 1 child Taxon (Landscape)
334
+ # Paintings already existed and had 1 child Taxon (Landscape)
333
335
  # 2 nested Taxon (Paintings>Nature>Seascape) created under it so expect Taxonomy :
334
336
 
335
337
  # WaterColour
@@ -340,13 +342,16 @@ describe 'SpreeLoader' do
340
342
  @Taxonomy_klass.count.should == 4
341
343
  @Taxon_klass.count.should == 7
342
344
 
343
- @klass.first.taxons.should have_exactly(2).items
344
- @klass.last.taxons.should have_exactly(2).items
345
+ @Product_klass.first.taxons.should have_exactly(2).items
346
+ @Product_klass.last.taxons.should have_exactly(2).items
345
347
 
346
348
  p2 = @Variant_klass.find_by_sku("DEMO_002").product
347
349
 
348
350
  # Paintings Oils Paintings>Nature>Seascape
349
351
 
352
+ # ["Nature", "Paintings", "Seascape"]
353
+
354
+
350
355
  #puts p2.taxons.collect(&:name).inspect
351
356
 
352
357
  p2.taxons.should have_exactly(4).items
@@ -354,7 +359,10 @@ describe 'SpreeLoader' do
354
359
  p2.taxons.collect(&:name).sort.should == ['Nature','Oils','Paintings','Seascape']
355
360
 
356
361
  paint_parent = @Taxonomy_klass.find_by_name('Paintings')
357
-
362
+
363
+
364
+ puts paint_parent.taxons.collect(&:name).sort.inspect
365
+
358
366
  paint_parent.taxons.should have_exactly(4).items # 3 children + all Taxonomies have a root Taxon
359
367
 
360
368
  paint_parent.taxons.collect(&:name).sort.should == ['Landscape','Nature','Paintings','Seascape']
@@ -367,16 +375,13 @@ describe 'SpreeLoader' do
367
375
 
368
376
  p2.taxons.collect( &:id ).should include(ts.id)
369
377
  p2.taxons.collect( &:id ).should include(tn.id)
370
-
371
- puts tn.inspect
372
- puts ts.inspect
378
+
373
379
 
374
380
  tn.parent.id.should == paint_parent.root.id
375
381
  ts.parent.id.should == tn.id
376
382
 
377
383
  tn.children.should have_exactly(1).items
378
384
  ts.children.should have_exactly(0).items
379
-
380
385
 
381
386
  end
382
387
 
@@ -392,7 +397,7 @@ describe 'SpreeLoader' do
392
397
  end
393
398
 
394
399
 
395
- it "should load Products from multiple column csv as per .xls" do
400
+ it "should load Products from multiple column csv as per .xls", :blah => true do
396
401
  test_variants_creation('SpreeProductsMultiColumn.csv')
397
402
 
398
403
  expected_multi_column_properties
data/spec/thor_spec.rb ADDED
@@ -0,0 +1,32 @@
1
+ # Copyright:: (c) Autotelik Media Ltd 2012
2
+ # Author :: Tom Statter
3
+ # Date :: April 20121
4
+ #
5
+ # License:: MIT - Free, OpenSource
6
+ #
7
+ # Details:: Specification for Thor tasks supplied with datashift
8
+ #
9
+ require 'thor'
10
+ require 'thor/group'
11
+
12
+
13
+ require File.dirname(__FILE__) + '/spec_helper'
14
+
15
+ require 'spree_helper'
16
+
17
+ load 'products_images.thor'
18
+
19
+ include DataShift
20
+
21
+ describe 'Thor high level command line tasks' do
22
+
23
+ before(:each) do
24
+ end
25
+
26
+
27
+ it "should be able to run spree loaders from a simple command line task" do
28
+ Datashift::Spree.start(["products"])
29
+ end
30
+
31
+
32
+ end
metadata CHANGED
@@ -2,7 +2,7 @@
2
2
  name: datashift
3
3
  version: !ruby/object:Gem::Version
4
4
  prerelease:
5
- version: 0.4.3
5
+ version: 0.5.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-31 00:00:00 Z
13
+ date: 2012-05-08 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
@@ -30,6 +30,7 @@ files:
30
30
  - README.rdoc
31
31
  - Rakefile
32
32
  - VERSION
33
+ - datashift-0.5.0.gem
33
34
  - datashift.gemspec
34
35
  - lib/applications/jruby/jexcel_file.rb
35
36
  - lib/applications/jruby/word.rb
@@ -74,6 +75,7 @@ files:
74
75
  - lib/loaders/spreadsheet_loader.rb
75
76
  - lib/loaders/spree/image_loader.rb
76
77
  - lib/loaders/spree/product_loader.rb
78
+ - lib/thor/export_excel.thor
77
79
  - lib/thor/generate_excel.thor
78
80
  - lib/thor/import_excel.thor
79
81
  - lib/thor/spree/bootstrap_cleanup.thor
@@ -98,6 +100,7 @@ files:
98
100
  - sandbox/config/database.yml
99
101
  - sandbox/config/environment.rb
100
102
  - sandbox/config/environments/development.rb
103
+ - spec/Gemfile
101
104
  - spec/csv_loader_spec.rb
102
105
  - spec/datashift_spec.rb
103
106
  - spec/db/migrate/20110803201325_create_test_bed.rb
@@ -119,13 +122,13 @@ files:
119
122
  - spec/fixtures/images/DEMO_002_Powerstation.jpg
120
123
  - spec/fixtures/images/DEMO_003_ror_mug.jpeg
121
124
  - spec/fixtures/images/DEMO_004_ror_ringer.jpeg
122
- - spec/fixtures/interact_models_db.sqlite
123
125
  - spec/fixtures/negative/SpreeProdMiss1Mandatory.csv
124
126
  - spec/fixtures/negative/SpreeProdMiss1Mandatory.xls
125
127
  - spec/fixtures/negative/SpreeProdMissManyMandatory.csv
126
128
  - spec/fixtures/negative/SpreeProdMissManyMandatory.xls
127
129
  - spec/fixtures/simple_export_spec.xls
128
130
  - spec/fixtures/simple_template_spec.xls
131
+ - spec/fixtures/spree/SpreeProductImages.xls
129
132
  - spec/fixtures/spree/SpreeProducts.csv
130
133
  - spec/fixtures/spree/SpreeProducts.xls
131
134
  - spec/fixtures/spree/SpreeProductsDefaults.yml
@@ -148,6 +151,7 @@ files:
148
151
  - spec/spree_images_loader_spec.rb
149
152
  - spec/spree_loader_spec.rb
150
153
  - spec/spree_method_mapping_spec.rb
154
+ - spec/thor_spec.rb
151
155
  - tasks/config/seed_fu_product_template.erb
152
156
  - tasks/config/tidy_config.txt
153
157
  - tasks/export/excel_generator.rake