datashift 0.15.0 → 0.16.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.
- checksums.yaml +7 -0
- data/README.markdown +91 -55
- data/VERSION +1 -1
- data/datashift.gemspec +8 -23
- data/lib/applications/jexcel_file.rb +1 -2
- data/lib/datashift.rb +34 -15
- data/lib/datashift/column_packer.rb +98 -34
- data/lib/datashift/data_transforms.rb +83 -0
- data/lib/datashift/delimiters.rb +58 -10
- data/lib/datashift/excel_base.rb +123 -0
- data/lib/datashift/exceptions.rb +45 -7
- data/lib/datashift/load_object.rb +25 -0
- data/lib/datashift/mapping_service.rb +91 -0
- data/lib/datashift/method_detail.rb +40 -62
- data/lib/datashift/method_details_manager.rb +18 -2
- data/lib/datashift/method_dictionary.rb +27 -10
- data/lib/datashift/method_mapper.rb +49 -41
- data/lib/datashift/model_mapper.rb +42 -22
- data/lib/datashift/populator.rb +258 -143
- data/lib/datashift/thor_base.rb +38 -0
- data/lib/exporters/csv_exporter.rb +57 -145
- data/lib/exporters/excel_exporter.rb +73 -60
- data/lib/generators/csv_generator.rb +65 -5
- data/lib/generators/generator_base.rb +69 -3
- data/lib/generators/mapping_generator.rb +112 -0
- data/lib/helpers/core_ext/csv_file.rb +33 -0
- data/lib/loaders/csv_loader.rb +41 -39
- data/lib/loaders/excel_loader.rb +130 -116
- data/lib/loaders/loader_base.rb +190 -146
- data/lib/loaders/paperclip/attachment_loader.rb +4 -4
- data/lib/loaders/paperclip/datashift_paperclip.rb +5 -3
- data/lib/loaders/paperclip/image_loading.rb +9 -7
- data/lib/loaders/reporter.rb +17 -8
- data/lib/thor/export.thor +12 -13
- data/lib/thor/generate.thor +1 -9
- data/lib/thor/import.thor +13 -24
- data/lib/thor/mapping.thor +65 -0
- data/spec/Gemfile +13 -11
- data/spec/Gemfile.lock +98 -93
- data/spec/csv_exporter_spec.rb +104 -99
- data/spec/csv_generator_spec.rb +159 -0
- data/spec/csv_loader_spec.rb +197 -16
- data/spec/datashift_spec.rb +9 -0
- data/spec/excel_exporter_spec.rb +149 -58
- data/spec/excel_generator_spec.rb +35 -44
- data/spec/excel_loader_spec.rb +196 -178
- data/spec/excel_spec.rb +8 -5
- data/spec/loader_base_spec.rb +47 -7
- data/spec/mapping_spec.rb +117 -0
- data/spec/method_dictionary_spec.rb +24 -11
- data/spec/method_mapper_spec.rb +5 -7
- data/spec/model_mapper_spec.rb +41 -0
- data/spec/paperclip_loader_spec.rb +3 -6
- data/spec/populator_spec.rb +48 -14
- data/spec/spec_helper.rb +85 -73
- data/spec/thor_spec.rb +40 -5
- metadata +93 -86
- data/lib/applications/excel_base.rb +0 -63
data/lib/datashift/populator.rb
CHANGED
@@ -14,183 +14,287 @@ require 'logging'
|
|
14
14
|
|
15
15
|
module DataShift
|
16
16
|
|
17
|
+
Struct.new("Substitution", :pattern, :replacement)
|
18
|
+
|
17
19
|
class Populator
|
18
|
-
|
20
|
+
|
19
21
|
include DataShift::Logging
|
20
|
-
|
22
|
+
|
21
23
|
def self.insistent_method_list
|
22
24
|
@insistent_method_list ||= [:to_s, :to_i, :to_f, :to_b]
|
23
25
|
end
|
24
|
-
|
26
|
+
|
25
27
|
# When looking up an association, when no field provided, try each of these in turn till a match
|
26
28
|
# i.e find_by_name, find_by_title, find_by_id
|
27
29
|
def self.insistent_find_by_list
|
28
30
|
@insistent_find_by_list ||= [:name, :title, :id]
|
29
31
|
end
|
30
|
-
|
31
|
-
|
32
|
+
|
33
|
+
|
34
|
+
# Default data embedded in column headings - so effectively apply globally
|
35
|
+
# to teh whole column - hence class methods
|
36
|
+
def self.set_header_default_data(operator, data )
|
37
|
+
header_default_data[operator] = data
|
38
|
+
end
|
39
|
+
|
40
|
+
def self.header_default_data
|
41
|
+
@header_default_data ||= {}
|
42
|
+
end
|
43
|
+
|
44
|
+
|
32
45
|
attr_reader :current_value, :original_value_before_override
|
46
|
+
attr_reader :current_col_type
|
47
|
+
|
33
48
|
attr_reader :current_attribute_hash
|
34
49
|
attr_reader :current_method_detail
|
35
|
-
|
36
|
-
def initialize
|
50
|
+
|
51
|
+
def initialize
|
37
52
|
@current_value = nil
|
53
|
+
@current_method_detail = nil
|
38
54
|
@original_value_before_override = nil
|
39
55
|
@current_attribute_hash = {}
|
40
56
|
|
41
57
|
end
|
42
|
-
|
43
|
-
#
|
58
|
+
|
59
|
+
# Convert DSL string forms into a hash
|
60
|
+
# e.g
|
61
|
+
#
|
62
|
+
# "{:name => 'autechre'}" => Hash['name'] = autechre'
|
63
|
+
# "{:cost_price => '13.45', :price => 23, :sale_price => 4.23 }"
|
64
|
+
|
65
|
+
def self.string_to_hash( str )
|
66
|
+
h = {}
|
67
|
+
str.gsub(/[{}:]/,'').split(', ').map do |e|
|
68
|
+
k,v = e.split('=>')
|
69
|
+
|
70
|
+
k.strip!
|
71
|
+
v.strip!
|
72
|
+
|
73
|
+
if( v.match(/['"]/) )
|
74
|
+
h[k] = v.gsub(/["']/, '')
|
75
|
+
elsif( v.match(/^\d+$|^\d*\.\d+$|^\.\d+$/) )
|
76
|
+
h[k] = v.to_f
|
77
|
+
else
|
78
|
+
h[k] = v
|
79
|
+
end
|
80
|
+
h
|
81
|
+
end
|
82
|
+
|
83
|
+
h
|
84
|
+
end
|
85
|
+
|
86
|
+
# Set member variables to hold details, value and optional attributes,
|
87
|
+
# to be set on the 'value' once created
|
44
88
|
#
|
45
89
|
# Check supplied value, validate it, and if required :
|
46
90
|
# set to provided default value
|
47
91
|
# prepend any provided prefixes
|
48
92
|
# add any provided postfixes
|
49
93
|
def prepare_data(method_detail, value)
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
@
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
94
|
+
|
95
|
+
raise NilDataSuppliedError.new("No method detail supplied for prepare_data") unless(method_detail)
|
96
|
+
|
97
|
+
begin
|
98
|
+
@prepare_data_const_regexp ||= Regexp.new( Delimiters::attribute_list_start + ".*" + Delimiters::attribute_list_end)
|
99
|
+
|
100
|
+
if( value.is_a? ActiveRecord::Relation ) # Rails 4 - query no longer returns an array
|
101
|
+
@current_value = value.to_a
|
102
|
+
elsif( !DataShift::Guards.jruby? && value.class.ancestors.include?(Spreadsheet::Formula))
|
103
|
+
@current_value = value.value
|
104
|
+
elsif( value.class.ancestors.include?(ActiveRecord::Base) || value.is_a?(Array))
|
105
|
+
@current_value = value
|
106
|
+
else
|
107
|
+
@current_value = value.to_s
|
108
|
+
|
109
|
+
attribute_hash = @current_value.slice!(@prepare_data_const_regexp)
|
110
|
+
|
111
|
+
if(attribute_hash)
|
112
|
+
@current_attribute_hash = Populator::string_to_hash( attribute_hash )
|
113
|
+
logger.info "Populator for #{@current_value} has attributes #{@current_attribute_hash.inspect}"
|
114
|
+
end
|
115
|
+
end
|
116
|
+
|
117
|
+
@current_attribute_hash ||= {}
|
118
|
+
|
119
|
+
@current_method_detail = method_detail
|
120
|
+
|
121
|
+
@current_col_type = @current_method_detail.col_type
|
122
|
+
|
123
|
+
operator = method_detail.operator
|
124
|
+
|
125
|
+
if(has_override?(operator))
|
126
|
+
override_value(operator) # takes precedence over anything else
|
127
|
+
else
|
128
|
+
# if no value check for a defaults from config, headers
|
129
|
+
if(default_value(operator))
|
130
|
+
@current_value = default_value(operator)
|
131
|
+
elsif(Populator::header_default_data[operator])
|
132
|
+
@current_value = Populator::header_default_data[operator].to_s
|
133
|
+
elsif(Populator::header_default_data[operator])
|
134
|
+
@current_value = Populator::header_default_data[operator].to_s
|
135
|
+
elsif(method_detail.find_by_value)
|
136
|
+
@current_value = method_detail.find_by_value
|
137
|
+
end if(value.nil? || value.to_s.empty?)
|
138
|
+
end
|
139
|
+
|
140
|
+
substitute( operator )
|
141
|
+
|
142
|
+
@current_value = "#{prefix(operator)}#{@current_value}" if(prefix(operator))
|
143
|
+
@current_value = "#{@current_value}#{postfix(operator)}" if(postfix(operator))
|
144
|
+
|
145
|
+
rescue => e
|
146
|
+
logger.error("populator failed to prepare data supplied for operator #{method_detail.operator}")
|
147
|
+
logger.error("populator error: #{e.inspect}")
|
148
|
+
logger.error("populator stacktrace: #{e.backtrace.last}")
|
149
|
+
raise DataProcessingError.new("opulator failed to prepare data #{value} for operator #{method_detail.operator}")
|
69
150
|
end
|
70
|
-
|
71
|
-
@current_value = "#{prefix(operator)}#{@current_value}" if(prefix(operator))
|
72
|
-
@current_value = "#{@current_value}#{postfix(operator)}" if(postfix(operator))
|
73
151
|
|
74
152
|
return @current_value, @current_attribute_hash
|
75
153
|
end
|
76
|
-
|
77
|
-
def assign(method_detail, record, value )
|
78
|
-
|
79
|
-
@current_value = value
|
80
|
-
|
81
|
-
# Rails 4 - not an array any more
|
82
|
-
if( value.is_a? ActiveRecord::Relation )
|
83
|
-
logger.warn("Relation passed rather than value #{value.inspect}")
|
84
|
-
@current_value = value.to_a
|
85
|
-
end
|
86
154
|
|
87
|
-
|
155
|
+
# Main client hook
|
156
|
+
|
157
|
+
def prepare_and_assign(method_detail, record, value)
|
158
|
+
|
159
|
+
prepare_data(method_detail, value)
|
160
|
+
|
161
|
+
assign(record)
|
162
|
+
end
|
163
|
+
|
164
|
+
def assign(record)
|
165
|
+
|
166
|
+
raise NilDataSuppliedError.new("No method detail - cannot assign data") unless(current_method_detail)
|
167
|
+
|
168
|
+
operator = current_method_detail.operator
|
169
|
+
|
170
|
+
logger.debug("Populator assign - [#{current_value}] via #{current_method_detail.operator} (#{current_method_detail.operator_type})")
|
171
|
+
|
172
|
+
if( current_method_detail.operator_for(:belongs_to) )
|
173
|
+
|
174
|
+
insistent_belongs_to(current_method_detail, record, current_value)
|
175
|
+
|
176
|
+
elsif( current_method_detail.operator_for(:has_many) )
|
88
177
|
|
89
|
-
operator = method_detail.operator
|
90
|
-
|
91
|
-
if( method_detail.operator_for(:belongs_to) )
|
92
|
-
|
93
|
-
#puts "DEBUG : BELONGS_TO : #{@name} : #{operator} - Lookup #{@current_value} in DB"
|
94
|
-
insistent_belongs_to(method_detail, record, @current_value)
|
95
|
-
|
96
|
-
elsif( method_detail.operator_for(:has_many) )
|
97
|
-
|
98
|
-
puts "DEBUG : VALUE TYPE [#{value.class.name.include?(operator.classify)}] [#{ModelMapper.class_from_string(value.class.name)}]" unless(value.is_a?(Array))
|
99
|
-
|
100
178
|
# The include? check is best I can come up with right now .. to handle module/namespaces
|
101
179
|
# TODO - can we determine the real class type of an association
|
102
180
|
# e.g given a association taxons, which operator.classify gives us Taxon, but actually it's Spree::Taxon
|
103
181
|
# so how do we get from 'taxons' to Spree::Taxons ? .. check if further info in reflect_on_all_associations
|
104
182
|
|
105
|
-
if(
|
106
|
-
record.send(operator) <<
|
107
|
-
|
108
|
-
|
183
|
+
begin #if(current_value.is_a?(Array) || current_value.class.name.include?(operator.classify))
|
184
|
+
record.send(operator) << current_value
|
185
|
+
rescue => e
|
186
|
+
logger.error e.inspect
|
187
|
+
logger.error "Cannot assign #{current_value.inspect} (#{current_value.class}) to has_many association [#{operator}] "
|
109
188
|
end
|
110
189
|
|
111
|
-
elsif(
|
190
|
+
elsif( current_method_detail.operator_for(:has_one) )
|
112
191
|
|
113
192
|
#puts "DEBUG : HAS_MANY : #{@name} : #{operator}(#{operator_class}) - Lookup #{@current_value} in DB"
|
114
|
-
if(
|
115
|
-
record.send(operator + '=',
|
193
|
+
if(current_value.is_a?(current_method_detail.operator_class))
|
194
|
+
record.send(operator + '=', current_value)
|
116
195
|
else
|
117
|
-
logger.error("ERROR #{
|
196
|
+
logger.error("ERROR #{current_value.class} - Not expected type for has_one #{operator} - cannot assign")
|
118
197
|
# TODO - Not expected type - maybe try to look it up somehow ?"
|
119
|
-
#insistent_has_many(record, @current_value)
|
120
198
|
end
|
121
199
|
|
122
|
-
elsif(
|
123
|
-
#
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
200
|
+
elsif( current_method_detail.operator_for(:assignment) && current_col_type)
|
201
|
+
# 'type_cast' was changed to 'type_cast_from_database'
|
202
|
+
if Rails::VERSION::STRING < '4.2.0'
|
203
|
+
logger.debug("Assign #{current_value} => [#{operator}] (CAST 2 TYPE #{current_col_type.type_cast( current_value ).inspect})")
|
204
|
+
record.send( operator + '=' , current_method_detail.col_type.type_cast( current_value ) )
|
205
|
+
else
|
206
|
+
logger.debug("Assign #{current_value} => [#{operator}] (CAST 2 TYPE #{current_col_type.type_cast_from_database( current_value ).inspect})")
|
207
|
+
record.send( operator + '=' , current_method_detail.col_type.type_cast_from_database( current_value ) )
|
208
|
+
end
|
128
209
|
|
129
|
-
elsif(
|
130
|
-
|
210
|
+
elsif( current_method_detail.operator_for(:assignment) )
|
211
|
+
logger.debug("Brute force assignment of value #{current_value} => [#{operator}]")
|
131
212
|
# brute force case for assignments without a column type (which enables us to do correct type_cast)
|
132
213
|
# so in this case, attempt straightforward assignment then if that fails, basic ops such as to_s, to_i, to_f etc
|
133
|
-
insistent_assignment(record,
|
214
|
+
insistent_assignment(record, current_value, operator)
|
134
215
|
else
|
135
216
|
puts "WARNING: No assignment possible on #{record.inspect} using [#{operator}]"
|
136
217
|
logger.error("WARNING: No assignment possible on #{record.inspect} using [#{operator}]")
|
137
218
|
end
|
138
219
|
end
|
139
|
-
|
220
|
+
|
140
221
|
def insistent_assignment(record, value, operator)
|
141
|
-
|
142
|
-
#puts "DEBUG: RECORD CLASS #{record.class}"
|
222
|
+
|
143
223
|
op = operator + '=' unless(operator.include?('='))
|
144
|
-
|
224
|
+
|
145
225
|
begin
|
146
226
|
record.send(op, value)
|
147
227
|
rescue => e
|
228
|
+
|
148
229
|
Populator::insistent_method_list.each do |f|
|
149
230
|
begin
|
150
231
|
record.send(op, value.send( f) )
|
151
232
|
break
|
152
233
|
rescue => e
|
153
|
-
puts "DEBUG: insistent_assignment: #{e.inspect}"
|
154
234
|
if f == Populator::insistent_method_list.last
|
155
|
-
|
156
|
-
|
235
|
+
logger.error(e.inspect)
|
236
|
+
logger.error("Failed to assign [#{value}] via operator #{operator}")
|
237
|
+
raise "Failed to assign [#{value}] to #{operator}" unless value.nil?
|
157
238
|
end
|
158
239
|
end
|
159
240
|
end
|
160
241
|
end
|
161
242
|
end
|
162
|
-
|
243
|
+
|
163
244
|
# Attempt to find the associated object via id, name, title ....
|
164
245
|
def insistent_belongs_to(method_detail, record, value )
|
165
246
|
|
166
247
|
operator = method_detail.operator
|
167
|
-
|
248
|
+
|
168
249
|
if( value.class == method_detail.operator_class)
|
250
|
+
logger.info("Populator assigning #{value} to belongs_to association #{operator}")
|
169
251
|
record.send(operator) << value
|
170
252
|
else
|
171
253
|
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
logger.error("
|
182
|
-
|
183
|
-
|
254
|
+
# TODO - DRY all this
|
255
|
+
if(method_detail.find_by_operator)
|
256
|
+
|
257
|
+
item = method_detail.operator_class.where(method_detail.find_by_operator => value).first_or_create
|
258
|
+
|
259
|
+
if(item)
|
260
|
+
logger.info("Populator assigning #{item.inspect} to belongs_to association #{operator}")
|
261
|
+
record.send(operator + '=', item)
|
262
|
+
else
|
263
|
+
logger.error("Could not find or create [#{value}] for belongs_to association [#{operator}]")
|
264
|
+
raise CouldNotAssignAssociation.new "Populator failed to assign [#{value}] to belongs_to association [#{operator}]"
|
265
|
+
end
|
266
|
+
|
267
|
+
else
|
268
|
+
#try the default field names
|
269
|
+
Populator::insistent_find_by_list.each do |x|
|
270
|
+
begin
|
271
|
+
|
272
|
+
next unless method_detail.operator_class.respond_to?("where")
|
273
|
+
|
274
|
+
item = method_detail.operator_class.where(x => value).first_or_create
|
275
|
+
|
276
|
+
if(item)
|
277
|
+
logger.info("Populator assigning #{item.inspect} to belongs_to association #{operator}")
|
278
|
+
record.send(operator + '=', item)
|
279
|
+
break
|
280
|
+
end
|
281
|
+
rescue => e
|
282
|
+
logger.error(e.inspect)
|
283
|
+
logger.error("Failed attempting to find belongs_to for #{method_detail.pp}")
|
284
|
+
if(x == Populator::insistent_method_list.last)
|
285
|
+
raise CouldNotAssignAssociation.new "Populator failed to assign [#{value}] to belongs_to association [#{operator}]" unless value.nil?
|
286
|
+
end
|
184
287
|
end
|
185
288
|
end
|
186
289
|
end
|
290
|
+
|
187
291
|
end
|
188
292
|
end
|
189
|
-
|
293
|
+
|
190
294
|
def assignment( operator, record, value )
|
191
|
-
|
295
|
+
|
192
296
|
op = operator + '=' unless(operator.include?('='))
|
193
|
-
|
297
|
+
|
194
298
|
begin
|
195
299
|
record.send(op, value)
|
196
300
|
rescue => e
|
@@ -199,7 +303,6 @@ module DataShift
|
|
199
303
|
record.send(op, value.send( f) )
|
200
304
|
break
|
201
305
|
rescue => e
|
202
|
-
#puts "DEBUG: insistent_assignment: #{e.inspect}"
|
203
306
|
if f == Populator::insistent_method_list.last
|
204
307
|
puts "I'm sorry I have failed to assign [#{value}] to #{operator}"
|
205
308
|
raise "I'm sorry I have failed to assign [#{value}] to #{operator}" unless value.nil?
|
@@ -208,8 +311,8 @@ module DataShift
|
|
208
311
|
end
|
209
312
|
end
|
210
313
|
end
|
211
|
-
|
212
|
-
|
314
|
+
|
315
|
+
|
213
316
|
# Default values and over rides can be provided in Ruby/YAML ???? config file.
|
214
317
|
#
|
215
318
|
# Format :
|
@@ -224,80 +327,93 @@ module DataShift
|
|
224
327
|
#
|
225
328
|
def configure_from(load_object_class, yaml_file)
|
226
329
|
|
227
|
-
data = YAML::load(
|
228
|
-
|
229
|
-
# TODO - MOVE DEFAULTS TO OWN MODULE
|
230
|
-
|
231
|
-
#
|
232
|
-
|
233
|
-
#unless(@default_data_objects[load_object_class])
|
234
|
-
#
|
235
|
-
# @default_data_objects[load_object_class] = load_object_class.new
|
236
|
-
|
237
|
-
# default_data_object = @default_data_objects[load_object_class]
|
238
|
-
|
239
|
-
|
240
|
-
# default_data_object.instance_eval do
|
241
|
-
# def datashift_defaults=(hash)
|
242
|
-
# @datashift_defaults = hash
|
243
|
-
# end
|
244
|
-
# def datashift_defaults
|
245
|
-
# @datashift_defaults
|
246
|
-
# end
|
247
|
-
#end unless load_object_class.respond_to?(:datashift_defaults)
|
248
|
-
#end
|
249
|
-
|
250
|
-
#puts load_object_class.new.to_yaml
|
251
|
-
|
252
|
-
logger.info("Read Datashift loading config: #{data.inspect}")
|
253
|
-
|
330
|
+
data = YAML::load( ERB.new( IO.read(yaml_file) ).result )
|
331
|
+
|
332
|
+
# TODO - MOVE DEFAULTS TO OWN MODULE
|
333
|
+
|
334
|
+
logger.info("Setting Populator defaults: #{data.inspect}")
|
335
|
+
|
254
336
|
if(data[load_object_class.name])
|
255
|
-
|
256
|
-
logger.info("Assigning defaults and over rides from config")
|
257
|
-
|
337
|
+
|
258
338
|
deflts = data[load_object_class.name]['datashift_defaults']
|
259
339
|
default_values.merge!(deflts) if deflts
|
260
|
-
|
340
|
+
|
341
|
+
logger.info("Set Populator default_values: #{default_values.inspect}")
|
342
|
+
|
261
343
|
ovrides = data[load_object_class.name]['datashift_overrides']
|
262
344
|
override_values.merge!(ovrides) if ovrides
|
345
|
+
logger.info("Set Populator overrides: #{override_values.inspect}")
|
346
|
+
|
347
|
+
subs = data[load_object_class.name]['datashift_substitutions']
|
348
|
+
|
349
|
+
subs.each do |o, sub|
|
350
|
+
# TODO support single array as well as multiple [[..,..], [....]]
|
351
|
+
sub.each { |tuple| set_substitution(o, tuple) }
|
352
|
+
end if(subs)
|
353
|
+
|
263
354
|
end
|
264
|
-
|
265
355
|
|
266
356
|
end
|
267
|
-
|
357
|
+
|
358
|
+
# Set a default value to be used to populate Model.operator
|
359
|
+
# Generally defaults will be used when no value supplied.
|
360
|
+
def set_substitution(operator, value )
|
361
|
+
substitutions[operator] ||= []
|
362
|
+
|
363
|
+
substitutions[operator] << Struct::Substitution.new(value[0], value[1])
|
364
|
+
end
|
365
|
+
|
366
|
+
def substitutions
|
367
|
+
@substitutions ||= {}
|
368
|
+
end
|
369
|
+
|
370
|
+
def substitute( operator )
|
371
|
+
subs = substitutions[operator] || {}
|
372
|
+
|
373
|
+
subs.each do |s|
|
374
|
+
@original_value_before_override = @current_value
|
375
|
+
@current_value = @original_value_before_override.gsub(s.pattern.to_s, s.replacement.to_s)
|
376
|
+
end
|
377
|
+
end
|
378
|
+
|
379
|
+
|
268
380
|
# Set a value to be used to populate Model.operator
|
269
381
|
# Generally over-rides will be used regardless of what value caller supplied.
|
270
382
|
def set_override_value( operator, value )
|
271
383
|
override_values[operator] = value
|
272
384
|
end
|
273
|
-
|
385
|
+
|
274
386
|
def override_values
|
275
387
|
@override_values ||= {}
|
276
388
|
end
|
277
|
-
|
389
|
+
|
278
390
|
def override_value( operator )
|
279
391
|
if(override_values[operator])
|
280
392
|
@original_value_before_override = @current_value
|
281
|
-
|
393
|
+
|
282
394
|
@current_value = @override_values[operator]
|
283
395
|
end
|
284
396
|
end
|
285
|
-
|
397
|
+
|
398
|
+
|
399
|
+
def has_override?( operator )
|
400
|
+
return override_values.has_key?(operator)
|
401
|
+
end
|
402
|
+
|
286
403
|
# Set a default value to be used to populate Model.operator
|
287
404
|
# Generally defaults will be used when no value supplied.
|
288
405
|
def set_default_value(operator, value )
|
289
406
|
default_values[operator] = value
|
290
407
|
end
|
291
|
-
|
408
|
+
|
292
409
|
def default_values
|
293
410
|
@default_values ||= {}
|
294
411
|
end
|
295
|
-
|
412
|
+
|
296
413
|
# Return the default value for supplied operator
|
297
414
|
def default_value(operator)
|
298
415
|
default_values[operator]
|
299
416
|
end
|
300
|
-
|
301
417
|
|
302
418
|
def set_prefix( operator, value )
|
303
419
|
prefixes[operator] = value
|
@@ -310,7 +426,7 @@ module DataShift
|
|
310
426
|
def prefixes
|
311
427
|
@prefixes ||= {}
|
312
428
|
end
|
313
|
-
|
429
|
+
|
314
430
|
def set_postfix(operator, value )
|
315
431
|
postfixes[operator] = value
|
316
432
|
end
|
@@ -318,12 +434,11 @@ module DataShift
|
|
318
434
|
def postfix(operator)
|
319
435
|
postfixes[operator]
|
320
436
|
end
|
321
|
-
|
437
|
+
|
322
438
|
def postfixes
|
323
439
|
@postfixes ||= {}
|
324
440
|
end
|
325
|
-
|
326
|
-
|
441
|
+
|
327
442
|
end
|
328
|
-
|
443
|
+
|
329
444
|
end
|