datashift 0.7.0 → 0.8.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 +14 -98
- data/VERSION +1 -1
- data/datashift.gemspec +6 -4
- data/lib/applications/jruby/jexcel_file.rb +69 -52
- data/lib/datashift/method_detail.rb +3 -2
- data/lib/datashift/method_dictionary.rb +7 -2
- data/lib/datashift/method_mapper.rb +12 -3
- data/lib/datashift/model_mapper.rb +4 -4
- data/lib/generators/excel_generator.rb +17 -6
- data/lib/loaders/excel_loader.rb +3 -2
- data/lib/loaders/loader_base.rb +62 -27
- data/lib/loaders/paperclip/image_loader.rb +75 -0
- data/lib/loaders/spree/image_loader.rb +11 -42
- data/lib/loaders/spree/product_loader.rb +94 -52
- data/lib/thor/generate_excel.thor +5 -2
- data/lib/thor/spree/bootstrap_cleanup.thor +22 -16
- data/lib/thor/spree/products_images.thor +58 -45
- data/lib/thor/spree/reports.thor +66 -0
- data/spec/db/migrate/20110803201325_create_test_bed.rb +12 -1
- data/spec/excel_generator_spec.rb +39 -1
- data/spec/excel_loader_spec.rb +1 -0
- data/spec/fixtures/datashift_Spree_db.sqlite +0 -0
- data/spec/fixtures/datashift_test_models_db.sqlite +0 -0
- data/spec/fixtures/spree/SpreeMultiVariant.csv +4 -0
- data/spec/fixtures/spree/SpreeProductsSimple.csv +1 -1
- data/spec/fixtures/spree/SpreeProductsSimple.xls +0 -0
- data/spec/fixtures/test_model_defs.rb +4 -0
- data/spec/spree_images_loader_spec.rb +11 -29
- data/spec/spree_loader_spec.rb +60 -15
- data/tasks/db_tasks.rake +45 -0
- metadata +6 -4
- data/datashift-0.6.0.gem +0 -0
- data/datashift-0.6.1.gem +0 -0
@@ -35,7 +35,7 @@ module DataShift
|
|
35
35
|
attr_reader :operator, :operator_type
|
36
36
|
|
37
37
|
# TODO make it a list/primary keys
|
38
|
-
attr_accessor :find_by_operator
|
38
|
+
attr_accessor :find_by_operator, :find_by_value
|
39
39
|
|
40
40
|
# Store the raw (client supplied) name against the active record klass(model).
|
41
41
|
# Operator is the associated method call on klass,
|
@@ -43,9 +43,10 @@ module DataShift
|
|
43
43
|
#
|
44
44
|
# col_types can typically be derived from klass.columns - set of ActiveRecord::ConnectionAdapters::Column
|
45
45
|
|
46
|
-
def initialize(client_name, klass, operator, type, col_types = {}, find_by_operator = nil )
|
46
|
+
def initialize(client_name, klass, operator, type, col_types = {}, find_by_operator = nil, find_by_value = nil )
|
47
47
|
@klass, @name = klass, client_name
|
48
48
|
@find_by_operator = find_by_operator
|
49
|
+
@find_by_value = find_by_value
|
49
50
|
|
50
51
|
if( MethodDetail::supported_types_enum.member?(type.to_sym) )
|
51
52
|
@operator_type = type.to_sym
|
@@ -17,6 +17,11 @@ module DataShift
|
|
17
17
|
end
|
18
18
|
|
19
19
|
|
20
|
+
# Has the dictionary been populated for klass
|
21
|
+
def self.for?(klass)
|
22
|
+
return !(has_many[klass] || belongs_to[klass] || has_one[klass] || assignments[klass]).nil?
|
23
|
+
end
|
24
|
+
|
20
25
|
# Create simple picture of all the operator names for assignment available on an AR model,
|
21
26
|
# grouped by type of association (includes belongs_to and has_many which provides both << and = )
|
22
27
|
# Options:
|
@@ -43,7 +48,7 @@ module DataShift
|
|
43
48
|
#puts "Belongs To Associations:", belongs_to[klass].inspect
|
44
49
|
|
45
50
|
# Find the has_one associations which can be populated via Model.has_one_name = OtherArModelObject
|
46
|
-
if( options[:reload] ||
|
51
|
+
if( options[:reload] || has_one[klass].nil? )
|
47
52
|
has_one[klass] = klass.reflect_on_all_associations(:has_one).map { |i| i.name.to_s }
|
48
53
|
end
|
49
54
|
|
@@ -145,7 +150,7 @@ module DataShift
|
|
145
150
|
|
146
151
|
MethodDetail::supported_types_enum.each do |t|
|
147
152
|
method_detail = method_details_mgr.find(n, t)
|
148
|
-
return method_detail if(method_detail)
|
153
|
+
return method_detail.clone if(method_detail)
|
149
154
|
end
|
150
155
|
|
151
156
|
end
|
@@ -32,6 +32,9 @@ module DataShift
|
|
32
32
|
# in the heading .. i.e Column header => 'BlogPosts:user_id'
|
33
33
|
# ... association has many BlogPosts selected via find_by_user_id
|
34
34
|
#
|
35
|
+
# in the heading .. i.e Column header => 'BlogPosts:user_name:John Smith'
|
36
|
+
# ... association has many BlogPosts selected via find_by_user_name("John Smith")
|
37
|
+
#
|
35
38
|
def self.column_delim
|
36
39
|
@column_delim ||= ':'
|
37
40
|
@column_delim
|
@@ -60,11 +63,12 @@ module DataShift
|
|
60
63
|
columns.each do |name|
|
61
64
|
if(name.nil? or name.empty?)
|
62
65
|
logger.warn("Column list contains empty or null columns")
|
66
|
+
@method_details << nil
|
63
67
|
next
|
64
68
|
end
|
65
69
|
|
66
70
|
operator, lookup = name.split(MethodMapper::column_delim)
|
67
|
-
|
71
|
+
|
68
72
|
md = MethodDictionary::find_method_detail( klass, operator )
|
69
73
|
|
70
74
|
# TODO be nice if we could cheeck that the assoc on klass responds to the specified
|
@@ -76,8 +80,13 @@ module DataShift
|
|
76
80
|
|
77
81
|
if(md)
|
78
82
|
|
79
|
-
|
80
|
-
|
83
|
+
if(lookup)
|
84
|
+
find_by, find_value = lookup.split(MethodMapper::column_delim)
|
85
|
+
md.find_by_value = find_value
|
86
|
+
md.find_by_operator = find_by # TODO and klass.x.respond_to?(active_record_helper))
|
87
|
+
#puts "DEBUG: Method Detail #{md.name};#{md.operator} : find_by_operator #{md.find_by_operator}"
|
88
|
+
end
|
89
|
+
|
81
90
|
@method_details << md
|
82
91
|
else
|
83
92
|
@missing_methods << operator
|
@@ -6,19 +6,19 @@ class ModelMapper
|
|
6
6
|
# e.g "Spree::Property" returns the Spree::Property class
|
7
7
|
# Raises exception if no such class found
|
8
8
|
def self.const_get_from_string(str)
|
9
|
-
str.split('::').inject(Object) do |mod, class_name|
|
9
|
+
str.to_s.split('::').inject(Object) do |mod, class_name|
|
10
10
|
mod.const_get(class_name)
|
11
11
|
end
|
12
12
|
end
|
13
|
-
|
14
|
-
|
13
|
+
|
14
|
+
|
15
15
|
# Similar to const_get_from_string except this version
|
16
16
|
# returns nil if no such class found
|
17
17
|
# Support modules e.g "Spree::Property"
|
18
18
|
#
|
19
19
|
def self.class_from_string( str )
|
20
20
|
begin
|
21
|
-
ModelMapper::const_get_from_string(str) #Kernel.const_get(model)
|
21
|
+
ModelMapper::const_get_from_string(str.to_s) #Kernel.const_get(model)
|
22
22
|
rescue NameError => e
|
23
23
|
return nil
|
24
24
|
end
|
@@ -27,7 +27,9 @@ module DataShift
|
|
27
27
|
end
|
28
28
|
|
29
29
|
# Create an Excel file template (header row) representing supplied Model
|
30
|
-
|
30
|
+
# Options:
|
31
|
+
# * <tt>:autosize</tt> - Autosize all the columns
|
32
|
+
#
|
31
33
|
def generate(klass, options = {})
|
32
34
|
|
33
35
|
prepare(klass, options)
|
@@ -36,18 +38,25 @@ module DataShift
|
|
36
38
|
|
37
39
|
logger.info("ExcelGenerator saving generated template #{@filename}")
|
38
40
|
|
41
|
+
@excel.autosize if(options[:autosize])
|
42
|
+
|
39
43
|
@excel.save( @filename )
|
40
44
|
end
|
41
45
|
|
42
46
|
|
43
|
-
# Create an Excel file
|
44
|
-
#
|
45
|
-
#
|
47
|
+
# Create an Excel file template (header row) representing supplied Model
|
48
|
+
# and it's associations
|
49
|
+
#
|
50
|
+
# Options:
|
51
|
+
# * <tt>:autosize</tt> - Autosize all the columns
|
52
|
+
#
|
53
|
+
# * <tt>:exclude</tt> - Associations to exclude.
|
54
|
+
# You can specify a hash of {association_type => [array of association names] }
|
55
|
+
# to exclude from the template.
|
46
56
|
#
|
47
|
-
# Possible values are given by MethodDetail::supported_types_enum
|
57
|
+
# Possible association_type values are given by MethodDetail::supported_types_enum
|
48
58
|
# ... [:assignment, :belongs_to, :has_one, :has_many]
|
49
59
|
#
|
50
|
-
# Options
|
51
60
|
def generate_with_associations(klass, options = {})
|
52
61
|
|
53
62
|
prepare(klass, options)
|
@@ -69,6 +78,8 @@ module DataShift
|
|
69
78
|
end
|
70
79
|
|
71
80
|
@excel.set_headers( headers )
|
81
|
+
|
82
|
+
@excel.autosize if(options[:autosize])
|
72
83
|
|
73
84
|
@excel.save( filename() )
|
74
85
|
end
|
data/lib/loaders/excel_loader.rb
CHANGED
@@ -66,7 +66,7 @@ module DataShift
|
|
66
66
|
# For example if model has an attribute 'price' will map columns called Price, price, PRICE etc to this attribute
|
67
67
|
map_headers_to_operators( @headers, options )
|
68
68
|
|
69
|
-
logger.info "Excel Loader
|
69
|
+
logger.info "Excel Loader processing #{@excel.num_rows} rows"
|
70
70
|
load_object_class.transaction do
|
71
71
|
@loaded_objects = []
|
72
72
|
|
@@ -124,8 +124,9 @@ module DataShift
|
|
124
124
|
end
|
125
125
|
end
|
126
126
|
puts "Excel loading stage complete - #{loaded_objects.size} rows added."
|
127
|
+
puts "There were NO failures." if failed_objects.empty?
|
127
128
|
|
128
|
-
puts "WARNING : #{failed_objects.size} rows contained errors and #{failed_objects.size} records NOT created." unless failed_objects.empty?
|
129
|
+
puts "WARNING : Check logs : #{failed_objects.size} rows contained errors and #{failed_objects.size} records NOT created." unless failed_objects.empty?
|
129
130
|
end
|
130
131
|
|
131
132
|
def value_at(row, column)
|
data/lib/loaders/loader_base.rb
CHANGED
@@ -85,21 +85,33 @@ module DataShift
|
|
85
85
|
def self.set_multi_assoc_delim(x) @multi_assoc_delim = x; end
|
86
86
|
|
87
87
|
|
88
|
+
# Setup loading
|
89
|
+
#
|
90
|
+
# Options to drive building the method dictionary for a class, enabling headers to be mapped to operators on that class.
|
91
|
+
#
|
88
92
|
# Options
|
89
|
-
#
|
93
|
+
# :load [default = true] : Load the method dictionary for object_class
|
94
|
+
#
|
95
|
+
# :reload : Force load of the method dictionary for object_class even if already loaded
|
96
|
+
# :instance_methods : Include setter type instance methods for assignment as well as AR columns
|
90
97
|
|
98
|
+
|
91
99
|
def initialize(object_class, object = nil, options = {})
|
92
100
|
@load_object_class = object_class
|
93
101
|
|
94
102
|
# Gather names of all possible 'setter' methods on AR class (instance variables and associations)
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
103
|
+
unless(MethodDictionary::for?(object_class) && options[:reload] == false)
|
104
|
+
#puts "Building Method Dictionary for class #{object_class}"
|
105
|
+
DataShift::MethodDictionary.find_operators( @load_object_class, :reload => options[:reload], :instance_methods => options[:instance_methods] )
|
106
|
+
|
107
|
+
# Create dictionary of data on all possible 'setter' methods which can be used to
|
108
|
+
# populate or integrate an object of type @load_object_class
|
109
|
+
DataShift::MethodDictionary.build_method_details(@load_object_class)
|
110
|
+
end unless(options[:load] == false)
|
100
111
|
|
101
112
|
@method_mapper = DataShift::MethodMapper.new
|
102
|
-
@options = options.clone
|
113
|
+
@options = options.dup # clone can cause issues like 'can't modify frozen hash'
|
114
|
+
|
103
115
|
@verbose = @options[:verbose]
|
104
116
|
@headers = []
|
105
117
|
|
@@ -127,8 +139,8 @@ module DataShift
|
|
127
139
|
# mandatory : List of columns that must be present in headers
|
128
140
|
#
|
129
141
|
# force_inclusion : List of columns that do not map to any operator but should be includeed in processing.
|
130
|
-
#
|
131
|
-
#
|
142
|
+
# This provides the opportunity for loaders to provide specific methods to handle these fields
|
143
|
+
# when no direct operator is available on the model or it's associations
|
132
144
|
#
|
133
145
|
def perform_load( file_name, options = {} )
|
134
146
|
|
@@ -179,7 +191,7 @@ module DataShift
|
|
179
191
|
end
|
180
192
|
|
181
193
|
unless(@method_mapper.missing_methods.empty?)
|
182
|
-
puts "WARNING:
|
194
|
+
puts "WARNING: These headings couldn't be mapped to class #{load_object_class} : #{@method_mapper.missing_methods.inspect}"
|
183
195
|
raise MappingDefinitionError, "Missing mappings for columns : #{@method_mapper.missing_methods.join(",")}" if(strict)
|
184
196
|
end
|
185
197
|
|
@@ -214,18 +226,20 @@ module DataShift
|
|
214
226
|
end
|
215
227
|
end
|
216
228
|
|
217
|
-
|
218
|
-
|
219
|
-
|
229
|
+
|
230
|
+
# Find a record for model klazz, looking up on field for x
|
231
|
+
# Responds to global Options :
|
232
|
+
# :case_sensitive : Default is a case insensitive lookup.
|
233
|
+
# :use_like : Attempts a lookup using ike and x% ratehr than equality
|
234
|
+
|
235
|
+
def get_record_by(klazz, field, x)
|
236
|
+
|
220
237
|
begin
|
221
238
|
if(@options[:case_sensitive])
|
222
|
-
puts "Search case sensitive for [#{x}] on #{field}" if(@verbose)
|
223
239
|
return klazz.send("find_by_#{field}", x)
|
224
240
|
elsif(@options[:use_like])
|
225
|
-
puts "Term : #{klazz}.where(\"#{field} LIKE '#{x}%'\")" if(@verbose)
|
226
241
|
return klazz.where("#{field} like ?", "#{x}%").first
|
227
242
|
else
|
228
|
-
puts "Term : #{klazz}.where(\"lower(#{field}) = '#{x.downcase}'\")" if(@verbose)
|
229
243
|
return klazz.where("lower(#{field}) = ?", x.downcase).first
|
230
244
|
end
|
231
245
|
rescue => e
|
@@ -238,8 +252,10 @@ module DataShift
|
|
238
252
|
|
239
253
|
# Default values and over rides can be provided in YAML config file.
|
240
254
|
#
|
241
|
-
# Any
|
242
|
-
#
|
255
|
+
# Any Config under key 'LoaderBase' is merged over existing options - taking precedence.
|
256
|
+
#
|
257
|
+
# Any Config under a key equal to the full name of the Loader class (e.g DataShift::SpreeHelper::ImageLoader)
|
258
|
+
# is merged over existing options - taking precedence.
|
243
259
|
#
|
244
260
|
# Format :
|
245
261
|
#
|
@@ -297,6 +313,10 @@ module DataShift
|
|
297
313
|
if(data['LoaderBase'])
|
298
314
|
@options.merge!(data['LoaderBase'])
|
299
315
|
end
|
316
|
+
|
317
|
+
if(data[self.class.name])
|
318
|
+
@options.merge!(data[self.class.name])
|
319
|
+
end
|
300
320
|
|
301
321
|
logger.info("Loader Options : #{@options.inspect}")
|
302
322
|
end
|
@@ -326,18 +346,31 @@ module DataShift
|
|
326
346
|
@current_value
|
327
347
|
end
|
328
348
|
|
329
|
-
#
|
330
|
-
|
331
|
-
|
332
|
-
|
333
|
-
|
349
|
+
# Return the find_by operator and the rest of the (row,columns) data
|
350
|
+
# price:0.99
|
351
|
+
#
|
352
|
+
# Column headings can already contain the operator so possible that row only contains
|
353
|
+
# 0.99
|
354
|
+
# We leave it to caller to manage any other aspects or problems in 'rest'
|
355
|
+
#
|
356
|
+
def get_find_operator_and_rest(inbound_data)
|
357
|
+
|
358
|
+
operator, rest = inbound_data.split(LoaderBase::name_value_delim)
|
359
|
+
|
360
|
+
#puts "DEBUG inbound_data: #{inbound_data} => #{operator} , #{rest}"
|
361
|
+
|
362
|
+
# Find by operator embedded in row takes precedence over operator in column heading
|
334
363
|
if(@current_method_detail.find_by_operator)
|
335
|
-
|
336
|
-
|
337
|
-
|
364
|
+
# row contains 0.99 so rest is effectively operator, and operator is in method details
|
365
|
+
if(rest.nil?)
|
366
|
+
rest = operator
|
367
|
+
operator = @current_method_detail.find_by_operator
|
368
|
+
end
|
338
369
|
end
|
339
370
|
|
340
|
-
|
371
|
+
#puts "DEBUG: get_find_operator_and_rest: #{operator} => #{rest}"
|
372
|
+
|
373
|
+
return operator, rest
|
341
374
|
end
|
342
375
|
|
343
376
|
# Process a value string from a column.
|
@@ -377,6 +410,8 @@ module DataShift
|
|
377
410
|
raise "Cannot perform DB find by #{find_operator}. Expected format key:value" unless(find_operator && col_values)
|
378
411
|
|
379
412
|
find_by_values = col_values.split(LoaderBase::multi_value_delim)
|
413
|
+
|
414
|
+
find_by_values << @current_method_detail.find_by_value if(@current_method_detail.find_by_value)
|
380
415
|
|
381
416
|
if(find_by_values.size > 1)
|
382
417
|
|
@@ -0,0 +1,75 @@
|
|
1
|
+
# Copyright:: (c) Autotelik Media Ltd 2012
|
2
|
+
# Author :: Tom Statter
|
3
|
+
# Date :: June 2012
|
4
|
+
# License:: MIT. Free, Open Source.
|
5
|
+
#
|
6
|
+
# => Provides facilities for bulk uploading/exporting attachments provided by PaperClip
|
7
|
+
# gem
|
8
|
+
require 'loader_base'
|
9
|
+
|
10
|
+
module DataShift
|
11
|
+
|
12
|
+
module ImageLoading
|
13
|
+
|
14
|
+
include DataShift::Logging
|
15
|
+
|
16
|
+
def self.get_files(path, options = {})
|
17
|
+
glob = (options['recursive'] || options[:recursive]) ? "**/*.{jpg,png,gif}" : "*.{jpg,png,gif}"
|
18
|
+
|
19
|
+
Dir.glob("#{path}/#{glob}")
|
20
|
+
end
|
21
|
+
|
22
|
+
def get_file( attachment_path )
|
23
|
+
|
24
|
+
unless File.exists?(attachment_path) && File.readable?(attachment_path)
|
25
|
+
logger.error("Cannot process Image from #{Dir.pwd}: Invalid Path #{attachment_path}")
|
26
|
+
raise "Cannot process Image : Invalid Path #{attachment_path}"
|
27
|
+
end
|
28
|
+
|
29
|
+
file = begin
|
30
|
+
File.new(attachment_path, "rb")
|
31
|
+
rescue => e
|
32
|
+
puts e.inspect
|
33
|
+
raise "ERROR : Failed to read image #{attachment_path}"
|
34
|
+
end
|
35
|
+
|
36
|
+
file
|
37
|
+
end
|
38
|
+
|
39
|
+
# Note the paperclip attachment model defines the storage path via something like :
|
40
|
+
# => :path => ":rails_root/public/blah/blahs/:id/:style/:basename.:extension"
|
41
|
+
# Options
|
42
|
+
# has_attached_file_name : Paperclip attachment name defined with macro 'has_attached_file :name' e.g has_attached_file :avatar
|
43
|
+
#
|
44
|
+
def create_image(klass, attachment_path, viewable_record = nil, options = {})
|
45
|
+
|
46
|
+
has_attached_file = options[:has_attached_file_name] || :attachment
|
47
|
+
|
48
|
+
alt = if(options[:alt])
|
49
|
+
options[:alt]
|
50
|
+
else
|
51
|
+
(viewable_record and viewable_record.respond_to? :name) ? viewable_record.name : ""
|
52
|
+
end
|
53
|
+
|
54
|
+
position = (viewable_record and viewable_record.respond_to?(:images)) ? viewable_record.images.length : 0
|
55
|
+
|
56
|
+
file = get_file(attachment_path)
|
57
|
+
|
58
|
+
begin
|
59
|
+
|
60
|
+
image = klass.new(
|
61
|
+
{has_attached_file.to_sym => file, :viewable => viewable_record, :alt => alt, :position => position},
|
62
|
+
:without_protection => true
|
63
|
+
)
|
64
|
+
|
65
|
+
#image.attachment.reprocess! not sure this is required anymore
|
66
|
+
|
67
|
+
puts image.save ? "Success: Created Image: #{image.id} : #{image.attachment_file_name}" : "ERROR : Problem saving to DB Image: #{image.inspect}"
|
68
|
+
rescue => e
|
69
|
+
puts "PaperClip error - Problem creating an Image from : #{attachment_path}"
|
70
|
+
puts e.inspect, e.backtrace
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
end
|
@@ -4,58 +4,24 @@
|
|
4
4
|
# License:: MIT. Free, Open Source.
|
5
5
|
#
|
6
6
|
require 'loader_base'
|
7
|
+
require 'paperclip/image_loader'
|
7
8
|
|
8
9
|
module DataShift
|
9
10
|
|
10
11
|
|
11
|
-
module
|
12
|
+
module DataShift::SpreeImageLoading
|
12
13
|
|
13
14
|
include DataShift::Logging
|
15
|
+
include DataShift::ImageLoading
|
14
16
|
|
15
|
-
def get_file( attachment_path )
|
16
|
-
|
17
|
-
unless File.exists?(attachment_path) && File.readable?(attachment_path)
|
18
|
-
logger.error("Cannot process Image from #{Dir.pwd}: Invalid Path #{attachment_path}")
|
19
|
-
raise "Cannot process Image : Invalid Path #{attachment_path}"
|
20
|
-
end
|
21
|
-
|
22
|
-
file = begin
|
23
|
-
File.new(attachment_path, "rb")
|
24
|
-
rescue => e
|
25
|
-
puts e.inspect
|
26
|
-
raise "ERROR : Failed to read image #{attachment_path}"
|
27
|
-
end
|
28
|
-
|
29
|
-
file
|
30
|
-
end
|
31
|
-
|
32
17
|
# Note the Spree Image model sets default storage path to
|
33
18
|
# => :path => ":rails_root/public/assets/products/:id/:style/:basename.:extension"
|
34
19
|
|
35
20
|
def create_image(klass, attachment_path, viewable_record = nil, options = {})
|
36
|
-
|
37
|
-
alt = if(options[:alt])
|
38
|
-
options[:alt]
|
39
|
-
else
|
40
|
-
(viewable_record and viewable_record.respond_to? :name) ? viewable_record.name : ""
|
41
|
-
end
|
42
|
-
|
43
|
-
position = (viewable_record and viewable_record.respond_to?(:images)) ? viewable_record.images.length : 0
|
44
|
-
|
45
|
-
file = get_file(attachment_path)
|
46
|
-
|
47
|
-
if(SpreeHelper::version.to_f > 1 && viewable_record.is_a?(Spree::Product) )
|
48
|
-
|
49
|
-
image = klass.new( :attachment => file, :alt => alt, :position => position)
|
50
21
|
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
image = klass.new( :attachment => file,:viewable => viewable_record, :alt => alt, :position => position)
|
55
|
-
end
|
56
|
-
#image.attachment.reprocess!
|
57
|
-
|
58
|
-
puts image.save ? "Success: Created Image: #{image.inspect}" : "ERROR : Problem saving to DB Image: #{image.inspect}"
|
22
|
+
viewable = (SpreeHelper::version.to_f > 1 && viewable_record.is_a?(Spree::Product) ) ? viewable_record.master : viewable_record
|
23
|
+
|
24
|
+
super(klass, attachment_path, viewable, options)
|
59
25
|
end
|
60
26
|
end
|
61
27
|
|
@@ -64,12 +30,15 @@ module DataShift
|
|
64
30
|
# TODO - extract this out of SpreeHelper to create a general paperclip loader
|
65
31
|
class ImageLoader < LoaderBase
|
66
32
|
|
67
|
-
include DataShift::
|
33
|
+
include DataShift::SpreeImageLoading
|
68
34
|
include DataShift::CsvLoading
|
69
35
|
include DataShift::ExcelLoading
|
70
36
|
|
71
37
|
def initialize(image = nil, options = {})
|
72
|
-
|
38
|
+
|
39
|
+
opts = options.merge(:load => false) # Don't need operators and no table Spree::Image
|
40
|
+
|
41
|
+
super( SpreeHelper::get_spree_class('Image'), image, opts )
|
73
42
|
|
74
43
|
if(SpreeHelper::version.to_f > 1.0 )
|
75
44
|
@attachment_klazz = DataShift::SpreeHelper::get_spree_class('Variant' )
|