hoodoo 1.1.2 → 1.1.3
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +8 -8
- data/lib/hoodoo/active/active_record/finder.rb +26 -42
- data/lib/hoodoo/version.rb +1 -1
- data/spec/active/active_record/finder_spec.rb +50 -30
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,15 +1,15 @@
|
|
1
1
|
---
|
2
2
|
!binary "U0hBMQ==":
|
3
3
|
metadata.gz: !binary |-
|
4
|
-
|
4
|
+
NWM1MTMyZWRmNGNkZDExY2IyYThiYjdhZDA2OGJmNWFiNTY2NDY4ZA==
|
5
5
|
data.tar.gz: !binary |-
|
6
|
-
|
6
|
+
N2YwMGE5ODIxNmFiNzEzMDc4YjE3YTk1ZWZiOTk2ODJhNTJmNjFhOQ==
|
7
7
|
SHA512:
|
8
8
|
metadata.gz: !binary |-
|
9
|
-
|
10
|
-
|
11
|
-
|
9
|
+
MmY2ODExNTRkZmJiYThmN2MyNGFkYTk0MjU4YjBhMzFkMTExZmU2YmNiMDNk
|
10
|
+
MjAwYzQ4NzRiM2FlMTA5NjQxNjdlMzM3OTA3YzQ3NzA2N2FlMTRhYTI4OGY4
|
11
|
+
NWUzNjFlNTE4NjdiNmE4YzMwYmZmMTJkZTg4NTdiZWVlYTVkODg=
|
12
12
|
data.tar.gz: !binary |-
|
13
|
-
|
14
|
-
|
15
|
-
|
13
|
+
ZjViMjVmM2FjMzY5YzBmYTU2NTljM2FiMjAwNWU3OTRiYzZhZjdiMmMzNzgz
|
14
|
+
MmE2ZmNjYWE2NTA4MGU4ODkwNjhlOTI0OGRlNjQ5ZjM1ZjIxYTI0ZjA5YWMz
|
15
|
+
ZGQ1OWIyYzNhMzBmZTU4Njk2Nzc0YmJjNWI4OGNhYmY4NDIwNjY=
|
@@ -152,48 +152,7 @@ module Hoodoo
|
|
152
152
|
# Returns a found model instance or +nil+ for no match.
|
153
153
|
#
|
154
154
|
def acquire( ident )
|
155
|
-
|
156
|
-
|
157
|
-
id_fields = [ :id ] + extra_fields
|
158
|
-
id_fields.each do | field |
|
159
|
-
|
160
|
-
# This is fiddly.
|
161
|
-
#
|
162
|
-
# You must use a string with field substitution approach, rather
|
163
|
-
# than e.g. ".where( :field => :ident )". AREL/ActiveRecord will,
|
164
|
-
# in the latter case, compose rational SQL based on column data
|
165
|
-
# types. If you have an *integer* ID field, then, it'll try to
|
166
|
-
# convert a *string* ident to an integer. This can give Hilarious
|
167
|
-
# Consequences. Consider looking up on (integer) field "id" or
|
168
|
-
# (text) field "uuid", with a string ident of "1f294942..." - the
|
169
|
-
# text UUID would be fine, but the integer ID may end up with the
|
170
|
-
# UUID being "to_i"'d, yielding integer 1. If the ID field is
|
171
|
-
# looked at first, you're highly likely to find the wrong record.
|
172
|
-
#
|
173
|
-
# The solution is, as written, simple; just use the substitution
|
174
|
-
# approach rather than higher level AREL, causing a string-like SQL
|
175
|
-
# query on all adapters which SQL handles just fine for varying
|
176
|
-
# field data types.
|
177
|
-
#
|
178
|
-
# The caveat is that should the database object to mismatched type
|
179
|
-
# comparisons it will actually raise an error - we see this on
|
180
|
-
# for example PostgreSQL where a column is an integer but we try
|
181
|
-
# to match it against a string that cannot be cleanly converted to
|
182
|
-
# one (e.g. trying to find an integer column 'id' based on a text
|
183
|
-
# UUID value containing alphabetic characters). That is still
|
184
|
-
# preferable to looking up the wrong record!
|
185
|
-
|
186
|
-
checker = where( [ "\"#{ self.table_name }\".\"#{ field }\" = ?", ident ] )
|
187
|
-
|
188
|
-
# If we have found a record return it, otherwise continue to loop
|
189
|
-
# through +id_fields+
|
190
|
-
#
|
191
|
-
if checker.first
|
192
|
-
return checker.first
|
193
|
-
end
|
194
|
-
end
|
195
|
-
|
196
|
-
return nil
|
155
|
+
return acquisition_scope( ident ).first
|
197
156
|
end
|
198
157
|
|
199
158
|
# Implicily secure, translated, dated etc. etc. version of #acquire,
|
@@ -294,6 +253,31 @@ module Hoodoo
|
|
294
253
|
self.nz_co_loyalty_hoodoo_show_id_fields || []
|
295
254
|
end
|
296
255
|
|
256
|
+
# Back-end to #acquire and therefore, in turn, #acquire_in. Returns
|
257
|
+
# an ActiveRecord::Relation instance which scopes the search for a
|
258
|
+
# record by +id+ and across any other columns specified by
|
259
|
+
# #acquire_with, via SQL +OR+.
|
260
|
+
#
|
261
|
+
# Normally such a scope could only ever return a single record based
|
262
|
+
# on an assuption of uniqueness constraints around columns which one
|
263
|
+
# might use in an equivalent of a +find+ call. In some instances
|
264
|
+
# however - e.g. a table that contains historic representations of a
|
265
|
+
# model as well as its 'current' representation - there may be more
|
266
|
+
# than one result and the returned value from this method may need to
|
267
|
+
# be chained in with other scopes to form a useful query.
|
268
|
+
#
|
269
|
+
def acquisition_scope( ident )
|
270
|
+
extra_fields = self.acquired_with()
|
271
|
+
arel_table = self.arel_table()
|
272
|
+
arel_query = arel_table[ :id ].eq( ident )
|
273
|
+
|
274
|
+
extra_fields.each do | field |
|
275
|
+
arel_query = arel_query.or( arel_table[ field ].eq( ident ) )
|
276
|
+
end
|
277
|
+
|
278
|
+
return where( arel_query )
|
279
|
+
end
|
280
|
+
|
297
281
|
# Generate an ActiveRecord::Relation instance which can be used to
|
298
282
|
# count, retrieve or further refine a list of model instances from
|
299
283
|
# the database.
|
data/lib/hoodoo/version.rb
CHANGED
@@ -154,47 +154,50 @@ describe Hoodoo::ActiveRecord::Finder do
|
|
154
154
|
expect( found ).to eq(nil) # Not in 'group 1'
|
155
155
|
end
|
156
156
|
|
157
|
-
#
|
158
|
-
#
|
157
|
+
# Early versions of the 'acquire'-backed methods always inadvertently
|
158
|
+
# performed two database calls, via a count then a true find. This was
|
159
|
+
# refactored to only make one call per attribute, but that in turn can
|
160
|
+
# be much improved via the AREL table to compose a single query that
|
161
|
+
# uses "OR" to get the database to check each attribute in order. Thus
|
162
|
+
# every test below expects exactly one database call only.
|
159
163
|
#
|
160
|
-
|
164
|
+
context 'only makes one database call when' do
|
161
165
|
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
# therefore only one call will be made
|
168
|
-
expect( count ).to eq( 1 )
|
166
|
+
it 'finding on the first attribute' do
|
167
|
+
count = count_database_calls_in do
|
168
|
+
found = RSpecModelFinderTest.acquire( @id )
|
169
|
+
expect( found ).to eq(@a)
|
170
|
+
end
|
169
171
|
|
170
|
-
|
171
|
-
found = RSpecModelFinderTest.acquire( @uuid )
|
172
|
-
expect( found ).to eq(@b)
|
172
|
+
expect( count ).to eq( 1 )
|
173
173
|
end
|
174
174
|
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
|
175
|
+
it 'finding on the second attribute' do
|
176
|
+
count = count_database_calls_in do
|
177
|
+
found = RSpecModelFinderTest.acquire( @uuid )
|
178
|
+
expect( found ).to eq(@b)
|
179
|
+
end
|
179
180
|
|
180
|
-
|
181
|
-
found = RSpecModelFinderTest.acquire( @code )
|
182
|
-
expect( found ).to eq(@c)
|
181
|
+
expect( count ).to eq( 1 )
|
183
182
|
end
|
184
183
|
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
|
184
|
+
it 'finding on the third attribute' do
|
185
|
+
count = count_database_calls_in do
|
186
|
+
found = RSpecModelFinderTest.acquire( @code )
|
187
|
+
expect( found ).to eq(@c)
|
188
|
+
end
|
190
189
|
|
191
|
-
|
192
|
-
found = RSpecModelFinderTest.acquire( Hoodoo::UUID.generate )
|
193
|
-
expect( found ).to be_nil
|
190
|
+
expect( count ).to eq( 1 )
|
194
191
|
end
|
195
192
|
|
196
|
-
|
197
|
-
|
193
|
+
it 'checking all three attributes but finding nothing' do
|
194
|
+
count = count_database_calls_in do
|
195
|
+
found = RSpecModelFinderTest.acquire( Hoodoo::UUID.generate )
|
196
|
+
expect( found ).to be_nil
|
197
|
+
end
|
198
|
+
|
199
|
+
expect( count ).to eq( 1 )
|
200
|
+
end
|
198
201
|
end
|
199
202
|
end
|
200
203
|
|
@@ -347,6 +350,23 @@ describe Hoodoo::ActiveRecord::Finder do
|
|
347
350
|
|
348
351
|
# ==========================================================================
|
349
352
|
|
353
|
+
context 'acquisition_scope' do
|
354
|
+
it 'SQL generation is as expected' do
|
355
|
+
sql = RSpecModelFinderTest.acquisition_scope( @id ).to_sql()
|
356
|
+
expect( sql ).to eq( "SELECT \"r_spec_model_finder_tests\".* "<<
|
357
|
+
"FROM \"r_spec_model_finder_tests\" " <<
|
358
|
+
"WHERE (" <<
|
359
|
+
"(" <<
|
360
|
+
"\"r_spec_model_finder_tests\".\"id\" = '#{ @id }' OR " <<
|
361
|
+
"\"r_spec_model_finder_tests\".\"uuid\" = '#{ @id }'" <<
|
362
|
+
") OR " <<
|
363
|
+
"\"r_spec_model_finder_tests\".\"code\" = '#{ @id }'" <<
|
364
|
+
")" )
|
365
|
+
end
|
366
|
+
end
|
367
|
+
|
368
|
+
# ==========================================================================
|
369
|
+
|
350
370
|
context 'lists' do
|
351
371
|
it 'lists with pages, offsets and counts' do
|
352
372
|
@list_params.offset = 1 # 0 is first record
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: hoodoo
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.1.
|
4
|
+
version: 1.1.3
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Loyalty New Zealand
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2016-02-
|
11
|
+
date: 2016-02-04 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: uuidtools
|