datashift 0.11.1 → 0.12.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/Rakefile +3 -2
- data/VERSION +1 -1
- data/datashift.gemspec +11 -174
- data/lib/datashift/column_packer.rb +64 -0
- data/lib/datashift/delimiters.rb +17 -1
- data/lib/datashift/exceptions.rb +7 -0
- data/lib/datashift/querying.rb +10 -4
- data/lib/loaders/csv_loader.rb +69 -32
- data/lib/loaders/excel_loader.rb +86 -53
- data/lib/loaders/loader_base.rb +32 -18
- data/lib/loaders/paperclip/attachment_loader.rb +11 -8
- data/lib/loaders/paperclip/datashift_paperclip.rb +21 -18
- data/lib/loaders/reporter.rb +48 -0
- data/spec/Gemfile.lock +129 -0
- data/spec/csv_exporter_spec.rb +1 -1
- metadata +121 -191
- data/.document +0 -5
- data/lib/java/poi-3.7/._poi-3.7-20101029.jar5645100390082102460.tmp +0 -0
- data/spec/MissingAttachmentRecords/DEMO_001_ror_bag.jpeg +0 -0
- data/spec/MissingAttachmentRecords/DEMO_002_Powerstation.jpeg +0 -0
- data/spec/MissingAttachmentRecords/DEMO_002_Powerstation.jpg +0 -0
- data/spec/MissingAttachmentRecords/DEMO_003_ror_mug.jpeg +0 -0
- data/spec/MissingAttachmentRecords/DEMO_004_ror_ringer.jpeg +0 -0
- data/spec/fixtures/BadAssociationName.xls +0 -0
- data/spec/fixtures/DemoNegativeTesting.xls +0 -0
- data/spec/fixtures/ProjectsDefaults.yml +0 -29
- data/spec/fixtures/ProjectsMultiCategories.xls +0 -0
- data/spec/fixtures/ProjectsMultiCategoriesHeaderLookup.xls +0 -0
- data/spec/fixtures/ProjectsSingleCategories.xls +0 -0
- data/spec/fixtures/SimpleProjects.xls +0 -0
- data/spec/fixtures/config/database.yml +0 -28
- data/spec/fixtures/db/datashift_test_models_db.sqlite +0 -0
- data/spec/fixtures/db/migrate/20110803201325_create_test_bed.rb +0 -96
- data/spec/fixtures/db/migrate/20121009161700_add_digitals.rb +0 -24
- data/spec/fixtures/images/DEMO_001_ror_bag.jpeg +0 -0
- data/spec/fixtures/images/DEMO_002_Powerstation.jpeg +0 -0
- data/spec/fixtures/images/DEMO_003_ror_mug.jpeg +0 -0
- data/spec/fixtures/images/DEMO_004_ror_ringer.jpeg +0 -0
- data/spec/fixtures/load_datashift.thor +0 -3
- data/spec/fixtures/models/category.rb +0 -7
- data/spec/fixtures/models/digital.rb +0 -14
- data/spec/fixtures/models/empty.rb +0 -2
- data/spec/fixtures/models/loader_release.rb +0 -10
- data/spec/fixtures/models/long_and_complex_table_linked_to_version.rb +0 -6
- data/spec/fixtures/models/milestone.rb +0 -8
- data/spec/fixtures/models/owner.rb +0 -7
- data/spec/fixtures/models/project.rb +0 -26
- data/spec/fixtures/models/version.rb +0 -7
- data/spec/fixtures/simple_export_spec.xls +0 -0
- data/spec/fixtures/simple_template_spec.xls +0 -0
- data/spec/fixtures/test_model_defs.rb +0 -9
- data/spec/rails_sandbox/.gitignore +0 -15
- data/spec/rails_sandbox/Gemfile +0 -40
- data/spec/rails_sandbox/README.rdoc +0 -261
- data/spec/rails_sandbox/Rakefile +0 -7
- data/spec/rails_sandbox/app/assets/images/rails.png +0 -0
- data/spec/rails_sandbox/app/assets/javascripts/application.js +0 -15
- data/spec/rails_sandbox/app/assets/stylesheets/application.css +0 -13
- data/spec/rails_sandbox/app/controllers/application_controller.rb +0 -3
- data/spec/rails_sandbox/app/helpers/application_helper.rb +0 -2
- data/spec/rails_sandbox/app/mailers/.gitkeep +0 -0
- data/spec/rails_sandbox/app/models/.gitkeep +0 -0
- data/spec/rails_sandbox/app/models/category.rb +0 -7
- data/spec/rails_sandbox/app/models/empty.rb +0 -2
- data/spec/rails_sandbox/app/models/loader_release.rb +0 -10
- data/spec/rails_sandbox/app/models/long_and_complex_table_linked_to_version.rb +0 -6
- data/spec/rails_sandbox/app/models/milestone.rb +0 -8
- data/spec/rails_sandbox/app/models/owner.rb +0 -5
- data/spec/rails_sandbox/app/models/project.rb +0 -26
- data/spec/rails_sandbox/app/models/test_model_defs.rb +0 -67
- data/spec/rails_sandbox/app/models/version.rb +0 -7
- data/spec/rails_sandbox/app/views/layouts/application.html.erb +0 -14
- data/spec/rails_sandbox/config.ru +0 -4
- data/spec/rails_sandbox/config/application.rb +0 -62
- data/spec/rails_sandbox/config/boot.rb +0 -6
- data/spec/rails_sandbox/config/database.yml +0 -20
- data/spec/rails_sandbox/config/environment.rb +0 -5
- data/spec/rails_sandbox/config/environments/development.rb +0 -37
- data/spec/rails_sandbox/config/environments/production.rb +0 -67
- data/spec/rails_sandbox/config/environments/test.rb +0 -37
- data/spec/rails_sandbox/config/initializers/backtrace_silencers.rb +0 -7
- data/spec/rails_sandbox/config/initializers/inflections.rb +0 -15
- data/spec/rails_sandbox/config/initializers/mime_types.rb +0 -5
- data/spec/rails_sandbox/config/initializers/secret_token.rb +0 -7
- data/spec/rails_sandbox/config/initializers/session_store.rb +0 -8
- data/spec/rails_sandbox/config/initializers/wrap_parameters.rb +0 -14
- data/spec/rails_sandbox/config/locales/en.yml +0 -5
- data/spec/rails_sandbox/config/routes.rb +0 -58
- data/spec/rails_sandbox/db/migrate/20110803201325_create_test_bed.rb +0 -96
- data/spec/rails_sandbox/db/schema.rb +0 -81
- data/spec/rails_sandbox/db/seeds.rb +0 -7
- data/spec/rails_sandbox/lib/assets/.gitkeep +0 -0
- data/spec/rails_sandbox/lib/tasks/.gitkeep +0 -0
- data/spec/rails_sandbox/log/.gitkeep +0 -0
- data/spec/rails_sandbox/public/404.html +0 -26
- data/spec/rails_sandbox/public/422.html +0 -26
- data/spec/rails_sandbox/public/500.html +0 -25
- data/spec/rails_sandbox/public/favicon.ico +0 -0
- data/spec/rails_sandbox/public/index.html +0 -241
- data/spec/rails_sandbox/public/robots.txt +0 -5
- data/spec/rails_sandbox/script/rails +0 -6
- data/spec/rails_sandbox/test/fixtures/.gitkeep +0 -0
- data/spec/rails_sandbox/test/functional/.gitkeep +0 -0
- data/spec/rails_sandbox/test/integration/.gitkeep +0 -0
- data/spec/rails_sandbox/test/performance/browsing_test.rb +0 -12
- data/spec/rails_sandbox/test/test_helper.rb +0 -13
- data/spec/rails_sandbox/test/unit/.gitkeep +0 -0
- data/spec/rails_sandbox/vendor/assets/javascripts/.gitkeep +0 -0
- data/spec/rails_sandbox/vendor/assets/stylesheets/.gitkeep +0 -0
- data/spec/rails_sandbox/vendor/plugins/.gitkeep +0 -0
data/lib/loaders/excel_loader.rb
CHANGED
|
@@ -22,6 +22,8 @@ module DataShift
|
|
|
22
22
|
module ExcelLoading
|
|
23
23
|
|
|
24
24
|
# Options:
|
|
25
|
+
# [:dummy] : Perform a dummy run - attempt to load everything but then roll back
|
|
26
|
+
#
|
|
25
27
|
# [:sheet_number] : Default is 0. The index of the Excel Worksheet to use.
|
|
26
28
|
# [:header_row] : Default is 0. Use alternative row as header definition.
|
|
27
29
|
#
|
|
@@ -72,77 +74,108 @@ module DataShift
|
|
|
72
74
|
|
|
73
75
|
logger.info "Excel Loader processing #{@sheet.num_rows} rows"
|
|
74
76
|
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
77
|
+
@reporter.reset
|
|
78
|
+
|
|
79
|
+
begin
|
|
80
|
+
puts "Dummy Run - Changes will be rolled back" if options[:dummy]
|
|
81
|
+
|
|
82
|
+
load_object_class.transaction do
|
|
78
83
|
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
84
|
+
@sheet.each_with_index do |row, i|
|
|
85
|
+
|
|
86
|
+
@current_row = row
|
|
87
|
+
|
|
88
|
+
next if(i == header_row_index)
|
|
82
89
|
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
contains_data = false
|
|
90
|
+
# Excel num_rows seems to return all 'visible' rows, which appears to be greater than the actual data rows
|
|
91
|
+
# (TODO - write spec to process .xls with a huge number of rows)
|
|
92
|
+
#
|
|
93
|
+
# This is rubbish but currently manually detect when actual data ends, this isn't very smart but
|
|
94
|
+
# got no better idea than ending once we hit the first completely empty row
|
|
95
|
+
break if @current_row.nil?
|
|
91
96
|
|
|
92
|
-
|
|
93
|
-
|
|
97
|
+
logger.info "Processing Row #{i} : #{@current_row}"
|
|
98
|
+
|
|
99
|
+
contains_data = false
|
|
100
|
+
|
|
101
|
+
begin
|
|
102
|
+
# First assign any default values for columns not included in parsed_file
|
|
103
|
+
process_missing_columns_with_defaults
|
|
94
104
|
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
105
|
+
# TODO - Smart sorting of column processing order ....
|
|
106
|
+
# Does not currently ensure mandatory columns (for valid?) processed first but model needs saving
|
|
107
|
+
# before associations can be processed so user should ensure mandatory columns are prior to associations
|
|
98
108
|
|
|
99
|
-
|
|
100
|
-
|
|
109
|
+
# as part of this we also attempt to save early, for example before assigning to
|
|
110
|
+
# has_and_belongs_to associations which require the load_object has an id for the join table
|
|
101
111
|
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
112
|
+
# Iterate over method_details, working on data out of associated Excel column
|
|
113
|
+
@method_mapper.method_details.each do |method_detail|
|
|
114
|
+
|
|
115
|
+
next unless method_detail # TODO populate unmapped with a real MethodDetail that is 'null' and create is_nil
|
|
106
116
|
|
|
107
|
-
|
|
117
|
+
logger.info "Processing Column #{method_detail.column_index}"
|
|
118
|
+
|
|
119
|
+
value = @current_row[method_detail.column_index]
|
|
108
120
|
|
|
109
|
-
|
|
121
|
+
contains_data = true unless(value.nil? || value.to_s.empty?)
|
|
110
122
|
|
|
111
|
-
|
|
123
|
+
prepare_data(method_detail, value)
|
|
112
124
|
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
125
|
+
process()
|
|
126
|
+
end
|
|
127
|
+
|
|
128
|
+
rescue => e
|
|
129
|
+
@reporter.processed_object_count += 1
|
|
130
|
+
|
|
131
|
+
failure(@current_row, true)
|
|
132
|
+
logger.error "Failed to process row [#{i}] (#{@current_row})"
|
|
133
|
+
# don't forget to reset the load object
|
|
134
|
+
new_load_object
|
|
135
|
+
next
|
|
136
|
+
end
|
|
137
|
+
|
|
138
|
+
break unless(contains_data == true)
|
|
139
|
+
|
|
140
|
+
# currently here as we can only identify the end of a speadsheet by first empty row
|
|
141
|
+
@reporter.processed_object_count += 1
|
|
142
|
+
|
|
143
|
+
# TODO - make optional - all or nothing or carry on and dump out the exception list at end
|
|
128
144
|
|
|
129
|
-
|
|
130
|
-
|
|
145
|
+
unless(save)
|
|
146
|
+
failure
|
|
147
|
+
logger.error "Failed to save row [#{@current_row}]"
|
|
148
|
+
logger.error load_object.errors.inspect if(load_object)
|
|
149
|
+
else
|
|
150
|
+
logger.info "Row #{@current_row} succesfully SAVED : ID #{load_object.id}"
|
|
151
|
+
@reporter.add_loaded_object(@load_object)
|
|
152
|
+
end
|
|
153
|
+
|
|
154
|
+
# don't forget to reset the object or we'll update rather than create
|
|
155
|
+
new_load_object
|
|
131
156
|
|
|
157
|
+
end
|
|
158
|
+
|
|
159
|
+
raise ActiveRecord::Rollback if(options[:dummy]) # Don't actually create/upload to DB if we are doing dummy run
|
|
132
160
|
end
|
|
133
|
-
end
|
|
134
|
-
|
|
135
|
-
loaded_objects.compact! if(loaded_objects)
|
|
136
161
|
|
|
137
|
-
|
|
138
|
-
puts "There were NO failures." if failed_objects.empty?
|
|
162
|
+
rescue => e
|
|
139
163
|
|
|
140
|
-
|
|
164
|
+
if e.is_a?(ActiveRecord::Rollback) && options[:dummy]
|
|
165
|
+
puts "Excel loading stage complete - Dummy run so Rolling Back."
|
|
166
|
+
else
|
|
167
|
+
raise e
|
|
168
|
+
end
|
|
169
|
+
ensure
|
|
170
|
+
report
|
|
171
|
+
end
|
|
172
|
+
|
|
141
173
|
end
|
|
142
|
-
|
|
174
|
+
|
|
143
175
|
def value_at(row, column)
|
|
144
176
|
@excel[row, column]
|
|
145
177
|
end
|
|
178
|
+
|
|
146
179
|
end
|
|
147
180
|
|
|
148
181
|
|
|
@@ -159,7 +192,7 @@ module DataShift
|
|
|
159
192
|
def perform_load( file_name, options = {} )
|
|
160
193
|
perform_excel_load( file_name, options )
|
|
161
194
|
|
|
162
|
-
puts "Excel loading stage complete - #{
|
|
195
|
+
puts "Excel loading stage complete - #{loaded_count} rows added."
|
|
163
196
|
end
|
|
164
197
|
|
|
165
198
|
end
|
data/lib/loaders/loader_base.rb
CHANGED
|
@@ -28,7 +28,7 @@ module DataShift
|
|
|
28
28
|
attr_accessor :load_object_class, :load_object
|
|
29
29
|
attr_accessor :current_value, :current_method_detail
|
|
30
30
|
|
|
31
|
-
attr_accessor :
|
|
31
|
+
attr_accessor :reporter
|
|
32
32
|
|
|
33
33
|
attr_accessor :config, :verbose
|
|
34
34
|
|
|
@@ -51,7 +51,7 @@ module DataShift
|
|
|
51
51
|
|
|
52
52
|
# Gather names of all possible 'setter' methods on AR class (instance variables and associations)
|
|
53
53
|
if((find_operators && !MethodDictionary::for?(object_class)) || options[:reload])
|
|
54
|
-
puts "Building Method Dictionary for class #{object_class}"
|
|
54
|
+
#puts "DEBUG Building Method Dictionary for class #{object_class}"
|
|
55
55
|
DataShift::MethodDictionary.find_operators( @load_object_class, :reload => options[:reload], :instance_methods => options[:instance_methods] )
|
|
56
56
|
|
|
57
57
|
# Create dictionary of data on all possible 'setter' methods which can be used to
|
|
@@ -73,9 +73,7 @@ module DataShift
|
|
|
73
73
|
@prefixes = {}
|
|
74
74
|
@postfixes = {}
|
|
75
75
|
|
|
76
|
-
|
|
77
|
-
@loaded_objects = []
|
|
78
|
-
@failed_objects = []
|
|
76
|
+
@reporter = DataShift::Reporter.new
|
|
79
77
|
|
|
80
78
|
reset(object)
|
|
81
79
|
end
|
|
@@ -88,6 +86,8 @@ module DataShift
|
|
|
88
86
|
#
|
|
89
87
|
# OPTIONS :
|
|
90
88
|
#
|
|
89
|
+
# [:dummy] : Perform a dummy run - attempt to load everything but then roll back
|
|
90
|
+
#
|
|
91
91
|
# strict : Raise an exception of any headers can't be mapped to an attribute/association
|
|
92
92
|
# ignore : List of column headers to ignore when building operator map
|
|
93
93
|
# mandatory : List of columns that must be present in headers
|
|
@@ -100,8 +100,12 @@ module DataShift
|
|
|
100
100
|
|
|
101
101
|
raise DataShift::BadFile, "Cannot load #{file_name} file not found." unless(File.exists?(file_name))
|
|
102
102
|
|
|
103
|
+
logger.info("Perform Load Options:\n#{options.inspect}")
|
|
104
|
+
|
|
103
105
|
ext = File.extname(file_name)
|
|
104
|
-
|
|
106
|
+
|
|
107
|
+
# TODO - make more modular - these methods doing too much, for example move the object creation/reset
|
|
108
|
+
# out of these perform... methods to make it easier to over ride that behaviour
|
|
105
109
|
if(ext.casecmp('.xls') == 0)
|
|
106
110
|
perform_excel_load(file_name, options)
|
|
107
111
|
elsif(ext.casecmp('.csv') == 0)
|
|
@@ -111,7 +115,9 @@ module DataShift
|
|
|
111
115
|
end
|
|
112
116
|
end
|
|
113
117
|
|
|
114
|
-
|
|
118
|
+
def report
|
|
119
|
+
@reporter.report
|
|
120
|
+
end
|
|
115
121
|
|
|
116
122
|
# Core API
|
|
117
123
|
#
|
|
@@ -166,6 +172,7 @@ module DataShift
|
|
|
166
172
|
def process_missing_columns_with_defaults()
|
|
167
173
|
inbound_ops = @method_mapper.operator_names
|
|
168
174
|
@default_values.each do |dn, dv|
|
|
175
|
+
logger.debug "Processing default value #{dn} : #{dv}"
|
|
169
176
|
assignment(dn, @load_object, dv) unless(inbound_ops.include?(dn))
|
|
170
177
|
end
|
|
171
178
|
end
|
|
@@ -382,20 +389,27 @@ module DataShift
|
|
|
382
389
|
end
|
|
383
390
|
end
|
|
384
391
|
|
|
385
|
-
|
|
386
|
-
|
|
392
|
+
|
|
393
|
+
# Loading failed. Store a failed object and if requested roll back (destroy) the current load object
|
|
394
|
+
# For use case where object saved early but subsequent required columns fail to process
|
|
395
|
+
# so the load object is invalid
|
|
396
|
+
|
|
397
|
+
def failure( object = @load_object, rollback = false)
|
|
398
|
+
if(object)
|
|
399
|
+
@reporter.add_failed_object(object)
|
|
400
|
+
|
|
401
|
+
@load_object.destroy if(rollback && ! @load_object.new_record?)
|
|
402
|
+
|
|
403
|
+
new_load_object # don't forget to reset the load object
|
|
404
|
+
end
|
|
387
405
|
end
|
|
388
406
|
|
|
389
407
|
def save
|
|
390
408
|
return unless( @load_object )
|
|
391
409
|
|
|
392
|
-
puts "DEBUG: SAVING #{@load_object.class} : #{@load_object.inspect}" if(@verbose)
|
|
410
|
+
#puts "DEBUG: SAVING #{@load_object.class} : #{@load_object.inspect}" if(@verbose)
|
|
393
411
|
begin
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
@loaded_objects << @load_object unless(@loaded_objects.include?(@load_object))
|
|
397
|
-
|
|
398
|
-
return result
|
|
412
|
+
return @load_object.save
|
|
399
413
|
rescue => e
|
|
400
414
|
failure
|
|
401
415
|
puts "Error saving #{@load_object.class} : #{e.inspect}"
|
|
@@ -447,7 +461,7 @@ module DataShift
|
|
|
447
461
|
#
|
|
448
462
|
def reset(object = nil)
|
|
449
463
|
@load_object = object || new_load_object
|
|
450
|
-
@
|
|
464
|
+
@reporter.reset
|
|
451
465
|
@current_value = nil
|
|
452
466
|
end
|
|
453
467
|
|
|
@@ -462,11 +476,11 @@ module DataShift
|
|
|
462
476
|
end
|
|
463
477
|
|
|
464
478
|
def loaded_count
|
|
465
|
-
|
|
479
|
+
reporter.loaded_objects.size
|
|
466
480
|
end
|
|
467
481
|
|
|
468
482
|
def failed_count
|
|
469
|
-
|
|
483
|
+
reporter.failed_objects.size
|
|
470
484
|
end
|
|
471
485
|
|
|
472
486
|
|
|
@@ -98,10 +98,14 @@ module DataShift
|
|
|
98
98
|
|
|
99
99
|
# This version creates attachments and also attaches them to instances of :attach_to_klazz
|
|
100
100
|
#
|
|
101
|
+
# Each file found in PATH will be processed - it's filename being used to scan for
|
|
102
|
+
# a matching record to attach the file to.
|
|
103
|
+
#
|
|
101
104
|
# Options
|
|
102
105
|
# :split_file_name_on Used in scan process to progresivly split filename to find
|
|
103
106
|
# :attach_to_klass with matching :attach_to_find_by_field
|
|
104
107
|
#
|
|
108
|
+
# :add_prefix
|
|
105
109
|
#
|
|
106
110
|
def process_from_filesystem(path, options = {} )
|
|
107
111
|
|
|
@@ -135,12 +139,11 @@ module DataShift
|
|
|
135
139
|
|
|
136
140
|
record = nil
|
|
137
141
|
|
|
138
|
-
puts "Attempting
|
|
142
|
+
puts "Attempting fo find Record for file name : #{base_name}"
|
|
139
143
|
record = get_record_by(attach_to_klass, attach_to_find_by_field, base_name, split_on, options)
|
|
140
144
|
|
|
141
145
|
if(record)
|
|
142
|
-
puts "Found record
|
|
143
|
-
logger.info "Found record for attachment : #{record.inspect}"
|
|
146
|
+
puts "Found #{record.class} where : #{attach_to_find_by_field} = #{record.send(attach_to_find_by_field)}(id : #{record.id})"
|
|
144
147
|
else
|
|
145
148
|
missing_records << file_name
|
|
146
149
|
end
|
|
@@ -162,15 +165,15 @@ module DataShift
|
|
|
162
165
|
FileUtils.mkdir_p('MissingAttachmentRecords') unless File.directory?('MissingAttachmentRecords')
|
|
163
166
|
|
|
164
167
|
puts "WARNING : #{missing_records.size} of #{loading_files_cache.size} files could not be attached to a #{@load_object_class}"
|
|
165
|
-
puts "For your convenience files with MISSING #{attach_to_klass}
|
|
166
|
-
missing_records.each do |i|
|
|
167
|
-
puts "Copying #{i} to MissingAttachmentRecords folder" if(options[:verbose])
|
|
168
|
+
puts "For your convenience copying files with MISSING #{attach_to_klass} to : MissingAttachmentRecords"
|
|
169
|
+
missing_records.each do |i|
|
|
168
170
|
FileUtils.cp( i, 'MissingAttachmentRecords') unless(options[:dummy] == 'true')
|
|
171
|
+
puts "Copyied #{i} to MissingAttachmentRecords folder" if(options[:verbose])
|
|
169
172
|
end
|
|
170
|
-
else
|
|
171
|
-
puts "Created #{loading_files_cache.size} #{@load_object_class} attachments and succesfully attached to a #{@attach_to_klass}"
|
|
172
173
|
end
|
|
173
174
|
|
|
175
|
+
puts "Created #{loading_files_cache.size - missing_records.size} of #{loading_files_cache.size} #{@load_object_class} attachments and succesfully attached to a #{@attach_to_klass}"
|
|
176
|
+
|
|
174
177
|
puts "Dummy Run Complete- if happy run without -d" if(options[:dummy])
|
|
175
178
|
|
|
176
179
|
end
|
|
@@ -13,7 +13,7 @@ module DataShift
|
|
|
13
13
|
module Paperclip
|
|
14
14
|
|
|
15
15
|
include DataShift::Logging
|
|
16
|
-
|
|
16
|
+
|
|
17
17
|
require 'paperclip/attachment_loader'
|
|
18
18
|
|
|
19
19
|
attr_accessor :attachment
|
|
@@ -34,14 +34,14 @@ module DataShift
|
|
|
34
34
|
|
|
35
35
|
unless File.exists?(attachment_path) && File.readable?(attachment_path)
|
|
36
36
|
logger.error("Cannot process Image from #{Dir.pwd}: Invalid Path #{attachment_path}")
|
|
37
|
-
raise "Cannot process Image : Invalid Path #{attachment_path}"
|
|
37
|
+
raise PathError.new("Cannot process Image : Invalid Path #{attachment_path}")
|
|
38
38
|
end
|
|
39
39
|
|
|
40
40
|
file = begin
|
|
41
41
|
File.new(attachment_path, "rb")
|
|
42
42
|
rescue => e
|
|
43
43
|
puts e.inspect
|
|
44
|
-
raise "ERROR : Failed to read image #{attachment_path}"
|
|
44
|
+
raise PathError.new("ERROR : Failed to read image from #{attachment_path}")
|
|
45
45
|
end
|
|
46
46
|
|
|
47
47
|
file
|
|
@@ -54,11 +54,13 @@ module DataShift
|
|
|
54
54
|
#
|
|
55
55
|
# :attributes
|
|
56
56
|
#
|
|
57
|
-
# Pass through hash of attributes to klass initializer
|
|
57
|
+
# Pass through a hash of attributes to the Paperclip klass's initializer
|
|
58
58
|
#
|
|
59
59
|
# :has_attached_file_name
|
|
60
60
|
#
|
|
61
61
|
# Paperclip attachment name defined with macro 'has_attached_file :name'
|
|
62
|
+
#
|
|
63
|
+
# This is usually called/defaults :attachment
|
|
62
64
|
#
|
|
63
65
|
# e.g
|
|
64
66
|
# When : has_attached_file :avatar
|
|
@@ -73,19 +75,21 @@ module DataShift
|
|
|
73
75
|
|
|
74
76
|
has_attached_file_attribute = options[:has_attached_file_name] ? options[:has_attached_file_name].to_sym : :attachment
|
|
75
77
|
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
78
|
+
# e.g (:attachment => File.read)
|
|
79
|
+
paperclip_attributes = { has_attached_file_attribute => get_file(attachment_path) }
|
|
80
|
+
|
|
81
|
+
paperclip_attributes.merge!(options[:attributes]) if(options[:attributes])
|
|
79
82
|
|
|
80
|
-
|
|
83
|
+
begin
|
|
84
|
+
@attachment = klass.new(paperclip_attributes, :without_protection => true)
|
|
85
|
+
rescue => e
|
|
86
|
+
puts e.inspect
|
|
87
|
+
logger.error("Failed to create PaperClip Attachment : #{e.inspect}")
|
|
88
|
+
raise CreateAttachmentFailed.new("Failed to create PaperClip Attachment from : #{attachment_path}")
|
|
89
|
+
end
|
|
81
90
|
|
|
82
|
-
#attributes.merge!(attach_to_record_field.to_sym => record) if(record && attach_to_record_field)
|
|
83
|
-
|
|
84
|
-
puts attributes.inspect
|
|
85
91
|
begin
|
|
86
92
|
|
|
87
|
-
@attachment = klass.new(attributes, :without_protection => true)
|
|
88
|
-
|
|
89
93
|
if(@attachment.save)
|
|
90
94
|
puts "Success: Created Attachment #{@attachment.id} : #{@attachment.attachment_file_name}"
|
|
91
95
|
|
|
@@ -103,12 +107,11 @@ module DataShift
|
|
|
103
107
|
|
|
104
108
|
@attachment
|
|
105
109
|
rescue => e
|
|
106
|
-
|
|
107
|
-
puts e.inspect
|
|
110
|
+
logger.error("Problem saving Paperclip Attachment: #{e.inspect}")
|
|
111
|
+
puts e.inspect
|
|
112
|
+
raise CreateAttachmentFailed.new("PaperClip error - Problem saving Attachment")
|
|
108
113
|
end
|
|
109
|
-
end
|
|
110
|
-
|
|
114
|
+
end
|
|
111
115
|
end
|
|
112
116
|
|
|
113
|
-
|
|
114
117
|
end
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
# Copyright:: (c) Autotelik Media Ltd 2011
|
|
2
|
+
# Author :: Tom Statter
|
|
3
|
+
# Date :: Dec 2012
|
|
4
|
+
# License:: MIT
|
|
5
|
+
#
|
|
6
|
+
# Details:: Store and report stats
|
|
7
|
+
#
|
|
8
|
+
module DataShift
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
class Reporter
|
|
12
|
+
|
|
13
|
+
include DataShift::Logging
|
|
14
|
+
|
|
15
|
+
attr_accessor :processed_object_count, :loaded_objects, :failed_objects
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
def initialize()
|
|
19
|
+
reset
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def reset()
|
|
23
|
+
@processed_object_count = 0
|
|
24
|
+
@loaded_objects, @failed_objects = [], []
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def add_loaded_object(object)
|
|
28
|
+
@loaded_objects << object unless(object.nil? || @loaded_objects.include?(object))
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def add_failed_object(object)
|
|
32
|
+
@failed_objects << object unless( object.nil? || @failed_objects.include?(object))
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def report
|
|
36
|
+
loaded_objects.compact! if(loaded_objects)
|
|
37
|
+
|
|
38
|
+
puts "Processing complete:"
|
|
39
|
+
puts "Processed total of #{processed_object_count} entries"
|
|
40
|
+
puts "#{loaded_objects.size} objects were succesfully processed."
|
|
41
|
+
|
|
42
|
+
puts "There were NO failures." if failed_objects.empty?
|
|
43
|
+
|
|
44
|
+
puts "WARNING : Check logs : #{failed_objects.size} rows contained errors and #{failed_objects.size} records NOT created." unless failed_objects.empty?
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
end
|
|
48
|
+
end
|