datashift 0.9.0 → 0.10.0
Sign up to get free protection for your applications and to get access to all the features.
- data/README.markdown +63 -64
- data/Rakefile +4 -7
- data/VERSION +1 -1
- data/datashift.gemspec +92 -62
- data/lib/applications/apache_poi_extensions.rb +62 -0
- data/lib/applications/excel.rb +78 -0
- data/lib/applications/excel_base.rb +65 -0
- data/lib/applications/jexcel_file.rb +222 -0
- data/lib/applications/jexcel_file_extensions.rb +244 -0
- data/lib/applications/jruby/{jexcel_file.rb → old_pre_proxy_jexcel_file.rb} +0 -0
- data/lib/applications/ruby_poi_translations.rb +64 -0
- data/lib/applications/spreadsheet_extensions.rb +31 -0
- data/lib/datashift/method_details_manager.rb +4 -0
- data/lib/exporters/csv_exporter.rb +3 -1
- data/lib/exporters/excel_exporter.rb +59 -74
- data/lib/generators/excel_generator.rb +70 -74
- data/lib/guards.rb +57 -0
- data/lib/loaders/excel_loader.rb +105 -105
- data/lib/loaders/loader_base.rb +43 -21
- data/lib/loaders/paperclip/attachment_loader.rb +104 -0
- data/lib/loaders/paperclip/datashift_paperclip.rb +78 -0
- data/lib/loaders/paperclip/{image_loader.rb → image_loading.rb} +2 -18
- data/lib/thor/{generate_excel.thor → generate.thor} +48 -0
- data/lib/thor/paperclip.thor +85 -0
- data/lib/thor/tools.thor +23 -2
- data/spec/Gemfile +1 -7
- data/spec/csv_exporter_spec.rb +4 -4
- data/spec/csv_loader_spec.rb +1 -1
- data/spec/excel_exporter_spec.rb +43 -45
- data/spec/excel_generator_spec.rb +132 -60
- data/spec/excel_loader_spec.rb +134 -140
- data/spec/excel_spec.rb +179 -0
- data/spec/fixtures/ProjectsMultiCategoriesHeaderLookup.xls +0 -0
- data/spec/fixtures/config/database.yml +2 -2
- data/spec/fixtures/db/datashift_test_models_db.sqlite +0 -0
- data/spec/{db → fixtures/db}/migrate/20110803201325_create_test_bed.rb +0 -0
- data/spec/fixtures/load_datashift.thor +3 -0
- data/spec/fixtures/models/category.rb +7 -0
- data/spec/fixtures/models/empty.rb +2 -0
- data/spec/fixtures/models/loader_release.rb +10 -0
- data/spec/fixtures/models/long_and_complex_table_linked_to_version.rb +6 -0
- data/spec/fixtures/models/milestone.rb +8 -0
- data/spec/fixtures/models/owner.rb +5 -0
- data/spec/fixtures/models/project.rb +26 -0
- data/spec/fixtures/models/test_model_defs.rb +67 -0
- data/spec/fixtures/models/version.rb +7 -0
- data/spec/loader_spec.rb +4 -3
- data/spec/method_dictionary_spec.rb +7 -6
- data/spec/method_mapper_spec.rb +3 -2
- data/spec/rails_sandbox/.gitignore +15 -0
- data/spec/rails_sandbox/Gemfile +40 -0
- data/spec/rails_sandbox/README.rdoc +261 -0
- data/spec/rails_sandbox/Rakefile +7 -0
- data/spec/rails_sandbox/app/assets/images/rails.png +0 -0
- data/spec/rails_sandbox/app/assets/javascripts/application.js +15 -0
- data/spec/rails_sandbox/app/assets/stylesheets/application.css +13 -0
- data/spec/rails_sandbox/app/controllers/application_controller.rb +3 -0
- data/spec/rails_sandbox/app/helpers/application_helper.rb +2 -0
- 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 +7 -0
- data/spec/rails_sandbox/app/models/empty.rb +2 -0
- data/spec/rails_sandbox/app/models/loader_release.rb +10 -0
- data/spec/rails_sandbox/app/models/long_and_complex_table_linked_to_version.rb +6 -0
- data/spec/rails_sandbox/app/models/milestone.rb +8 -0
- data/spec/rails_sandbox/app/models/owner.rb +5 -0
- data/spec/rails_sandbox/app/models/project.rb +26 -0
- data/spec/rails_sandbox/app/models/test_model_defs.rb +67 -0
- data/spec/rails_sandbox/app/models/version.rb +7 -0
- data/spec/rails_sandbox/app/views/layouts/application.html.erb +14 -0
- data/spec/rails_sandbox/config.ru +4 -0
- data/spec/rails_sandbox/config/application.rb +62 -0
- data/spec/rails_sandbox/config/boot.rb +6 -0
- data/spec/rails_sandbox/config/database.yml +20 -0
- data/spec/rails_sandbox/config/environment.rb +5 -0
- data/spec/rails_sandbox/config/environments/development.rb +37 -0
- data/spec/rails_sandbox/config/environments/production.rb +67 -0
- data/spec/rails_sandbox/config/environments/test.rb +37 -0
- data/spec/rails_sandbox/config/initializers/backtrace_silencers.rb +7 -0
- data/spec/rails_sandbox/config/initializers/inflections.rb +15 -0
- data/spec/rails_sandbox/config/initializers/mime_types.rb +5 -0
- data/spec/rails_sandbox/config/initializers/secret_token.rb +7 -0
- data/spec/rails_sandbox/config/initializers/session_store.rb +8 -0
- data/spec/rails_sandbox/config/initializers/wrap_parameters.rb +14 -0
- data/spec/rails_sandbox/config/locales/en.yml +5 -0
- data/spec/rails_sandbox/config/routes.rb +58 -0
- data/spec/rails_sandbox/db/migrate/20110803201325_create_test_bed.rb +96 -0
- data/spec/rails_sandbox/db/schema.rb +81 -0
- data/spec/rails_sandbox/db/seeds.rb +7 -0
- 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 +26 -0
- data/spec/rails_sandbox/public/422.html +26 -0
- data/spec/rails_sandbox/public/500.html +25 -0
- data/spec/rails_sandbox/public/favicon.ico +0 -0
- data/spec/rails_sandbox/public/index.html +241 -0
- data/spec/rails_sandbox/public/robots.txt +5 -0
- data/spec/rails_sandbox/script/rails +6 -0
- 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 +12 -0
- data/spec/rails_sandbox/test/test_helper.rb +13 -0
- 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/spec/spec_helper.rb +144 -121
- data/spec/thor_spec.rb +34 -14
- metadata +207 -194
- data/lib/helpers/spree_helper.rb +0 -213
- data/lib/loaders/spreadsheet_loader.rb +0 -144
- data/lib/loaders/spree/image_loader.rb +0 -90
- data/lib/loaders/spree/product_loader.rb +0 -354
- data/lib/thor/spree/bootstrap_cleanup.thor +0 -61
- data/lib/thor/spree/products_images.thor +0 -252
- data/lib/thor/spree/reports.thor +0 -56
- data/public/spree/products/large/DEMO_001_ror_bag.jpeg +0 -0
- data/public/spree/products/large/DEMO_002_Powerstation.jpg +0 -0
- data/public/spree/products/large/DEMO_003_ror_mug.jpeg +0 -0
- data/public/spree/products/mini/DEMO_001_ror_bag.jpeg +0 -0
- data/public/spree/products/mini/DEMO_002_Powerstation.jpg +0 -0
- data/public/spree/products/mini/DEMO_003_ror_mug.jpeg +0 -0
- data/public/spree/products/original/DEMO_001_ror_bag.jpeg +0 -0
- data/public/spree/products/original/DEMO_002_Powerstation.jpg +0 -0
- data/public/spree/products/original/DEMO_003_ror_mug.jpeg +0 -0
- data/public/spree/products/product/DEMO_001_ror_bag.jpeg +0 -0
- data/public/spree/products/product/DEMO_002_Powerstation.jpg +0 -0
- data/public/spree/products/product/DEMO_003_ror_mug.jpeg +0 -0
- data/public/spree/products/small/DEMO_001_ror_bag.jpeg +0 -0
- data/public/spree/products/small/DEMO_002_Powerstation.jpg +0 -0
- data/public/spree/products/small/DEMO_003_ror_mug.jpeg +0 -0
- data/spec/fixtures/datashift_Spree_db.sqlite +0 -0
- data/spec/fixtures/datashift_test_models_db.sqlite +0 -0
- data/spec/fixtures/negative/SpreeProdMiss1Mandatory.csv +0 -4
- data/spec/fixtures/negative/SpreeProdMiss1Mandatory.xls +0 -0
- data/spec/fixtures/negative/SpreeProdMissManyMandatory.csv +0 -4
- data/spec/fixtures/negative/SpreeProdMissManyMandatory.xls +0 -0
- data/spec/fixtures/spree/SpreeImages.xls +0 -0
- data/spec/fixtures/spree/SpreeMultiVariant.csv +0 -4
- data/spec/fixtures/spree/SpreeProducts.csv +0 -4
- data/spec/fixtures/spree/SpreeProducts.xls +0 -0
- data/spec/fixtures/spree/SpreeProductsDefaults.yml +0 -15
- data/spec/fixtures/spree/SpreeProductsMandatoryOnly.xls +0 -0
- data/spec/fixtures/spree/SpreeProductsMultiColumn.csv +0 -4
- data/spec/fixtures/spree/SpreeProductsMultiColumn.xls +0 -0
- data/spec/fixtures/spree/SpreeProductsSimple.csv +0 -4
- data/spec/fixtures/spree/SpreeProductsSimple.xls +0 -0
- data/spec/fixtures/spree/SpreeProductsWithImages.csv +0 -4
- data/spec/fixtures/spree/SpreeProductsWithImages.xls +0 -0
- data/spec/fixtures/spree/SpreeZoneExample.csv +0 -5
- data/spec/fixtures/spree/SpreeZoneExample.xls +0 -0
- data/spec/spree_exporter_spec.rb +0 -72
- data/spec/spree_generator_spec.rb +0 -96
- data/spec/spree_images_loader_spec.rb +0 -107
- data/spec/spree_loader_spec.rb +0 -375
- data/spec/spree_method_mapping_spec.rb +0 -226
- data/spec/spree_variants_loader_spec.rb +0 -189
- data/tasks/export/excel_generator.rake +0 -102
- data/tasks/import/excel.rake +0 -75
- data/test/helper.rb +0 -18
- data/test/test_interact.rb +0 -7
data/lib/guards.rb
ADDED
@@ -0,0 +1,57 @@
|
|
1
|
+
# Copyright:: (c) Autotelik Media Ltd 2010 - 2012 Tom Statter
|
2
|
+
# Author :: Tom Statter
|
3
|
+
# Date :: Aug 2010
|
4
|
+
# License:: Free, Open Source.
|
5
|
+
#
|
6
|
+
# Permission is hereby granted, free of charge, to any person obtaining
|
7
|
+
# a copy of this software and associated documentation files (the
|
8
|
+
# "Software"), to deal in the Software without restriction, including
|
9
|
+
# without limitation the rights to use, copy, modify, merge, publish,
|
10
|
+
# distribute, sublicense, and/or sell copies of the Software, and to
|
11
|
+
# permit persons to whom the Software is furnished to do so, subject to
|
12
|
+
# the following conditions:
|
13
|
+
#
|
14
|
+
# The above copyright notice and this permission notice shall be
|
15
|
+
# included in all copies or substantial portions of the Software.
|
16
|
+
#
|
17
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
18
|
+
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
19
|
+
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
20
|
+
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
21
|
+
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
22
|
+
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
23
|
+
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
24
|
+
#++
|
25
|
+
|
26
|
+
|
27
|
+
# Details:: Active Record Loader
|
28
|
+
#
|
29
|
+
# To pull DataShift commands into your main application :
|
30
|
+
#
|
31
|
+
# require 'datashift'
|
32
|
+
#
|
33
|
+
# DataShift::load_commands
|
34
|
+
#
|
35
|
+
require 'rbconfig'
|
36
|
+
|
37
|
+
module DataShift
|
38
|
+
|
39
|
+
module Guards
|
40
|
+
|
41
|
+
def self.jruby?
|
42
|
+
return RUBY_PLATFORM == "java"
|
43
|
+
end
|
44
|
+
def self.mac?
|
45
|
+
RbConfig::CONFIG['target_os'] =~ /darwin/i
|
46
|
+
end
|
47
|
+
|
48
|
+
def self.linux?
|
49
|
+
RbConfig::CONFIG['target_os'] =~ /linux/i
|
50
|
+
end
|
51
|
+
|
52
|
+
def self.windows?
|
53
|
+
RbConfig::CONFIG['target_os'] =~ /mswin|mingw/i
|
54
|
+
end
|
55
|
+
|
56
|
+
end
|
57
|
+
end
|
data/lib/loaders/excel_loader.rb
CHANGED
@@ -15,149 +15,149 @@ require 'datashift/exceptions'
|
|
15
15
|
|
16
16
|
module DataShift
|
17
17
|
|
18
|
-
|
18
|
+
require 'loaders/loader_base'
|
19
19
|
|
20
|
-
|
20
|
+
require 'excel'
|
21
21
|
|
22
|
-
|
23
|
-
require 'jexcel_file'
|
22
|
+
module ExcelLoading
|
24
23
|
|
25
|
-
|
24
|
+
# Options:
|
25
|
+
# [:sheet_number] : Default is 0. The index of the Excel Worksheet to use.
|
26
|
+
# [:header_row] : Default is 0. Use alternative row as header definition.
|
27
|
+
# [:mandatory] : Array of mandatory column names
|
28
|
+
# [:force_inclusion] : Array of inbound column names to force into mapping
|
29
|
+
# [:strict] : Raise exception when no mapping found for a column heading (non mandatory)
|
26
30
|
|
27
|
-
|
28
|
-
# [:sheet_number] : Default is 0. The index of the Excel Worksheet to use.
|
29
|
-
# [:header_row] : Default is 0. Use alternative row as header definition.
|
30
|
-
# [:mandatory] : Array of mandatory column names
|
31
|
-
# [:force_inclusion] : Array of inbound column names to force into mapping
|
32
|
-
# [:strict] : Raise exception when no mapping found for a column heading (non mandatory)
|
31
|
+
def perform_excel_load( file_name, options = {} )
|
33
32
|
|
33
|
+
raise MissingHeadersError, "Minimum row for Headers is 0 - passed #{options[:header_row]}" if(options[:header_row] && options[:header_row].to_i < 0)
|
34
|
+
|
35
|
+
@excel = Excel.new
|
34
36
|
|
35
|
-
|
36
|
-
|
37
|
-
@excel = JExcelFile.new
|
38
|
-
|
39
|
-
@excel.open(file_name)
|
37
|
+
@excel.open(file_name)
|
40
38
|
|
41
|
-
|
42
|
-
|
39
|
+
#if(options[:verbose])
|
40
|
+
puts "\n\n\nLoading from Excel file: #{file_name}"
|
43
41
|
|
44
|
-
|
42
|
+
sheet_number = options[:sheet_number] || 0
|
45
43
|
|
46
|
-
|
44
|
+
|
45
|
+
@sheet = @excel.worksheet( sheet_number )
|
47
46
|
|
48
|
-
|
49
|
-
|
47
|
+
header_row_index = options[:header_row] || 0
|
48
|
+
@header_row = @sheet.row(header_row_index)
|
50
49
|
|
51
|
-
|
50
|
+
raise MissingHeadersError, "No headers found - Check Sheet #{@sheet} is complete and Row #{header_row_index} contains headers" unless(@header_row)
|
52
51
|
|
53
|
-
|
54
|
-
|
55
|
-
(0..JExcelFile::MAX_COLUMNS).each do |i|
|
56
|
-
cell = @header_row.getCell(i)
|
57
|
-
break unless cell
|
58
|
-
header = "#{@excel.cell_value(cell).to_s}".strip
|
59
|
-
break if header.empty?
|
60
|
-
@headers << header
|
61
|
-
end
|
52
|
+
@headers = []
|
62
53
|
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
54
|
+
# TODO - make more robust - currently end on first empty column
|
55
|
+
# There is no actual max columns in Excel .. you will run out of memory though at some point
|
56
|
+
(0..1024).each do |column|
|
57
|
+
cell = @header_row[column]
|
58
|
+
break unless cell
|
59
|
+
header = "#{cell.to_s}".strip
|
60
|
+
break if header.empty?
|
61
|
+
@headers << header
|
62
|
+
end
|
72
63
|
|
73
|
-
|
64
|
+
raise MissingHeadersError, "No headers found - Check Sheet #{@sheet} is complete and Row #{header_row_index} contains headers" if(@headers.empty?)
|
74
65
|
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
# got no better idea than ending once we hit the first completely empty row
|
80
|
-
break if @excel.sheet.getRow(row).nil?
|
66
|
+
|
67
|
+
# Create a method_mapper which maps list of headers into suitable calls on the Active Record class
|
68
|
+
# For example if model has an attribute 'price' will map columns called Price, price, PRICE etc to this attribute
|
69
|
+
map_headers_to_operators( @headers, options )
|
81
70
|
|
82
|
-
|
71
|
+
logger.info "Excel Loader processing #{@sheet.num_rows} rows"
|
72
|
+
|
73
|
+
loaded_objects.clear
|
83
74
|
|
84
|
-
|
85
|
-
|
86
|
-
|
75
|
+
load_object_class.transaction do
|
76
|
+
|
77
|
+
@sheet.each_with_index do |row, i|
|
78
|
+
|
79
|
+
next if(i == header_row_index)
|
80
|
+
|
81
|
+
# Excel num_rows seems to return all 'visible' rows, which appears to be greater than the actual data rows
|
82
|
+
# (TODO - write spec to process .xls with a huge number of rows)
|
83
|
+
#
|
84
|
+
# This is rubbish but currently manually detect when actual data ends, this isn't very smart but
|
85
|
+
# got no better idea than ending once we hit the first completely empty row
|
86
|
+
break if row.nil?
|
87
|
+
|
88
|
+
contains_data = false
|
89
|
+
|
90
|
+
# First assign any default values for columns not included in parsed_file
|
91
|
+
process_missing_columns_with_defaults
|
87
92
|
|
88
|
-
|
89
|
-
|
90
|
-
|
93
|
+
# TODO - Smart sorting of column processing order ....
|
94
|
+
# Does not currently ensure mandatory columns (for valid?) processed first but model needs saving
|
95
|
+
# before associations can be processed so user should ensure mandatory columns are prior to associations
|
91
96
|
|
92
|
-
|
93
|
-
|
97
|
+
# as part of this we also attempt to save early, for example before assigning to
|
98
|
+
# has_and_belongs_to associations which require the load_object has an id for the join table
|
94
99
|
|
95
|
-
|
96
|
-
|
97
|
-
|
100
|
+
# Iterate over the columns method_mapper found in Excel,
|
101
|
+
# pulling data out of associated column
|
102
|
+
@method_mapper.method_details.each_with_index do |method_detail, col|
|
98
103
|
|
99
|
-
|
104
|
+
value = row[col]
|
100
105
|
|
101
|
-
|
106
|
+
contains_data = true unless(value.nil? || value.to_s.empty?)
|
102
107
|
|
103
|
-
|
108
|
+
prepare_data(method_detail, value)
|
104
109
|
|
105
|
-
|
106
|
-
|
110
|
+
process()
|
111
|
+
end
|
107
112
|
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
113
|
+
break unless(contains_data == true)
|
114
|
+
|
115
|
+
# TODO - requirements to handle not valid ?
|
116
|
+
# all or nothing or carry on and dump out the exception list at end
|
117
|
+
#puts "DEBUG: FINAL SAVE #{load_object.inspect}"
|
118
|
+
unless(save)
|
119
|
+
failure
|
120
|
+
logger.error "Failed to save row [#{row}]"
|
121
|
+
logger.error load_object.errors.inspect
|
122
|
+
else
|
123
|
+
logger.info "Row #{row} succesfully SAVED : ID #{load_object.id}"
|
124
|
+
end
|
120
125
|
|
121
|
-
|
122
|
-
|
126
|
+
# don't forget to reset the object or we'll update rather than create
|
127
|
+
new_load_object
|
123
128
|
|
124
|
-
end
|
125
129
|
end
|
126
|
-
puts "Excel loading stage complete - #{loaded_objects.size} rows added."
|
127
|
-
puts "There were NO failures." if failed_objects.empty?
|
128
|
-
|
129
|
-
puts "WARNING : Check logs : #{failed_objects.size} rows contained errors and #{failed_objects.size} records NOT created." unless failed_objects.empty?
|
130
130
|
end
|
131
|
+
|
132
|
+
loaded_objects.compact! if(loaded_objects)
|
133
|
+
|
134
|
+
puts "Excel loading stage complete - #{loaded_objects.size} rows added."
|
135
|
+
puts "There were NO failures." if failed_objects.empty?
|
136
|
+
|
137
|
+
puts "WARNING : Check logs : #{failed_objects.size} rows contained errors and #{failed_objects.size} records NOT created." unless failed_objects.empty?
|
138
|
+
end
|
131
139
|
|
132
|
-
|
133
|
-
|
134
|
-
end
|
140
|
+
def value_at(row, column)
|
141
|
+
@excel[row, column]
|
135
142
|
end
|
143
|
+
end
|
136
144
|
|
137
145
|
|
138
|
-
|
146
|
+
class ExcelLoader < LoaderBase
|
139
147
|
|
140
|
-
|
148
|
+
include ExcelLoading
|
141
149
|
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
150
|
+
def initialize(klass, object = nil, options = {})
|
151
|
+
super( klass, object, options )
|
152
|
+
raise "Cannot load - failed to create a #{klass}" unless @load_object
|
153
|
+
end
|
147
154
|
|
148
|
-
def perform_load( file_name, options = {} )
|
149
|
-
perform_excel_load( file_name, options )
|
150
155
|
|
151
|
-
|
152
|
-
|
156
|
+
def perform_load( file_name, options = {} )
|
157
|
+
perform_excel_load( file_name, options )
|
153
158
|
|
159
|
+
puts "Excel loading stage complete - #{loaded_objects.size} rows added."
|
154
160
|
end
|
155
|
-
|
156
|
-
else
|
157
|
-
|
158
|
-
module ExcelLoading
|
159
|
-
end
|
160
|
-
|
161
|
+
|
161
162
|
end
|
162
|
-
|
163
163
|
end
|
data/lib/loaders/loader_base.rb
CHANGED
@@ -28,8 +28,10 @@ module DataShift
|
|
28
28
|
|
29
29
|
attr_accessor :loaded_objects, :failed_objects
|
30
30
|
|
31
|
-
attr_accessor :
|
31
|
+
attr_accessor :config, :verbose
|
32
32
|
|
33
|
+
def options() return @config; end
|
34
|
+
|
33
35
|
# Support multiple associations being added to a base object to be specified in a single column.
|
34
36
|
#
|
35
37
|
# Entry represents the association to find via supplied name, value to use in the lookup.
|
@@ -110,9 +112,9 @@ module DataShift
|
|
110
112
|
end unless(options[:load] == false)
|
111
113
|
|
112
114
|
@method_mapper = DataShift::MethodMapper.new
|
113
|
-
@
|
115
|
+
@config = options.dup # clone can cause issues like 'can't modify frozen hash'
|
114
116
|
|
115
|
-
@verbose = @
|
117
|
+
@verbose = @config[:verbose]
|
116
118
|
@headers = []
|
117
119
|
|
118
120
|
@default_data_objects ||= {}
|
@@ -123,6 +125,8 @@ module DataShift
|
|
123
125
|
@prefixes = {}
|
124
126
|
@postfixes = {}
|
125
127
|
|
128
|
+
@loaded_objects = []
|
129
|
+
|
126
130
|
reset(object)
|
127
131
|
end
|
128
132
|
|
@@ -149,7 +153,6 @@ module DataShift
|
|
149
153
|
ext = File.extname(file_name)
|
150
154
|
|
151
155
|
if(ext.casecmp('.xls') == 0)
|
152
|
-
raise DataShift::BadRuby, "Please install and use JRuby for loading .xls files" unless(Guards::jruby?)
|
153
156
|
perform_excel_load(file_name, options)
|
154
157
|
elsif(ext.casecmp('.csv') == 0)
|
155
158
|
perform_csv_load(file_name, options)
|
@@ -227,23 +230,42 @@ module DataShift
|
|
227
230
|
end
|
228
231
|
|
229
232
|
|
230
|
-
# Find a record for model klazz, looking up on field
|
233
|
+
# Find a record for model klazz, looking up on field containing search_terms
|
231
234
|
# Responds to global Options :
|
232
|
-
#
|
233
|
-
#
|
235
|
+
# :case_sensitive : Default is a case insensitive lookup.
|
236
|
+
# :use_like : Attempts a lookup using ike and x% ratehr than equality
|
234
237
|
|
235
|
-
def get_record_by(klazz, field,
|
238
|
+
def get_record_by(klazz, field, search_terms, split_on = ' ', split_on_prefix = nil)
|
236
239
|
|
237
240
|
begin
|
238
|
-
if(@
|
239
|
-
|
240
|
-
elsif(@
|
241
|
-
|
241
|
+
record = if(@config[:case_sensitive])
|
242
|
+
klazz.send("find_by_#{field}", search_terms)
|
243
|
+
elsif(@config[:use_like])
|
244
|
+
klazz.where("#{field} like ?", "#{search_terms}%").first
|
242
245
|
else
|
243
|
-
|
246
|
+
klazz.where("lower(#{field}) = ?", search_terms.downcase).first
|
244
247
|
end
|
248
|
+
|
249
|
+
# try the separate individual portions of the search_terms, front -> back
|
250
|
+
search_terms.split(split_on).each do |x|
|
251
|
+
z = "#{split_on_prefix}#{x}" if(split_on_prefix)
|
252
|
+
|
253
|
+
record = get_record_by(klazz, field, z, split_on, split_on_prefix)
|
254
|
+
break if record
|
255
|
+
end unless(record)
|
256
|
+
|
257
|
+
# this time try sequentially and incrementally scanning
|
258
|
+
search_terms.split(split_on).inject("") do |str, term|
|
259
|
+
z = (split_on_prefix) ? "#{split_on_prefix}#{str}#{term}": "#{str}#{term}"
|
260
|
+
record = get_record_by(klazz, field, z, split_on, split_on_prefix)
|
261
|
+
break if record
|
262
|
+
term
|
263
|
+
end unless(record)
|
264
|
+
|
265
|
+
return record
|
266
|
+
|
245
267
|
rescue => e
|
246
|
-
logger.error("Exception attempting to find a record for [#{
|
268
|
+
logger.error("Exception attempting to find a record for [#{search_terms}] on #{klazz}.#{field}")
|
247
269
|
logger.error e.backtrace
|
248
270
|
logger.error e.inspect
|
249
271
|
return nil
|
@@ -311,14 +333,14 @@ module DataShift
|
|
311
333
|
end
|
312
334
|
|
313
335
|
if(data['LoaderBase'])
|
314
|
-
@
|
336
|
+
@config.merge!(data['LoaderBase'])
|
315
337
|
end
|
316
338
|
|
317
339
|
if(data[self.class.name])
|
318
|
-
@
|
340
|
+
@config.merge!(data[self.class.name])
|
319
341
|
end
|
320
342
|
|
321
|
-
logger.info("Loader Options : #{@
|
343
|
+
logger.info("Loader Options : #{@config.inspect}")
|
322
344
|
end
|
323
345
|
|
324
346
|
# Set member variables to hold details and value.
|
@@ -380,7 +402,7 @@ module DataShift
|
|
380
402
|
#
|
381
403
|
def process()
|
382
404
|
|
383
|
-
logger.info("Current value to assign : #{@current_value}") #if @
|
405
|
+
logger.info("Current value to assign : #{@current_value}") #if @config['verboose_logging']
|
384
406
|
|
385
407
|
if(@current_method_detail.operator_for(:has_many))
|
386
408
|
|
@@ -420,7 +442,7 @@ module DataShift
|
|
420
442
|
unless(find_by_values.size == @current_value.size)
|
421
443
|
found = @current_value.collect {|f| f.send(find_operator) }
|
422
444
|
@load_object.errors.add( @current_method_detail.operator, "Association with key(s) #{(find_by_values - found).inspect} NOT found")
|
423
|
-
puts "WARNING: Association with key(s) #{(
|
445
|
+
puts "WARNING: Association #{@current_method_detail.operator} with key(s) #{(find_by_values - found).inspect} NOT found - Not added."
|
424
446
|
next if(@current_value.empty?)
|
425
447
|
end
|
426
448
|
|
@@ -464,7 +486,7 @@ module DataShift
|
|
464
486
|
failure
|
465
487
|
puts "Error saving #{@load_object.class} : #{e.inspect}"
|
466
488
|
logger.error e.backtrace
|
467
|
-
raise "Error in save whilst processing column #{@current_method_detail.name}" if(@
|
489
|
+
raise "Error in save whilst processing column #{@current_method_detail.name}" if(@config[:strict])
|
468
490
|
end
|
469
491
|
end
|
470
492
|
|
@@ -522,7 +544,7 @@ module DataShift
|
|
522
544
|
end
|
523
545
|
|
524
546
|
def abort_on_failure?
|
525
|
-
@
|
547
|
+
@config[:abort_on_failure] == 'true'
|
526
548
|
end
|
527
549
|
|
528
550
|
def loaded_count
|