drive_time 0.0.7 → 0.0.8
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/lib/drive_time/converters/spreadsheets_converter.rb +5 -2
- data/lib/drive_time/converters/worksheet_converter.rb +84 -28
- data/lib/drive_time/model_store.rb +12 -5
- data/lib/drive_time/version.rb +1 -1
- data/lib/drive_time.rb +1 -0
- data/spec/fixtures/mapping.yml +1 -1
- data/spec/full_tests.rb +1 -1
- metadata +2 -2
@@ -104,10 +104,13 @@ module DriveTime
|
|
104
104
|
def worksheet_for_association(name, worksheets)
|
105
105
|
# And find the worksheet that satisfies it
|
106
106
|
worksheets.each do |worksheet|
|
107
|
+
puts "#{name} --->"
|
107
108
|
class_name = DriveTime.class_name_from_title(worksheet.title)
|
108
|
-
|
109
|
+
puts " -- #{DriveTime.underscore_from_text(worksheet.title)}"
|
110
|
+
#resolved = @class_name_map.resolve_mapped_from_original class_name
|
111
|
+
#puts "Resolved -- #{resolved}"
|
109
112
|
# If the name matches we have a dependent relationship
|
110
|
-
if
|
113
|
+
if name == DriveTime.underscore_from_text(worksheet.title)
|
111
114
|
return worksheet
|
112
115
|
end
|
113
116
|
end
|
@@ -6,7 +6,7 @@ module DriveTime
|
|
6
6
|
|
7
7
|
class NoClassWithTitleError < StandardError; end
|
8
8
|
class NoFieldNameError < StandardError; end
|
9
|
-
|
9
|
+
class NoMethodError < StandardError; end
|
10
10
|
class NoKeyError < StandardError; end
|
11
11
|
class PolymorphicAssociationError < StandardError; end
|
12
12
|
|
@@ -57,7 +57,8 @@ module DriveTime
|
|
57
57
|
model_key = build_id_for_model mapping
|
58
58
|
Logger.log_as_sub_header "Model Key: #{model_key}"
|
59
59
|
# Build hash ready to pass into model
|
60
|
-
model_fields = row_fields_to_model_fields
|
60
|
+
model_fields = row_fields_to_model_fields(mapping, model_key)
|
61
|
+
method_calls = row_fields_to_method_calls(mapping, model_key)
|
61
62
|
|
62
63
|
# Set the model key as an attribute on the model
|
63
64
|
if mapping[:key_to]
|
@@ -65,8 +66,23 @@ module DriveTime
|
|
65
66
|
end
|
66
67
|
|
67
68
|
Logger.debug "Creating Model of class '#{clazz.name.to_s}' with Model Fields #{model_fields.to_s}"
|
69
|
+
|
68
70
|
# Create new model
|
69
71
|
model = clazz.new(model_fields, without_protection: true)
|
72
|
+
|
73
|
+
# Invoke any method calls
|
74
|
+
method_calls.each do |method_call|
|
75
|
+
call_step = model
|
76
|
+
methods = method_call["methods"]
|
77
|
+
methods.each_with_index do |method, index|
|
78
|
+
if index == method_call.length - 1
|
79
|
+
call_step.send(method, method_call["value"])
|
80
|
+
else
|
81
|
+
call_step = call_step.send(method)
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
70
86
|
# Add its associations
|
71
87
|
add_associations(model, mapping)
|
72
88
|
# Store the model using its ID
|
@@ -85,39 +101,46 @@ module DriveTime
|
|
85
101
|
end
|
86
102
|
end
|
87
103
|
|
104
|
+
def row_fields_to_method_calls(mapping, model_key)
|
105
|
+
method_calls = []
|
106
|
+
# Run through the mapping, pulling values from row_map as required
|
107
|
+
if mapping[:calls]
|
108
|
+
mapping[:calls].each do |call_mapping|
|
109
|
+
field_name = call_mapping[:name]
|
110
|
+
methods = call_mapping[:methods]
|
111
|
+
|
112
|
+
unless methods
|
113
|
+
raise NoMethodError "Missing Method: Name for call field: #{field_name} in mapping: #{mapping}"
|
114
|
+
end
|
115
|
+
|
116
|
+
field_value = parse_field_value(@row_map[field_name])
|
117
|
+
|
118
|
+
# handle multi-values
|
119
|
+
if call_mapping[:builder] == "multi"
|
120
|
+
field_value = MultiBuilder.new.build(field_value)
|
121
|
+
end
|
122
|
+
method_calls << {"methods" => methods, "value" => field_value}
|
123
|
+
end
|
124
|
+
end
|
125
|
+
return method_calls
|
126
|
+
end
|
127
|
+
|
88
128
|
# Run through the mapping's fields and convert them
|
89
129
|
def row_fields_to_model_fields(mapping, model_key)
|
90
130
|
model_fields = HashWithIndifferentAccess.new
|
131
|
+
|
91
132
|
# Run through the mapping, pulling values from row_map as required
|
92
133
|
if mapping[:fields]
|
93
134
|
mapping[:fields].each do |field_mapping|
|
94
135
|
field_name = field_mapping[:name]
|
95
136
|
mapped_to_field_name = field_mapping[:map_to]
|
137
|
+
|
96
138
|
unless field_name
|
97
139
|
raise NoFieldNameError "Missing Field: Name for field: #{value} in mapping: #{mapping}"
|
98
140
|
end
|
99
141
|
|
100
|
-
field_value = @row_map[field_name]
|
101
|
-
# Check for token pattern: {{some_value}}
|
102
|
-
match = /\{\{(.*?)\}\}/.match(field_value)
|
103
|
-
if match
|
104
|
-
field_value = @field_expander.expand(match[1], model_key)
|
105
|
-
end
|
106
|
-
|
107
|
-
# Check for Boolean values
|
108
|
-
if field_value
|
109
|
-
downcased = field_value.downcase
|
110
|
-
if downcased == 'y' || downcased == 'yes' || downcased == 'true'
|
111
|
-
field_value = true
|
112
|
-
elsif downcased == 'n' || downcased == 'no' || downcased == 'false'
|
113
|
-
field_value = false
|
114
|
-
end
|
115
|
-
end
|
116
|
-
|
117
|
-
# Make sure any empty cells give us nil (rather than an empty string)
|
118
|
-
field_value = nil if field_value.blank?
|
142
|
+
field_value = parse_field_value(@row_map[field_name])
|
119
143
|
model_fields[mapped_to_field_name || field_name] = field_value
|
120
|
-
|
121
144
|
end
|
122
145
|
end
|
123
146
|
return model_fields
|
@@ -133,7 +156,7 @@ module DriveTime
|
|
133
156
|
associations_mapping.each do |association_mapping|
|
134
157
|
# Use the spreadsheet name unless 'map_to_class' is set
|
135
158
|
if !association_mapping[:polymorphic]
|
136
|
-
association_class_name = @class_name_map.resolve_mapped_from_original
|
159
|
+
association_class_name = @class_name_map.resolve_mapped_from_original(association_mapping[:name].classify)
|
137
160
|
else
|
138
161
|
possible_class_names = association_mapping[:name]
|
139
162
|
# The classname will be taken from the type collumn
|
@@ -180,7 +203,7 @@ module DriveTime
|
|
180
203
|
associated_models.each do |associated_model|
|
181
204
|
Logger.debug " - Associated Model: #{associated_model}"
|
182
205
|
unless association_mapping[:inverse] == true
|
183
|
-
association_name = association_class_name.underscore
|
206
|
+
association_name = association_class_name.split('::').last.underscore
|
184
207
|
if association_mapping[:singular] == true
|
185
208
|
Logger.debug " - Adding association #{associated_model} to #{model}::#{association_name}"
|
186
209
|
# Set the association
|
@@ -210,9 +233,11 @@ module DriveTime
|
|
210
233
|
def associated_models_from_builder(association_mapping, class_name)
|
211
234
|
associated_models = []
|
212
235
|
if association_mapping[:builder] == 'multi' # It's a multi value, find a matching cell and split its value by comma
|
213
|
-
|
214
|
-
|
215
|
-
|
236
|
+
# Use only the classname for the fieldname, discarding namespace
|
237
|
+
field_name = class_name.split("::").last.underscore.pluralize
|
238
|
+
cell_value = @row_map[field_name]
|
239
|
+
raise MissingAssociationError "No field #{class_name.underscore.pluralize} to satisfy multi association" if cell_value.blank? && association_mapping[:optional] != true
|
240
|
+
components = MultiBuilder.new.build(cell_value)
|
216
241
|
components.each do |component|
|
217
242
|
associated_models << model_for_id(component, namespaced_class_name(class_name))
|
218
243
|
end
|
@@ -252,9 +277,40 @@ module DriveTime
|
|
252
277
|
end
|
253
278
|
end
|
254
279
|
|
255
|
-
def namespaced_class_name
|
280
|
+
def namespaced_class_name(class_name)
|
256
281
|
class_name = "#{@namespace}::#{class_name}" unless @namespace.blank?
|
257
282
|
class_name.constantize
|
258
283
|
end
|
284
|
+
|
285
|
+
def parse_field_value(field_value)
|
286
|
+
if field_value
|
287
|
+
field_value = check_for_token(field_value)
|
288
|
+
field_value = check_for_boolean(field_value)
|
289
|
+
end
|
290
|
+
# Make sure any empty cells give us nil (rather than an empty string)
|
291
|
+
field_value = nil if field_value.blank?
|
292
|
+
field_value
|
293
|
+
end
|
294
|
+
|
295
|
+
def check_for_token(field_value)
|
296
|
+
# Check for token pattern: {{some_value}}
|
297
|
+
match = /\{\{(.*?)\}\}/.match(field_value)
|
298
|
+
if match
|
299
|
+
@field_expander.expand(match[1], model_key)
|
300
|
+
else
|
301
|
+
field_value
|
302
|
+
end
|
303
|
+
end
|
304
|
+
|
305
|
+
def check_for_boolean(field_value)
|
306
|
+
downcased = field_value.downcase
|
307
|
+
if downcased == 'y' || downcased == 'yes' || downcased == 'true'
|
308
|
+
true
|
309
|
+
elsif downcased == 'n' || downcased == 'no' || downcased == 'false'
|
310
|
+
false
|
311
|
+
else
|
312
|
+
field_value
|
313
|
+
end
|
314
|
+
end
|
259
315
|
end
|
260
316
|
end
|
@@ -32,6 +32,7 @@ module DriveTime
|
|
32
32
|
class_string = clazz.to_s
|
33
33
|
# Sanitise key
|
34
34
|
key = DriveTime.underscore_from_text(key)
|
35
|
+
|
35
36
|
@logger.debug "Adding model with key #{key} of class #{clazz}"
|
36
37
|
if !@store[class_string]
|
37
38
|
@store[class_string] = {}
|
@@ -43,7 +44,6 @@ module DriveTime
|
|
43
44
|
|
44
45
|
def get_model(clazz, key)
|
45
46
|
@logger.debug "Request for model with key #{key} of class #{clazz}"
|
46
|
-
|
47
47
|
models_for_class = @store[clazz.to_s]
|
48
48
|
# Are there any classes of this type in the store?
|
49
49
|
if models_for_class.nil?
|
@@ -52,8 +52,7 @@ module DriveTime
|
|
52
52
|
|
53
53
|
# Is there an instance
|
54
54
|
model = models_for_class[key]
|
55
|
-
|
56
|
-
if !model
|
55
|
+
unless model.preset?
|
57
56
|
raise NoModelOfClassWithKeyInStoreError, "No model of class #{clazz} with a key of #{key} in model store"
|
58
57
|
end
|
59
58
|
|
@@ -61,13 +60,21 @@ module DriveTime
|
|
61
60
|
end
|
62
61
|
|
63
62
|
def save_all
|
63
|
+
@logger.log_as_header "Saving Models"
|
64
64
|
@store.each do |key, models|
|
65
65
|
models.each do |key, model|
|
66
|
-
model.
|
66
|
+
@logger.debug "Saving Model: #{key} #{model.inspect}"
|
67
|
+
begin
|
68
|
+
model.save!
|
69
|
+
rescue Exception => error
|
70
|
+
@logger.warn "Failed To Save Model: #{key}"
|
71
|
+
@logger.warn "Error: #{error}"
|
72
|
+
@logger.warn "#{model.inspect}"
|
73
|
+
raise error
|
74
|
+
end
|
67
75
|
end
|
68
76
|
end
|
69
77
|
end
|
70
78
|
|
71
79
|
end
|
72
|
-
|
73
80
|
end
|
data/lib/drive_time/version.rb
CHANGED
data/lib/drive_time.rb
CHANGED
@@ -15,6 +15,7 @@ require 'drive_time/loader'
|
|
15
15
|
require 'drive_time/class_name_map'
|
16
16
|
require 'drive_time/builders/join_builder'
|
17
17
|
require 'drive_time/builders/name_builder'
|
18
|
+
require 'drive_time/builders/multi_builder'
|
18
19
|
require 'drive_time/converters/spreadsheets_converter'
|
19
20
|
require 'drive_time/converters/worksheet_converter'
|
20
21
|
require 'drive_time/logging'
|
data/spec/fixtures/mapping.yml
CHANGED
data/spec/full_tests.rb
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: drive_time
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.8
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2013-09-
|
12
|
+
date: 2013-09-11 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: log4r
|