datashift 0.2.2 → 0.4.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/README.markdown +15 -3
- data/VERSION +1 -1
- data/datashift.gemspec +11 -3
- data/lib/applications/jruby/jexcel_file.rb +10 -3
- data/lib/datashift.rb +25 -62
- data/lib/datashift/exceptions.rb +1 -0
- data/lib/datashift/logging.rb +58 -0
- data/lib/datashift/method_detail.rb +6 -45
- data/lib/datashift/method_details_manager.rb +54 -0
- data/lib/datashift/method_dictionary.rb +6 -1
- data/lib/datashift/method_mapper.rb +12 -5
- data/lib/datashift/populator.rb +46 -0
- data/lib/exporters/excel_exporter.rb +1 -1
- data/lib/generators/excel_generator.rb +48 -44
- data/lib/helpers/spree_helper.rb +14 -3
- data/lib/loaders/csv_loader.rb +9 -6
- data/lib/loaders/excel_loader.rb +5 -1
- data/lib/loaders/loader_base.rb +28 -14
- data/lib/loaders/spree/image_loader.rb +36 -34
- data/lib/loaders/spree/product_loader.rb +17 -7
- data/lib/thor/generate_excel.thor +35 -15
- data/lib/thor/import_excel.thor +84 -0
- data/lib/thor/spree/bootstrap_cleanup.thor +33 -0
- data/lib/thor/spree/products_images.thor +171 -0
- data/spec/datashift_spec.rb +19 -0
- data/spec/excel_exporter_spec.rb +3 -3
- data/spec/fixtures/datashift_Spree_db.sqlite +0 -0
- data/spec/fixtures/datashift_test_models_db.sqlite +0 -0
- data/spec/fixtures/spree/SpreeProductsDefaults.yml +15 -0
- data/spec/fixtures/spree/SpreeProductsMandatoryOnly.xls +0 -0
- data/spec/fixtures/spree/SpreeProductsWithImages.xls +0 -0
- data/spec/spec_helper.rb +2 -2
- data/spec/spree_generator_spec.rb +14 -0
- data/spec/spree_images_loader_spec.rb +73 -0
- data/spec/spree_loader_spec.rb +53 -19
- data/tasks/spree/image_load.rake +18 -13
- metadata +11 -3
- data/tasks/spree/product_loader.rake +0 -44
@@ -7,62 +7,64 @@ require 'loader_base'
|
|
7
7
|
|
8
8
|
module DataShift
|
9
9
|
|
10
|
-
|
10
|
+
|
11
|
+
module ImageLoading
|
11
12
|
|
13
|
+
include DataShift::Logging
|
14
|
+
|
12
15
|
# Note the Spree Image model sets default storage path to
|
13
16
|
# => :path => ":rails_root/public/assets/products/:id/:style/:basename.:extension"
|
14
17
|
|
15
|
-
def create_image(image_path, viewable_record = nil, options = {})
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
unless File.exists?(image_path)
|
22
|
-
puts "ERROR : Invalid Path"
|
23
|
-
return image
|
18
|
+
def create_image(klass, image_path, viewable_record = nil, options = {})
|
19
|
+
|
20
|
+
unless File.exists?(image_path) && File.readable?(image_path)
|
21
|
+
logger.error("Cannot process Image : Invalid Path #{image_path}")
|
22
|
+
raise "Cannot process Image : Invalid Path #{image_path}"
|
24
23
|
end
|
25
|
-
|
24
|
+
|
26
25
|
alt = if(options[:alt])
|
27
26
|
options[:alt]
|
28
27
|
else
|
29
28
|
(viewable_record and viewable_record.respond_to? :name) ? viewable_record.name : ""
|
30
29
|
end
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
begin
|
35
|
-
image.attachment = File.new(image_path, "r")
|
30
|
+
|
31
|
+
file = begin
|
32
|
+
File.new(image_path, "rb")
|
36
33
|
rescue => e
|
37
34
|
puts e.inspect
|
38
|
-
|
39
|
-
return image
|
35
|
+
raise "ERROR : Failed to read image #{image_path}"
|
40
36
|
end
|
41
37
|
|
42
|
-
|
43
|
-
|
38
|
+
position = (viewable_record and viewable_record.respond_to?(:images)) ? viewable_record.images.length : 0
|
39
|
+
|
40
|
+
image = klass.new( :attachment => file,:viewable => viewable_record, :alt => alt, :position => position)
|
41
|
+
#image.attachment.reprocess!
|
42
|
+
|
43
|
+
#image.viewable = viewable_record if viewable_record
|
44
44
|
|
45
45
|
puts image.save ? "Success: Created Image: #{image.inspect}" : "ERROR : Problem saving to DB Image: #{image.inspect}"
|
46
46
|
end
|
47
47
|
end
|
48
|
-
|
49
|
-
class ImageLoader < LoaderBase
|
50
48
|
|
51
|
-
|
49
|
+
module SpreeHelper
|
50
|
+
|
51
|
+
class ImageLoader < LoaderBase
|
52
|
+
|
53
|
+
include DataShift::ImageLoading
|
54
|
+
|
55
|
+
def initialize(image = nil)
|
56
|
+
puts SpreeHelper::get_spree_class('Image')
|
52
57
|
|
53
|
-
|
54
|
-
@@image_klass ||= SpreeHelper::get_spree_class('Image')
|
58
|
+
@@image_klass ||= SpreeHelper::get_spree_class('Image')
|
55
59
|
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
# Note the Spree Image model sets default storage path to
|
61
|
-
# => :path => ":rails_root/public/assets/products/:id/:style/:basename.:extension"
|
60
|
+
super( @@image_klass, image )
|
61
|
+
raise "Failed to create Image for loading" unless @load_object
|
62
|
+
end
|
62
63
|
|
63
|
-
|
64
|
-
|
64
|
+
# The path to the physical image on local disk
|
65
|
+
def process(image_path, record = nil)
|
66
|
+
@load_object = create_image(@@image_klass, image_path, record)
|
67
|
+
end
|
65
68
|
end
|
66
69
|
end
|
67
|
-
|
68
70
|
end
|
@@ -25,6 +25,7 @@ module DataShift
|
|
25
25
|
def initialize(product = nil)
|
26
26
|
super( SpreeHelper::get_product_class(), product, :instance_methods => true )
|
27
27
|
|
28
|
+
@@image_klass ||= SpreeHelper::get_spree_class('Image')
|
28
29
|
@@option_type_klass ||= SpreeHelper::get_spree_class('OptionType')
|
29
30
|
@@option_value_klass ||= SpreeHelper::get_spree_class('OptionValue')
|
30
31
|
@@property_klass ||= SpreeHelper::get_spree_class('Property')
|
@@ -42,6 +43,8 @@ module DataShift
|
|
42
43
|
# CSV files
|
43
44
|
def perform_load( file_name, options = {} )
|
44
45
|
|
46
|
+
raise DataShift::BadFile, "Cannot load #{file_name} file not found." unless(File.exists?(file_name))
|
47
|
+
|
45
48
|
ext = File.extname(file_name)
|
46
49
|
|
47
50
|
if(ext == '.xls')
|
@@ -50,7 +53,7 @@ module DataShift
|
|
50
53
|
elsif(ext == '.csv')
|
51
54
|
perform_csv_load(file_name, options)
|
52
55
|
else
|
53
|
-
raise DataShift::UnsupportedFileType, "#{ext} files not supported - Try
|
56
|
+
raise DataShift::UnsupportedFileType, "#{ext} files not supported - Try .csv or OpenOffice/Excel .xls"
|
54
57
|
end
|
55
58
|
end
|
56
59
|
|
@@ -95,7 +98,7 @@ module DataShift
|
|
95
98
|
|
96
99
|
# Spree has some stock management stuff going on, so dont usually assign to column vut use
|
97
100
|
# on_hand and on_hand=
|
98
|
-
if(@load_object.variants.size > 0 && current_value.include?(LoaderBase::multi_assoc_delim))
|
101
|
+
if(@load_object.variants.size > 0 && current_value.to_s.include?(LoaderBase::multi_assoc_delim))
|
99
102
|
|
100
103
|
#puts "DEBUG: COUNT_ON_HAND PER VARIANT",current_value.is_a?(String),
|
101
104
|
|
@@ -118,6 +121,13 @@ module DataShift
|
|
118
121
|
end
|
119
122
|
|
120
123
|
private
|
124
|
+
|
125
|
+
# Take current column data and split into each association
|
126
|
+
# Supported Syntax :
|
127
|
+
# assoc_find_name:value | assoc2_find_name:value | etc
|
128
|
+
def get_each_assoc
|
129
|
+
current_value.to_s.split( LoaderBase::multi_assoc_delim )
|
130
|
+
end
|
121
131
|
|
122
132
|
# Special case for OptionTypes as it's two stage process
|
123
133
|
# First add the possible option_types to Product, then we are able
|
@@ -128,7 +138,7 @@ module DataShift
|
|
128
138
|
# TODO smart column ordering to ensure always valid by time we get to associations
|
129
139
|
save_if_new
|
130
140
|
|
131
|
-
option_types = current_value.split( LoaderBase::multi_assoc_delim )
|
141
|
+
option_types = get_each_assoc#current_value.split( LoaderBase::multi_assoc_delim )
|
132
142
|
|
133
143
|
option_types.each do |ostr|
|
134
144
|
oname, value_str = ostr.split(LoaderBase::name_value_delim)
|
@@ -182,13 +192,13 @@ module DataShift
|
|
182
192
|
# TODO smart column ordering to ensure always valid by time we get to associations
|
183
193
|
save_if_new
|
184
194
|
|
185
|
-
images = current_value.split(LoaderBase::multi_assoc_delim)
|
195
|
+
images = get_each_assoc#current_value.split(LoaderBase::multi_assoc_delim)
|
186
196
|
|
187
197
|
images.each do |image|
|
188
198
|
|
189
199
|
img_path, alt_text = image.split(LoaderBase::name_value_delim)
|
190
200
|
|
191
|
-
image = create_image(img_path, @load_object, :alt => alt_text)
|
201
|
+
image = create_image(@@image_klass, img_path, @load_object, :alt => alt_text)
|
192
202
|
end
|
193
203
|
|
194
204
|
end
|
@@ -202,7 +212,7 @@ module DataShift
|
|
202
212
|
# TODO smart column ordering to ensure always valid by time we get to associations
|
203
213
|
save_if_new
|
204
214
|
|
205
|
-
property_list = current_value.split(LoaderBase::multi_assoc_delim)
|
215
|
+
property_list = get_each_assoc#current_value.split(LoaderBase::multi_assoc_delim)
|
206
216
|
|
207
217
|
property_list.each do |pstr|
|
208
218
|
pname, pvalue = pstr.split(LoaderBase::name_value_delim)
|
@@ -244,7 +254,7 @@ module DataShift
|
|
244
254
|
# TODO smart column ordering to ensure always valid by time we get to associations
|
245
255
|
save_if_new
|
246
256
|
|
247
|
-
chain_list = current_value().split(LoaderBase::multi_assoc_delim)
|
257
|
+
chain_list = get_each_assoc#current_value().split(LoaderBase::multi_assoc_delim)
|
248
258
|
|
249
259
|
chain_list.each do |chain|
|
250
260
|
|
@@ -3,7 +3,6 @@
|
|
3
3
|
# Date :: Mar 2012
|
4
4
|
# License:: MIT.
|
5
5
|
#
|
6
|
-
#
|
7
6
|
# Usage::
|
8
7
|
#
|
9
8
|
# To pull Datashift commands into your main application :
|
@@ -14,29 +13,37 @@
|
|
14
13
|
#
|
15
14
|
# Cmd Line:
|
16
15
|
#
|
17
|
-
# => bundle exec thor datashift:generate:excel
|
16
|
+
# => bundle exec thor datashift:generate:excel -m <active record class> -r <output_template.xls> -a
|
18
17
|
#
|
19
|
-
|
18
|
+
require 'datashift'
|
19
|
+
|
20
|
+
# Note, not DataShift, case sensitive, create namespace for command line : datashift
|
20
21
|
module Datashift
|
21
|
-
|
22
|
+
|
23
|
+
|
22
24
|
class Generate < Thor
|
23
|
-
|
24
|
-
|
25
|
+
|
26
|
+
include DataShift::Logging
|
27
|
+
|
28
|
+
desc "excel", "generate a template from an active record model (with optional associations)"
|
25
29
|
method_option :model, :aliases => '-m', :required => true, :desc => "The active record model to export"
|
26
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}"
|
27
33
|
|
28
34
|
def excel()
|
29
35
|
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
require 'excel_generator'
|
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_generator'
|
36
41
|
|
37
42
|
model = options[:model]
|
38
43
|
result = options[:result]
|
39
|
-
|
44
|
+
|
45
|
+
logger.info "Datashift: Start Excel template generation in #{result}"
|
46
|
+
|
40
47
|
begin
|
41
48
|
# support modules e.g "Spree::Property")
|
42
49
|
klass = ModelMapper::class_from_string(model) #Kernel.const_get(model)
|
@@ -45,9 +52,22 @@ module Datashift
|
|
45
52
|
raise "ERROR: No such Model [#{model}] found - check valid model supplied via -model <Class>"
|
46
53
|
end
|
47
54
|
|
48
|
-
|
55
|
+
begin
|
56
|
+
gen = DataShift::ExcelGenerator.new(result)
|
57
|
+
|
58
|
+
if(options[:assoc])
|
59
|
+
opts = (options[:exclude]) ? {:exclude => options[:exclude]} : {}
|
60
|
+
logger.info("Datashift: Generating 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 generation, template may be incomplete"
|
69
|
+
end
|
49
70
|
|
50
|
-
gen.generate(klass)
|
51
71
|
end
|
52
72
|
end
|
53
73
|
|
@@ -0,0 +1,84 @@
|
|
1
|
+
# Copyright:: (c) Autotelik Media Ltd 2012
|
2
|
+
# Author :: Tom Statter
|
3
|
+
# Date :: Mar 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
|
+
# Requires Jruby, cmd Line:
|
15
|
+
#
|
16
|
+
# => bundle exec thor datashift:import:excel -m <active record class> -r <output_template.xls> -a
|
17
|
+
#
|
18
|
+
# Cmd Line:
|
19
|
+
#
|
20
|
+
# => jruby -S rake datashift:import:excel model=<active record class> input=<file.xls>
|
21
|
+
# => jruby -S rake datashift:import:excel model=<active record class> input=C:\MyProducts.xlsverbose=true
|
22
|
+
#
|
23
|
+
require 'datashift'
|
24
|
+
|
25
|
+
|
26
|
+
# Note, not DataShift, case sensitive, create namespace for command line : datashift
|
27
|
+
module Datashift
|
28
|
+
|
29
|
+
|
30
|
+
class Import < Thor
|
31
|
+
|
32
|
+
include DataShift::Logging
|
33
|
+
|
34
|
+
desc "excel", "import .xls file for specifiec active record model"
|
35
|
+
method_option :model, :aliases => '-m', :required => true, :desc => "The related active record model"
|
36
|
+
method_option :input, :aliases => '-i', :required => true, :desc => "The input .xls file"
|
37
|
+
method_option :assoc, :aliases => '-a', :type => :boolean, :desc => "Include any associations supplied in the input"
|
38
|
+
method_option :exclude, :aliases => '-e', :type => :array, :desc => "Use with -a : Exclude association types. Any from #{DataShift::MethodDetail::supported_types_enum.to_a.inspect}"
|
39
|
+
|
40
|
+
def excel()
|
41
|
+
|
42
|
+
# TODO - We're assuming run from a rails app/top level dir...
|
43
|
+
# ...can we make this more robust ? e.g what about when using active record but not in Rails app,
|
44
|
+
require File.expand_path('config/environment.rb')
|
45
|
+
|
46
|
+
require 'excel_loader'
|
47
|
+
|
48
|
+
model = options[:model]
|
49
|
+
begin
|
50
|
+
# support modules e.g "Spree::Property")
|
51
|
+
klass = ModelMapper::class_from_string(model) #Kernel.const_get(model)
|
52
|
+
rescue NameError
|
53
|
+
raise "ERROR: No such AR Model found - check valid model supplied via model=<Class>"
|
54
|
+
end
|
55
|
+
|
56
|
+
if(ENV['loader'])
|
57
|
+
begin
|
58
|
+
#loader_klass = Kernel.const_get(ENV['loader'])
|
59
|
+
# support modules e.g "Spree::Property")
|
60
|
+
loader_klass = ModelMapper::class_from_string(ENV['loader']) #Kernel.const_get(model)
|
61
|
+
|
62
|
+
loader = loader_klass.new(klass)
|
63
|
+
|
64
|
+
logger.info("INFO: Using loader : #{loader.class}")
|
65
|
+
rescue
|
66
|
+
logger.error("INFO: No specific #{model}Loader found - using generic ExcelLoader")
|
67
|
+
loader = DataShift::ExcelLoader.new(klass)
|
68
|
+
end
|
69
|
+
else
|
70
|
+
logger.info("No Loader specified - using generic ExcelLoader")
|
71
|
+
loader = DataShift::ExcelLoader.new(klass)
|
72
|
+
end
|
73
|
+
|
74
|
+
logger.info("ARGS #{options.inspect} [#{options[:verbose]}]")
|
75
|
+
loader.logger.verbose if(ENV['verbose'])
|
76
|
+
|
77
|
+
loader.configure_from( ENV['config'] ) if(ENV['config'])
|
78
|
+
|
79
|
+
loader.perform_load(options[:input])
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
end
|
84
|
+
|
@@ -0,0 +1,33 @@
|
|
1
|
+
# Copyright:: (c) Autotelik Media Ltd 2012
|
2
|
+
# Author :: Tom Statter
|
3
|
+
# Date :: March 2012
|
4
|
+
# License:: MIT. Free, Open Source.
|
5
|
+
#
|
6
|
+
# Usage::
|
7
|
+
# bundle exec thor help datashift:spreeboot
|
8
|
+
# bundle exec thor datashift:spreeboot:cleanup
|
9
|
+
#
|
10
|
+
# Note, not DataShift, case sensitive, create namespace for command line : datashift
|
11
|
+
module Datashift
|
12
|
+
|
13
|
+
class Spreeboot < Thor
|
14
|
+
|
15
|
+
include DataShift::Logging
|
16
|
+
|
17
|
+
desc "cleanup", "Remove Spree Product/Variant data from DB"
|
18
|
+
|
19
|
+
def cleanup() #, [:input, :verbose, :sku_prefix] => :environment do |t, args|
|
20
|
+
|
21
|
+
require 'spree_helper'
|
22
|
+
|
23
|
+
require File.expand_path('config/environment.rb')
|
24
|
+
|
25
|
+
%w{Image OptionType OptionValue Product Property ProductProperty Variant Taxonomy Taxon Zone}.each do |k|
|
26
|
+
instance_variable_set("@#{k}_klass", DataShift::SpreeHelper::get_spree_class(k))
|
27
|
+
instance_variable_get("@#{k}_klass").delete_all
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
end
|
32
|
+
|
33
|
+
end
|
@@ -0,0 +1,171 @@
|
|
1
|
+
# Copyright:: (c) Autotelik Media Ltd 2012
|
2
|
+
# Author :: Tom Statter
|
3
|
+
# Date :: March 2012
|
4
|
+
# License:: MIT. Free, Open Source.
|
5
|
+
#
|
6
|
+
# Usage::
|
7
|
+
# bundle exec thor help datashift:spree
|
8
|
+
# bundle exec thor datashift:spree:products -i db/datashift/MegamanFozz20111115_load.xls -s 299S_
|
9
|
+
#
|
10
|
+
# bundle exec thor datashift:spree:images -i db/datashift/imagebank -s -p 299S_
|
11
|
+
#
|
12
|
+
|
13
|
+
# Note, not DataShift, case sensitive, create namespace for command line : datashift
|
14
|
+
module Datashift
|
15
|
+
|
16
|
+
class Spree < Thor
|
17
|
+
|
18
|
+
include DataShift::Logging
|
19
|
+
|
20
|
+
desc "products", "Populate Spree Product/Variant data from .xls (Excel) or CSV file"
|
21
|
+
|
22
|
+
method_option :input, :aliases => '-i', :required => true, :desc => "The import file (.xls or .csv)"
|
23
|
+
method_option :sku_prefix, :aliases => '-s', :desc => "Prefix to add to each SKU in import file"
|
24
|
+
method_option :verbose, :aliases => '-v', :type => :boolean, :desc => "Verbose logging"
|
25
|
+
method_option :config, :aliases => '-c', :type => :string, :desc => "Configuration file containg defaults or over rides in YAML"
|
26
|
+
|
27
|
+
def products() #, [:input, :verbose, :sku_prefix] => :environment do |t, args|
|
28
|
+
|
29
|
+
# TODO - We're assuming run from a rails app/top level dir...
|
30
|
+
# ...can we make this more robust ? e.g what about when using active record but not in Rails app,
|
31
|
+
require File.expand_path('config/environment.rb')
|
32
|
+
|
33
|
+
input = options[:input]
|
34
|
+
|
35
|
+
require 'product_loader'
|
36
|
+
|
37
|
+
loader = DataShift::SpreeHelper::ProductLoader.new
|
38
|
+
|
39
|
+
# YAML configuration file to drive defaults etc
|
40
|
+
|
41
|
+
if(options[:config])
|
42
|
+
raise "Bad Config - Cannot find specified file #{options[:config]}" unless File.exists?(options[:config])
|
43
|
+
|
44
|
+
loader.configure_from( options[:config] )
|
45
|
+
else
|
46
|
+
loader.set_default_value('available_on', Time.now.to_s(:db) )
|
47
|
+
loader.set_default_value('cost_price', 0.0 )
|
48
|
+
end
|
49
|
+
|
50
|
+
loader.set_prefix('sku', options[:sku_prefix] ) if(options[:sku_prefix])
|
51
|
+
|
52
|
+
puts "DataShift::Product starting upload from file: #{input}"
|
53
|
+
|
54
|
+
loader.perform_load(input, :mandatory => ['sku', 'name', 'price'] )
|
55
|
+
end
|
56
|
+
|
57
|
+
|
58
|
+
#
|
59
|
+
# => rake datashift:spree:images input=vendor/extensions/site/fixtures/images
|
60
|
+
# => rake datashift:spree:images input=C:\images\photos large dummy=true
|
61
|
+
#
|
62
|
+
# => rake datashift:spree:images input=C:\images\taxon_icons skip_if_no_assoc=true klass=Taxon
|
63
|
+
#
|
64
|
+
desc "images", "Populate the DB with images.\nDefault location db/image_seeds, or specify :input=<path> or dir under db/image_seeds with :folder"
|
65
|
+
|
66
|
+
# :dummy => dummy run without actual saving to DB
|
67
|
+
method_option :input, :aliases => '-i', :required => true, :desc => "The import file (.xls or .csv)"
|
68
|
+
|
69
|
+
method_option :process_when_no_assoc, :aliases => '-f', :type => :boolean, :desc => "Process image even if no Product found - force loading"
|
70
|
+
|
71
|
+
|
72
|
+
method_option :sku, :aliases => '-s', :desc => "Lookup Product based on image name starting with sku"
|
73
|
+
method_option :sku_prefix, :aliases => '-p', :desc => "Prefix to add to each SKU in import file"
|
74
|
+
method_option :dummy, :aliases => '-d', :type => :boolean, :desc => "Dummy run, do not actually save Image or Product"
|
75
|
+
method_option :verbose, :aliases => '-v', :type => :boolean, :desc => "Verbose logging"
|
76
|
+
#method_option :config, :aliases => '-c', :type => :string, :desc => "Configuration file containg defaults or over rides in YAML"
|
77
|
+
|
78
|
+
def images()#, [:input, :folder, :dummy, :sku, :skip_if_no_assoc, :skip_if_loaded, :model] => :environment do |t, args|
|
79
|
+
|
80
|
+
require File.expand_path('config/environment.rb')
|
81
|
+
|
82
|
+
require 'image_loader'
|
83
|
+
|
84
|
+
@image_cache = options[:input]
|
85
|
+
|
86
|
+
attachment_klazz = DataShift::SpreeHelper::get_spree_class('Product' )
|
87
|
+
sku_klazz = DataShift::SpreeHelper::get_spree_class('Variant' )
|
88
|
+
|
89
|
+
# TODO generalise for any paperclip project, for now just Spree
|
90
|
+
#begin
|
91
|
+
# attachment_klazz = Kernel.const_get(args[:model]) if(args[:model])
|
92
|
+
# rescue NameError
|
93
|
+
# raise "Could not find contant for model #{args[:model]}"
|
94
|
+
#end
|
95
|
+
|
96
|
+
image_loader = DataShift::SpreeHelper::ImageLoader.new
|
97
|
+
|
98
|
+
if(File.directory? @image_cache )
|
99
|
+
logger.info "Loading Spree images from #{@image_cache}"
|
100
|
+
|
101
|
+
missing_records = []
|
102
|
+
Dir.glob("#{@image_cache}/**/*.{jpg,png,gif}") do |image_name|
|
103
|
+
|
104
|
+
base_name = File.basename(image_name, '.*')
|
105
|
+
|
106
|
+
logger.info "Processing #{base_name} : #{File.exists?(image_name)}"
|
107
|
+
|
108
|
+
record = nil
|
109
|
+
if(options[:sku])
|
110
|
+
sku = base_name.slice!(/\w+/)
|
111
|
+
sku.strip!
|
112
|
+
base_name.strip!
|
113
|
+
|
114
|
+
sku = "#{options[:sku_prefix]}#{sku}" if(options[:sku_prefix])
|
115
|
+
|
116
|
+
record = sku_klazz.find_by_sku(sku)
|
117
|
+
|
118
|
+
unless record # try splitting up filename in various ways looking for the SKU
|
119
|
+
sku.split( '_' ).each do |x|
|
120
|
+
x = "#{options[:sku_prefix]}#{x}" if(options[:sku_prefix])
|
121
|
+
record = sku_klazz.find_by_sku(x)
|
122
|
+
break if record
|
123
|
+
end
|
124
|
+
end
|
125
|
+
|
126
|
+
record = record.product if(record) # SKU stored on Variant but we want it's master Product
|
127
|
+
|
128
|
+
else
|
129
|
+
record = attachment_klazz.find_by_name(base_name)
|
130
|
+
end
|
131
|
+
|
132
|
+
if(record)
|
133
|
+
logger.info "Found record for attachment : #{record.inspect}"
|
134
|
+
exists = record.images.detect {|i| puts "COMPARE #{i.attachment_file_name} => #{image_name}"; i.attachment_file_name == image_name }
|
135
|
+
|
136
|
+
if(options[:skip_if_loaded] && !exists.nil?)
|
137
|
+
logger.info "Skipping - Image #{image_name} already loaded for #{attachment_klazz}"
|
138
|
+
next
|
139
|
+
end
|
140
|
+
else
|
141
|
+
missing_records << image_name
|
142
|
+
end
|
143
|
+
|
144
|
+
# Now do actual upload to DB unless we are doing a dummy run,
|
145
|
+
# or the Image must have an associated record
|
146
|
+
unless(options[:dummy] == 'true' || (options[:process_when_no_assoc] && record.nil?))
|
147
|
+
image_loader.reset()
|
148
|
+
puts "Process Image"
|
149
|
+
image_loader.process( image_name, record )
|
150
|
+
end
|
151
|
+
|
152
|
+
end
|
153
|
+
|
154
|
+
unless missing_records.empty?
|
155
|
+
FileUtils.mkdir_p('MissingRecords') unless File.directory?('MissingRecords')
|
156
|
+
|
157
|
+
puts '\nMISSING Records Report>>'
|
158
|
+
missing_records.each do |i|
|
159
|
+
puts "Copy #{i} to MissingRecords folder"
|
160
|
+
FileUtils.cp( i, 'MissingRecords') unless(options[:dummy] == 'true')
|
161
|
+
end
|
162
|
+
end
|
163
|
+
|
164
|
+
else
|
165
|
+
puts "ERROR: Supplied Path #{@image_cache} not accesible"
|
166
|
+
exit(-1)
|
167
|
+
end
|
168
|
+
end
|
169
|
+
end
|
170
|
+
|
171
|
+
end
|