datashift 0.2.2 → 0.4.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|