ncs_mdes_warehouse 0.0.1 → 0.0.2

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/.gitignore CHANGED
@@ -5,3 +5,4 @@ docs
5
5
  reports
6
6
  *.sqlite3
7
7
  logs
8
+ pkg
data/CHANGELOG.md CHANGED
@@ -1,6 +1,13 @@
1
1
  NCS Navigator MDES Warehouse History
2
2
  ====================================
3
3
 
4
+ 0.0.2
5
+ -----
6
+
7
+ - Added `model_row` helper in Transformers::Database for
8
+ heuristic-based semi-automatic mapping of transactional data to
9
+ warehouse entries.
10
+
4
11
  0.0.1
5
12
  -----
6
13
 
@@ -2,6 +2,7 @@ require 'ncs_navigator/warehouse'
2
2
 
3
3
  require 'active_support/core_ext/string'
4
4
  require 'forwardable'
5
+ require 'data_mapper'
5
6
 
6
7
  module NcsNavigator::Warehouse::Transformers
7
8
  ##
@@ -93,6 +94,7 @@ module NcsNavigator::Warehouse::Transformers
93
94
  def repository
94
95
  @repository ||=
95
96
  begin
97
+ log.debug("Connecting DM repo #{repository_name.inspect} with #{connection_parameters.merge('password' => 'SUPPRESSED').inspect}")
96
98
  ::DataMapper.setup(repository_name, connection_parameters)
97
99
  ::DataMapper.repository(repository_name)
98
100
  end
@@ -173,6 +175,33 @@ module NcsNavigator::Warehouse::Transformers
173
175
  @repository_name ||= name.demodulize.underscore.to_sym
174
176
  end
175
177
 
178
+ ##
179
+ # What to do if are encountered by {#model_row}. Default is
180
+ # `:ignore` but may be set to `:fail` for all producers using
181
+ # this method. The value set here may be overridden per
182
+ # {#model_row} call.
183
+ #
184
+ # @return [:ignore, :fail]
185
+ def on_unused_columns(setting=nil)
186
+ if setting
187
+ @on_unused_columns = setting
188
+ else
189
+ @on_unused_columns ||= :ignore
190
+ end
191
+ end
192
+
193
+ ##
194
+ # Indicates a set of columns which which should not be checked
195
+ # for used-ness by {#model_row}, even if the `:unused` option is
196
+ # set to `:fail`.
197
+ def ignored_columns(*columns)
198
+ if columns.empty?
199
+ @ignored_columns ||= []
200
+ else
201
+ @ignored_columns = columns.collect(&:to_sym)
202
+ end
203
+ end
204
+
176
205
  ##
177
206
  # Defines the bcdatabase specification to use when connecting to
178
207
  # the database for this enumeration.
@@ -211,6 +240,126 @@ module NcsNavigator::Warehouse::Transformers
211
240
  def produce_records(name, options={}, &logic)
212
241
  record_producers << RecordProducer.new(name, options[:query], logic)
213
242
  end
243
+
244
+ ##
245
+ # Performs automatic conversion from a row struct to a
246
+ # an instance of a particular warehouse model. This conversion
247
+ # uses several heuristics to apply values from the row to the
248
+ # model instance. Each column in the row will be converted into
249
+ # at most one model property value. In the order that they are
250
+ # applied, the heuristics are:
251
+ #
252
+ # * If there's a `:prefix` option, the column is named {X},
253
+ # and there's a property named {prefix}{X}, use that
254
+ # property.
255
+ # * If the column is named {X} and there's a property named
256
+ # {X}, use that property.
257
+ # * If the column is named {X}_code and there's a property
258
+ # named {X}, use that property.
259
+ # * If the column is named {X}_code and there's a property
260
+ # named {X}_id, use that property.
261
+ # * If the column is named {X}_other and there's a property
262
+ # named {X}_oth, use that property.
263
+ #
264
+ # Separately, any property value in the instance may be
265
+ # explicitly set via a hash passed as the `:explicit`
266
+ # option. Property values in `:explicit` take precedence over
267
+ # the heuristically-determined values.
268
+ #
269
+ # @param [Class] model the warehouse model class (e.g.,
270
+ # `NcsNavigator::Warehouse::Models::TwoPointZero::Person`)
271
+ # @param [Object] row a DataMapper row struct that is the source
272
+ # of the data for the instance. (This is the kind of object
273
+ # that is yielded to {#produce_records} blocks.)
274
+ # @param [Hash] options Options controlling the created
275
+ # instance.
276
+ #
277
+ # @option options :prefix [String] a prefix to use when looking
278
+ # for matching property values. (See above.)
279
+ # @option options :column_map [Hash<Symbol, Symbol>] explicit
280
+ # mapping from column name to model property name. This
281
+ # mapping is consulted before the heuristics are applied and
282
+ # before `:property_values` is used.
283
+ # @option options :property_values [Hash<Symbol, Object>]
284
+ # explicit values to use. Keys are model property names and
285
+ # values are the desired values. Any values in this hash trump
286
+ # the heuristically-determined values.
287
+ # @option options :on_unused [:ignore,:fail] what to do when
288
+ # there are columns in the row which are not used.
289
+ # @option options :ignored_columns [Array<String,Symbol>]
290
+ # columns to consider "used" even if the heuristic doesn't
291
+ # match them to anything.
292
+ #
293
+ # @return [Object] an instance of `model`.
294
+ def model_row(model, row, options={})
295
+ unused_behavior = options[:on_unused] || on_unused_columns
296
+ pv, unused = create_property_values(model, row, options)
297
+
298
+ unused -= ignored_columns
299
+ unused -= options[:ignored_or_used].collect(&:to_sym) if options[:ignored_or_used]
300
+
301
+ if unused_behavior == :fail && !unused.empty?
302
+ raise UnusedColumnsForModelError.new(unused)
303
+ end
304
+ model.new(pv)
305
+ end
306
+
307
+ ##
308
+ # Returns a two-member array. The first member is the matched
309
+ # property values. The second is the columns from the row which
310
+ # were not matched to anything.
311
+ def create_property_values(model, row, options)
312
+ column_map = (options[:column_map] || {}).inject({}) { |h, (k, v)| h[k.to_s] = v.to_s; h }
313
+
314
+ pv = (options[:property_values] || {}).inject({}) { |h, (k, v)| h[k.to_s] = v; h }
315
+ column_map.values.each { |prop| pv.delete(prop) }
316
+
317
+ available_props = model.properties.collect { |p| p.name.to_s }
318
+ available_props -= pv.keys
319
+
320
+ unused = []
321
+ row.members.each do |column|
322
+ prop =
323
+ if column_map[column.to_s]
324
+ column_map[column.to_s]
325
+ else
326
+ [
327
+ [//, ''],
328
+ [/_code$/, ''],
329
+ [/_code$/, '_id'],
330
+ [/_other$/, '_oth'],
331
+ ].collect do |pattern, substution|
332
+ if column =~ pattern
333
+ prefixed_property_name(available_props,
334
+ column.to_s.sub(pattern, substution), options[:prefix])
335
+ end
336
+ end.compact.first
337
+ end
338
+ if prop
339
+ available_props.delete(prop)
340
+ pv[prop] = row[column]
341
+ else
342
+ unused << column.to_sym
343
+ end
344
+ end
345
+ [pv, unused]
346
+ end
347
+ private :create_property_values
348
+
349
+ ##
350
+ # Determines if the model has a property with the given name,
351
+ # with or without the prefix.
352
+ #
353
+ # @return [String,nil] the name of an existing property on the
354
+ # model, either with or without the prefix; or nil.
355
+ def prefixed_property_name(available_props, name, prefix)
356
+ if prefix && available_props.include?(prop = "#{prefix}#{name}")
357
+ prop
358
+ elsif available_props.include?(name)
359
+ name
360
+ end
361
+ end
362
+ private :prefixed_property_name
214
363
  end
215
364
 
216
365
  ##
@@ -232,5 +381,16 @@ module NcsNavigator::Warehouse::Transformers
232
381
  EnumTransformer.new(new(configuration, options))
233
382
  end
234
383
  end
384
+
385
+ class UnusedColumnsForModelError < StandardError
386
+ attr_accessor :unused
387
+
388
+ def initialize(unused)
389
+ super(
390
+ "#{unused.size} unused column#{'s' unless unused.size == 1} when building model. " +
391
+ "Use :ignored_or_used => %w(#{unused.join(' ')}) or :unused => :ignore to suppress this error.")
392
+ @unused = unused
393
+ end
394
+ end
235
395
  end
236
396
  end
@@ -1,5 +1,5 @@
1
1
  module NcsNavigator
2
2
  module Warehouse
3
- VERSION = '0.0.1'
3
+ VERSION = '0.0.2'
4
4
  end
5
5
  end
@@ -18,7 +18,7 @@ Gem::Specification.new do |s|
18
18
  s.add_dependency 'ncs_mdes', '~> 0.4', '>= 0.4.2'
19
19
  s.add_dependency 'ncs_navigator_configuration', '~> 0.1'
20
20
 
21
- s.add_dependency 'activesupport', '~> 3.0.9'
21
+ s.add_dependency 'activesupport', '~> 3.0'
22
22
  s.add_dependency 'i18n', '~> 0.6' # required by activesupport
23
23
 
24
24
  s.add_dependency 'thor', '~> 0.14.6'
@@ -167,6 +167,15 @@ module NcsNavigator::Warehouse::Transformers
167
167
 
168
168
  acc.should == %w(A)
169
169
  end
170
+
171
+ it 'can execute just one producer by calling :to_a' do
172
+ execute_sql(
173
+ "INSERT INTO people (id) VALUES ('B')",
174
+ "INSERT INTO more_people (id) VALUES ('Q')"
175
+ )
176
+
177
+ enumerator.to_a(:people).should == %w(B)
178
+ end
170
179
  end
171
180
  end
172
181
 
@@ -190,5 +199,181 @@ module NcsNavigator::Warehouse::Transformers
190
199
  end
191
200
  end
192
201
  end
202
+
203
+ describe Database::DSL do
204
+ describe '#on_unused_columns' do
205
+ it 'defaults to :ignore' do
206
+ sample_class.on_unused_columns.should == :ignore
207
+ end
208
+
209
+ it 'can be set' do
210
+ sample_class { on_unused_columns :fail }.on_unused_columns.should == :fail
211
+ end
212
+ end
213
+
214
+ describe '#model_row' do
215
+ # DataMapper models can't be anonymous
216
+ module Database::DSL::TestModels
217
+ class Address
218
+ include ::DataMapper::Resource
219
+
220
+ property :address_id, String, :key => true
221
+ property :street, NcsNavigator::Warehouse::DataMapper::NcsString
222
+ property :address_type,
223
+ NcsNavigator::Warehouse::DataMapper::NcsString,
224
+ { :required => true, :length => 1..2, :set => ["1", "2", "3", "4", "5", "-5", "-6", "-4"] }
225
+ property :address_type_oth,
226
+ NcsNavigator::Warehouse::DataMapper::NcsString,
227
+ { :pii => :possible, :length => 0..255 }
228
+ end
229
+
230
+ Address.finalize
231
+ end
232
+
233
+ let(:address_model) { Database::DSL::TestModels::Address }
234
+
235
+ let(:options) { {} }
236
+ let(:cls) { sample_class }
237
+
238
+ def make_row(contents)
239
+ Struct.new(*contents.keys).new.tap do |r|
240
+ contents.each_pair do |c, v|
241
+ r.send("#{c}=", v)
242
+ end
243
+ end
244
+ end
245
+
246
+ def model_row(row)
247
+ cls.model_row(address_model, make_row(row), options)
248
+ end
249
+
250
+ it 'maps a column to the property with the same name' do
251
+ model_row(:street => '123 Anymain Dr.').street.should == '123 Anymain Dr.'
252
+ end
253
+
254
+ it 'maps a column named {X}_code to a property named {X}' do
255
+ model_row(:address_type_code => '5').address_type.should == '5'
256
+ end
257
+
258
+ it 'maps a column named {X}_code to a property named {X}_id' do
259
+ model_row(:address_code => '-7').address_id.should == '-7'
260
+ end
261
+
262
+ it 'maps a column named {X}_other to a property named {X}_oth' do
263
+ model_row(:address_type_other => 'Elephant graveyard').address_type_oth.
264
+ should == 'Elephant graveyard'
265
+ end
266
+
267
+ describe 'and unused columns' do
268
+ it 'fails with unused columns if requested' do
269
+ options[:on_unused] = :fail
270
+ begin
271
+ model_row(:address_type => '-5', :address_length => '6')
272
+ fail "Exception not thrown"
273
+ rescue Database::UnusedColumnsForModelError => e
274
+ e.unused.should == [:address_length]
275
+ end
276
+ end
277
+
278
+ it 'does not fail if the unused column is ignored in the options' do
279
+ options[:on_unused] = :fail
280
+ options[:ignored_or_used] = %w(address_length)
281
+ lambda { model_row(:address_type => '-5', :address_length => '6') }.
282
+ should_not raise_error
283
+ end
284
+
285
+ it 'does not fail if the unused column is ignored at the class level' do
286
+ options[:on_unused] = :fail
287
+ cls.ignored_columns 'address_length'
288
+ lambda { model_row(:address_type => '-5', :address_length => '6') }.
289
+ should_not raise_error
290
+ end
291
+
292
+ describe 'when #on_unused_columns is set to :fail' do
293
+ let(:cls) {
294
+ sample_class do
295
+ on_unused_columns :fail
296
+ end
297
+ }
298
+
299
+ it 'fails appropriately' do
300
+ begin
301
+ model_row(:address_type => '-5', :address_length => '6')
302
+ fail "Exception not thrown"
303
+ rescue Database::UnusedColumnsForModelError => e
304
+ e.unused.should == [:address_length]
305
+ end
306
+ end
307
+
308
+ it 'does not fail if the global setting is overridden' do
309
+ options[:on_unused] = :ignore
310
+ lambda { model_row(:address_type => '-5', :address_length => '6') }.
311
+ should_not raise_error
312
+ end
313
+ end
314
+ end
315
+
316
+ describe 'with a prefix' do
317
+ before do
318
+ options[:prefix] = 'address_'
319
+ end
320
+
321
+ it 'maps a column to {prefix}_{property_name}' do
322
+ model_row(:type => '-4').address_type.should == '-4'
323
+ end
324
+
325
+ it 'still maps a column to {property_name} if there is no prefixed version' do
326
+ model_row(:street => '123 Anymain Dr.').street.should == '123 Anymain Dr.'
327
+ end
328
+
329
+ it 'maps a column named {X}_code to {prefix}{X}' do
330
+ model_row(:type_code => '1').address_type.should == '1'
331
+ end
332
+ end
333
+
334
+ describe 'with a column map' do
335
+ before do
336
+ options[:column_map] = { :street_loc => :street }
337
+ end
338
+
339
+ it 'uses the value specified by the map' do
340
+ model_row(:street_loc => '123 Anymain Dr.').street.should == '123 Anymain Dr.'
341
+ end
342
+
343
+ it 'prefers the mapped value to a heuristically-determined value' do
344
+ model_row(
345
+ :street_loc => '123 Anymain Dr.', :street => '456 Anywhere St.'
346
+ ).street.should == '123 Anymain Dr.'
347
+ end
348
+
349
+ it 'prefers the mapped column value to an explicit property value' do
350
+ options[:property_values] = { :street => '456 Anywhere St.' }
351
+ model_row(:street_loc => '123 Anymain Dr.').street.should == '123 Anymain Dr.'
352
+ end
353
+ end
354
+
355
+ describe 'with property value mappings' do
356
+ before do
357
+ options[:property_values] = {
358
+ :street => '456 Anywhere St.'
359
+ }
360
+ end
361
+
362
+ it 'prefers the explicit mapping to a column' do
363
+ model_row(:street => '123 Anymain Dr.').street.should == '456 Anywhere St.'
364
+ end
365
+
366
+ it 'reports the column as unused' do
367
+ options[:on_unused] = :fail
368
+ begin
369
+ model_row(:street => '123 Anymain Dr.').street.should == '456 Anywhere St.'
370
+ fail "Exception not thrown"
371
+ rescue Database::UnusedColumnsForModelError => e
372
+ e.unused.should include(:street)
373
+ end
374
+ end
375
+ end
376
+ end
377
+ end
193
378
  end
194
379
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ncs_mdes_warehouse
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.1
4
+ version: 0.0.2
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,11 +9,11 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2011-10-28 00:00:00.000000000Z
12
+ date: 2011-11-04 00:00:00.000000000Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: ncs_mdes
16
- requirement: &2154987140 !ruby/object:Gem::Requirement
16
+ requirement: &2159237800 !ruby/object:Gem::Requirement
17
17
  none: false
18
18
  requirements:
19
19
  - - ~>
@@ -24,10 +24,10 @@ dependencies:
24
24
  version: 0.4.2
25
25
  type: :runtime
26
26
  prerelease: false
27
- version_requirements: *2154987140
27
+ version_requirements: *2159237800
28
28
  - !ruby/object:Gem::Dependency
29
29
  name: ncs_navigator_configuration
30
- requirement: &2154986380 !ruby/object:Gem::Requirement
30
+ requirement: &2159236980 !ruby/object:Gem::Requirement
31
31
  none: false
32
32
  requirements:
33
33
  - - ~>
@@ -35,21 +35,21 @@ dependencies:
35
35
  version: '0.1'
36
36
  type: :runtime
37
37
  prerelease: false
38
- version_requirements: *2154986380
38
+ version_requirements: *2159236980
39
39
  - !ruby/object:Gem::Dependency
40
40
  name: activesupport
41
- requirement: &2154985920 !ruby/object:Gem::Requirement
41
+ requirement: &2159236440 !ruby/object:Gem::Requirement
42
42
  none: false
43
43
  requirements:
44
44
  - - ~>
45
45
  - !ruby/object:Gem::Version
46
- version: 3.0.9
46
+ version: '3.0'
47
47
  type: :runtime
48
48
  prerelease: false
49
- version_requirements: *2154985920
49
+ version_requirements: *2159236440
50
50
  - !ruby/object:Gem::Dependency
51
51
  name: i18n
52
- requirement: &2154985420 !ruby/object:Gem::Requirement
52
+ requirement: &2159235940 !ruby/object:Gem::Requirement
53
53
  none: false
54
54
  requirements:
55
55
  - - ~>
@@ -57,10 +57,10 @@ dependencies:
57
57
  version: '0.6'
58
58
  type: :runtime
59
59
  prerelease: false
60
- version_requirements: *2154985420
60
+ version_requirements: *2159235940
61
61
  - !ruby/object:Gem::Dependency
62
62
  name: thor
63
- requirement: &2154984960 !ruby/object:Gem::Requirement
63
+ requirement: &2159235400 !ruby/object:Gem::Requirement
64
64
  none: false
65
65
  requirements:
66
66
  - - ~>
@@ -68,10 +68,10 @@ dependencies:
68
68
  version: 0.14.6
69
69
  type: :runtime
70
70
  prerelease: false
71
- version_requirements: *2154984960
71
+ version_requirements: *2159235400
72
72
  - !ruby/object:Gem::Dependency
73
73
  name: rubyzip
74
- requirement: &2154984420 !ruby/object:Gem::Requirement
74
+ requirement: &2159234800 !ruby/object:Gem::Requirement
75
75
  none: false
76
76
  requirements:
77
77
  - - ~>
@@ -79,10 +79,10 @@ dependencies:
79
79
  version: 0.9.4
80
80
  type: :runtime
81
81
  prerelease: false
82
- version_requirements: *2154984420
82
+ version_requirements: *2159234800
83
83
  - !ruby/object:Gem::Dependency
84
84
  name: nokogiri
85
- requirement: &2154983960 !ruby/object:Gem::Requirement
85
+ requirement: &2159234100 !ruby/object:Gem::Requirement
86
86
  none: false
87
87
  requirements:
88
88
  - - ~>
@@ -90,10 +90,10 @@ dependencies:
90
90
  version: 1.5.0
91
91
  type: :runtime
92
92
  prerelease: false
93
- version_requirements: *2154983960
93
+ version_requirements: *2159234100
94
94
  - !ruby/object:Gem::Dependency
95
95
  name: builder
96
- requirement: &2154983480 !ruby/object:Gem::Requirement
96
+ requirement: &2159233480 !ruby/object:Gem::Requirement
97
97
  none: false
98
98
  requirements:
99
99
  - - ~>
@@ -101,10 +101,10 @@ dependencies:
101
101
  version: '3.0'
102
102
  type: :runtime
103
103
  prerelease: false
104
- version_requirements: *2154983480
104
+ version_requirements: *2159233480
105
105
  - !ruby/object:Gem::Dependency
106
106
  name: data_mapper
107
- requirement: &2154982940 !ruby/object:Gem::Requirement
107
+ requirement: &2159232820 !ruby/object:Gem::Requirement
108
108
  none: false
109
109
  requirements:
110
110
  - - ~>
@@ -112,10 +112,10 @@ dependencies:
112
112
  version: 1.2.0
113
113
  type: :runtime
114
114
  prerelease: false
115
- version_requirements: *2154982940
115
+ version_requirements: *2159232820
116
116
  - !ruby/object:Gem::Dependency
117
117
  name: bcdatabase
118
- requirement: &2154982440 !ruby/object:Gem::Requirement
118
+ requirement: &2159232220 !ruby/object:Gem::Requirement
119
119
  none: false
120
120
  requirements:
121
121
  - - ~>
@@ -123,10 +123,10 @@ dependencies:
123
123
  version: '1.1'
124
124
  type: :runtime
125
125
  prerelease: false
126
- version_requirements: *2154982440
126
+ version_requirements: *2159232220
127
127
  - !ruby/object:Gem::Dependency
128
128
  name: dm-postgres-adapter
129
- requirement: &2154981960 !ruby/object:Gem::Requirement
129
+ requirement: &2159231600 !ruby/object:Gem::Requirement
130
130
  none: false
131
131
  requirements:
132
132
  - - ~>
@@ -134,10 +134,10 @@ dependencies:
134
134
  version: 1.2.0
135
135
  type: :runtime
136
136
  prerelease: false
137
- version_requirements: *2154981960
137
+ version_requirements: *2159231600
138
138
  - !ruby/object:Gem::Dependency
139
139
  name: rspec
140
- requirement: &2154981460 !ruby/object:Gem::Requirement
140
+ requirement: &2159230940 !ruby/object:Gem::Requirement
141
141
  none: false
142
142
  requirements:
143
143
  - - ~>
@@ -145,10 +145,10 @@ dependencies:
145
145
  version: '2.6'
146
146
  type: :development
147
147
  prerelease: false
148
- version_requirements: *2154981460
148
+ version_requirements: *2159230940
149
149
  - !ruby/object:Gem::Dependency
150
150
  name: rake
151
- requirement: &2154981000 !ruby/object:Gem::Requirement
151
+ requirement: &2159230280 !ruby/object:Gem::Requirement
152
152
  none: false
153
153
  requirements:
154
154
  - - ~>
@@ -156,10 +156,10 @@ dependencies:
156
156
  version: 0.9.2
157
157
  type: :development
158
158
  prerelease: false
159
- version_requirements: *2154981000
159
+ version_requirements: *2159230280
160
160
  - !ruby/object:Gem::Dependency
161
161
  name: yard
162
- requirement: &2154953340 !ruby/object:Gem::Requirement
162
+ requirement: &2159225600 !ruby/object:Gem::Requirement
163
163
  none: false
164
164
  requirements:
165
165
  - - ~>
@@ -167,10 +167,10 @@ dependencies:
167
167
  version: 0.7.2
168
168
  type: :development
169
169
  prerelease: false
170
- version_requirements: *2154953340
170
+ version_requirements: *2159225600
171
171
  - !ruby/object:Gem::Dependency
172
172
  name: ci_reporter
173
- requirement: &2154952780 !ruby/object:Gem::Requirement
173
+ requirement: &2159225100 !ruby/object:Gem::Requirement
174
174
  none: false
175
175
  requirements:
176
176
  - - ~>
@@ -178,10 +178,10 @@ dependencies:
178
178
  version: 1.6.5
179
179
  type: :development
180
180
  prerelease: false
181
- version_requirements: *2154952780
181
+ version_requirements: *2159225100
182
182
  - !ruby/object:Gem::Dependency
183
183
  name: fakefs
184
- requirement: &2154952200 !ruby/object:Gem::Requirement
184
+ requirement: &2159224500 !ruby/object:Gem::Requirement
185
185
  none: false
186
186
  requirements:
187
187
  - - ~>
@@ -189,7 +189,7 @@ dependencies:
189
189
  version: 0.4.0
190
190
  type: :development
191
191
  prerelease: false
192
- version_requirements: *2154952200
192
+ version_requirements: *2159224500
193
193
  description:
194
194
  email:
195
195
  - r-sutphin@northwestern.edu
@@ -529,7 +529,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
529
529
  version: '0'
530
530
  segments:
531
531
  - 0
532
- hash: 1308600136922814816
532
+ hash: 3545445795691480899
533
533
  required_rubygems_version: !ruby/object:Gem::Requirement
534
534
  none: false
535
535
  requirements:
@@ -538,7 +538,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
538
538
  version: '0'
539
539
  segments:
540
540
  - 0
541
- hash: 1308600136922814816
541
+ hash: 3545445795691480899
542
542
  requirements: []
543
543
  rubyforge_project:
544
544
  rubygems_version: 1.8.10