hoodoo 1.3.1 → 1.4.0
Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml
CHANGED
@@ -1,15 +1,15 @@
|
|
1
1
|
---
|
2
2
|
!binary "U0hBMQ==":
|
3
3
|
metadata.gz: !binary |-
|
4
|
-
|
4
|
+
OGQ2ZGRmYWM3NTIwOWEwOGIyNjFiOTkyN2I4ZDdhNzY1YWUzZWIyNw==
|
5
5
|
data.tar.gz: !binary |-
|
6
|
-
|
6
|
+
OWUxNzBkMjc2NzM5N2ViZDM5ZWY2ZjNjMDFhZjJiNDVmNzA5NDYxMA==
|
7
7
|
SHA512:
|
8
8
|
metadata.gz: !binary |-
|
9
|
-
|
10
|
-
|
11
|
-
|
9
|
+
MjE2MTQ5YTU0OWFkZWEyN2Y0YTU5ZDJhOWU5MjkwODI3MmViYWFmODg4ZDll
|
10
|
+
MWI5MjUyNjIzNGFjMWZiYmViYzhhYTcyZGQyZmRhMjk5M2ZjMjQzOWJiNWFl
|
11
|
+
Mzg4NWZlMDFhZjQ3MjA4ZmQxZWM1YzM5YTY4YTJiNTE4MjFjOGQ=
|
12
12
|
data.tar.gz: !binary |-
|
13
|
-
|
14
|
-
|
15
|
-
|
13
|
+
NWFlNzg2Y2E4ODg4ODY3MjYwMTRmMzQzZmYzMWQ0OGJkYzljZDdhZjY0ZmYw
|
14
|
+
YjUwNjljZjkwMWM5Y2ZjOTgwNmJiNTZkNzg4MGE3OTk4M2ZlOWQxZDEzMWQy
|
15
|
+
ZDJiYzBjNTAzMDkwOGIzYzI3MjU1OGQxMjk0MDg2OTcwMTdjMWY=
|
@@ -88,6 +88,27 @@ module Hoodoo
|
|
88
88
|
#
|
89
89
|
module ClassMethods
|
90
90
|
|
91
|
+
# Returns an ActiveRecord::Relation instance representing a primitive
|
92
|
+
# base scope that includes various context-related aspects according
|
93
|
+
# to the prevailing mixins included by "this" class, if any - e.g.
|
94
|
+
# security, dating and/or translation.
|
95
|
+
#
|
96
|
+
# See Hoodoo::ActiveRecord::Support#full_scope_for to see the list
|
97
|
+
# of things that get included. If there are no "interesting" mixins,
|
98
|
+
# the returned scope will just return the same thing that the +all+
|
99
|
+
# method in ActiveRecord would have returned. Consequently, a default
|
100
|
+
# scope _will_ be honoured if one has been declared, though default
|
101
|
+
# scopes are generally considered an anti-pattern to be avoided.
|
102
|
+
#
|
103
|
+
# +context+:: Hoodoo::Services::Context instance describing a call
|
104
|
+
# context. This is typically a value passed to one of
|
105
|
+
# the Hoodoo::Services::Implementation instance methods
|
106
|
+
# that a resource subclass implements.
|
107
|
+
#
|
108
|
+
def scoped_in( context )
|
109
|
+
Hoodoo::ActiveRecord::Support.full_scope_for( self, context )
|
110
|
+
end
|
111
|
+
|
91
112
|
# "Polymorphic" find - support for finding a model by fields other
|
92
113
|
# than just +:id+, based on a single unique identifier. Use #acquire
|
93
114
|
# just like you'd use +find_by_id+ and only bother with it if you
|
@@ -159,10 +180,11 @@ module Hoodoo
|
|
159
180
|
end
|
160
181
|
|
161
182
|
# Implicily secure, translated, dated etc. etc. version of #acquire,
|
162
|
-
# according to which modules are mixed into your model class.
|
163
|
-
#
|
164
|
-
#
|
165
|
-
# that
|
183
|
+
# according to which modules are mixed into your model class. Uses
|
184
|
+
# #scoped_in to obtain a base scope in which to operate, so it is
|
185
|
+
# "mixin aware" and incorporates other Hoodoo extensions within the
|
186
|
+
# wider scope chain. See that method's documentation for more
|
187
|
+
# information.
|
166
188
|
#
|
167
189
|
# For example, if you are using or at some point intend to mix in and
|
168
190
|
# use the mechanism described by the likes of
|
@@ -213,8 +235,7 @@ module Hoodoo
|
|
213
235
|
# SomeModel.acquire_in( context )
|
214
236
|
#
|
215
237
|
# The same applies to forgetting dated scopes, translated scopes, or
|
216
|
-
# anything else that
|
217
|
-
# might include for you.
|
238
|
+
# anything else that #scoped_in might include for you.
|
218
239
|
#
|
219
240
|
# Parameters:
|
220
241
|
#
|
@@ -226,8 +247,7 @@ module Hoodoo
|
|
226
247
|
# Returns a found model instance or +nil+ for no match.
|
227
248
|
#
|
228
249
|
def acquire_in( context )
|
229
|
-
|
230
|
-
return scope.acquire( context.request.ident )
|
250
|
+
return scoped_in( context ).acquire( context.request.ident )
|
231
251
|
end
|
232
252
|
|
233
253
|
# Describe the list of model fields _in_ _addition_ _to_ +id+ which
|
@@ -294,11 +314,13 @@ module Hoodoo
|
|
294
314
|
#
|
295
315
|
# Normally such a scope could only ever return a single record based
|
296
316
|
# on an assuption of uniqueness constraints around columns which one
|
297
|
-
# might use in an equivalent of a +find+ call.
|
298
|
-
#
|
299
|
-
#
|
300
|
-
#
|
301
|
-
#
|
317
|
+
# might use in an equivalent of a +find+ call. This scope is often
|
318
|
+
# chained on top of a wider listing scope provided by #scoped_in to
|
319
|
+
# create a fully context-aware, secure, dated, translated etc. query.
|
320
|
+
# It is possible however that the chosen +ident+ value might not
|
321
|
+
# resolve to a single unique record depending on how your data works
|
322
|
+
# and you may need to manually apply additional constraints to the
|
323
|
+
# returned ActiveRecord::Relation instance.
|
302
324
|
#
|
303
325
|
def acquisition_scope( ident )
|
304
326
|
extra_fields = self.acquired_with()
|
@@ -432,9 +454,8 @@ module Hoodoo
|
|
432
454
|
|
433
455
|
# Implicily secure, translated, dated etc. etc. version of #list,
|
434
456
|
# according to which modules are mixed into your model class. See
|
435
|
-
#
|
436
|
-
#
|
437
|
-
# that are in use.
|
457
|
+
# #scoped_in to see the list of things that get included in the
|
458
|
+
# scope according to the mixins that are in use.
|
438
459
|
#
|
439
460
|
# For example, if you have included Hoodoo::ActiveRecord::Secure,
|
440
461
|
# this method provides you with an implicitly secure query. Read the
|
@@ -450,8 +471,7 @@ module Hoodoo
|
|
450
471
|
# SomeModel.list_in( context )
|
451
472
|
#
|
452
473
|
# The same applies to forgetting dated scopes, translated scopes, or
|
453
|
-
# anything else that
|
454
|
-
# might include for you.
|
474
|
+
# anything else that #scoped_in might include for you.
|
455
475
|
#
|
456
476
|
# +context+:: Hoodoo::Services::Context instance describing a call
|
457
477
|
# context. This is typically a value passed to one of
|
@@ -462,8 +482,7 @@ module Hoodoo
|
|
462
482
|
# query methods like +where+ or fetching from the database with +all+.
|
463
483
|
#
|
464
484
|
def list_in( context )
|
465
|
-
|
466
|
-
return scope.list( context.request.list )
|
485
|
+
return scoped_in( context ).list( context.request.list )
|
467
486
|
end
|
468
487
|
|
469
488
|
# Given some scope - typically that obtained from a prior call to
|
data/lib/hoodoo/version.rb
CHANGED
@@ -129,7 +129,90 @@ describe Hoodoo::ActiveRecord::Finder do
|
|
129
129
|
|
130
130
|
# ==========================================================================
|
131
131
|
|
132
|
-
context '
|
132
|
+
context '#scoped_in' do
|
133
|
+
before :each do
|
134
|
+
|
135
|
+
# Get a good-enough-for-test interaction which has a context
|
136
|
+
# that contains a Session we can modify.
|
137
|
+
|
138
|
+
@interaction = Hoodoo::Services::Middleware::Interaction.new( {}, nil )
|
139
|
+
@interaction.context = Hoodoo::Services::Context.new(
|
140
|
+
Hoodoo::Services::Session.new,
|
141
|
+
@interaction.context.request,
|
142
|
+
@interaction.context.response,
|
143
|
+
@interaction
|
144
|
+
)
|
145
|
+
|
146
|
+
@context = @interaction.context
|
147
|
+
@session = @interaction.context.session
|
148
|
+
end
|
149
|
+
|
150
|
+
# If security scoping works _and_ we know that it called #full_scope_for
|
151
|
+
# in the "internal"-ish support API, then we consider that good enough
|
152
|
+
# to prove that it's calling the scope engine and that engine has its
|
153
|
+
# own comprehensive test coverage in suport_spec.rb.
|
154
|
+
#
|
155
|
+
it 'generates appropriate scope' do
|
156
|
+
@session.scoping = { :authorised_uuids => [ 'uuid 1', 'uuid 2' ], :authorised_code => 'code 1' }
|
157
|
+
|
158
|
+
expect( Hoodoo::ActiveRecord::Support ).to(
|
159
|
+
receive( :full_scope_for ).once().with(
|
160
|
+
RSpecModelFinderTest, @context
|
161
|
+
).and_call_original()
|
162
|
+
)
|
163
|
+
|
164
|
+
sql = RSpecModelFinderTest.scoped_in( @context ).to_sql
|
165
|
+
|
166
|
+
expect( sql ).to eq( "SELECT \"r_spec_model_finder_tests\".* "<<
|
167
|
+
"FROM \"r_spec_model_finder_tests\" " <<
|
168
|
+
"WHERE " <<
|
169
|
+
"\"r_spec_model_finder_tests\".\"uuid\" IN ('uuid 1', 'uuid 2') AND " <<
|
170
|
+
"\"r_spec_model_finder_tests\".\"code\" = 'code 1'" )
|
171
|
+
end
|
172
|
+
end
|
173
|
+
|
174
|
+
# ==========================================================================
|
175
|
+
|
176
|
+
context 'acquisition scope and overrides' do
|
177
|
+
def expect_sql( sql, id_attr_name )
|
178
|
+
expect( sql ).to eq( "SELECT \"r_spec_model_finder_tests\".* "<<
|
179
|
+
"FROM \"r_spec_model_finder_tests\" " <<
|
180
|
+
"WHERE (" <<
|
181
|
+
"(" <<
|
182
|
+
"\"r_spec_model_finder_tests\".\"#{ id_attr_name }\" = '#{ @id }' OR " <<
|
183
|
+
"\"r_spec_model_finder_tests\".\"uuid\" = '#{ @id }'" <<
|
184
|
+
") OR " <<
|
185
|
+
"\"r_spec_model_finder_tests\".\"code\" = '#{ @id }'" <<
|
186
|
+
")" )
|
187
|
+
end
|
188
|
+
|
189
|
+
context '#acquisition_scope' do
|
190
|
+
it 'SQL generation is as expected' do
|
191
|
+
sql = RSpecModelFinderTest.acquisition_scope( @id ).to_sql()
|
192
|
+
expect_sql( sql, 'id' )
|
193
|
+
end
|
194
|
+
end
|
195
|
+
|
196
|
+
context '#acquire_with_id_substitute' do
|
197
|
+
before :each do
|
198
|
+
@alt_attr_name = 'foo'
|
199
|
+
RSpecModelFinderTest.acquire_with_id_substitute( @alt_attr_name )
|
200
|
+
end
|
201
|
+
|
202
|
+
after :each do
|
203
|
+
RSpecModelFinderTest.acquire_with_id_substitute( 'id' )
|
204
|
+
end
|
205
|
+
|
206
|
+
it 'SQL generation is as expected' do
|
207
|
+
sql = RSpecModelFinderTest.acquisition_scope( @id ).to_sql()
|
208
|
+
expect_sql( sql, @alt_attr_name )
|
209
|
+
end
|
210
|
+
end
|
211
|
+
end
|
212
|
+
|
213
|
+
# ==========================================================================
|
214
|
+
|
215
|
+
context '#acquire' do
|
133
216
|
it 'finds from the class' do
|
134
217
|
found = RSpecModelFinderTest.acquire( @id )
|
135
218
|
expect( found ).to eq(@a)
|
@@ -203,7 +286,7 @@ describe Hoodoo::ActiveRecord::Finder do
|
|
203
286
|
|
204
287
|
# ==========================================================================
|
205
288
|
|
206
|
-
context 'acquire_in' do
|
289
|
+
context '#acquire_in' do
|
207
290
|
before :each do
|
208
291
|
@scoped_1 = RSpecModelFinderTest.new
|
209
292
|
@scoped_1.id = 'id 1'
|
@@ -350,46 +433,7 @@ describe Hoodoo::ActiveRecord::Finder do
|
|
350
433
|
|
351
434
|
# ==========================================================================
|
352
435
|
|
353
|
-
context '
|
354
|
-
def expect_sql( sql, id_attr_name )
|
355
|
-
expect( sql ).to eq( "SELECT \"r_spec_model_finder_tests\".* "<<
|
356
|
-
"FROM \"r_spec_model_finder_tests\" " <<
|
357
|
-
"WHERE (" <<
|
358
|
-
"(" <<
|
359
|
-
"\"r_spec_model_finder_tests\".\"#{ id_attr_name }\" = '#{ @id }' OR " <<
|
360
|
-
"\"r_spec_model_finder_tests\".\"uuid\" = '#{ @id }'" <<
|
361
|
-
") OR " <<
|
362
|
-
"\"r_spec_model_finder_tests\".\"code\" = '#{ @id }'" <<
|
363
|
-
")" )
|
364
|
-
end
|
365
|
-
|
366
|
-
context 'acquisition_scope' do
|
367
|
-
it 'SQL generation is as expected' do
|
368
|
-
sql = RSpecModelFinderTest.acquisition_scope( @id ).to_sql()
|
369
|
-
expect_sql( sql, 'id' )
|
370
|
-
end
|
371
|
-
end
|
372
|
-
|
373
|
-
context 'acquire_with_id_substitute' do
|
374
|
-
before :each do
|
375
|
-
@alt_attr_name = 'foo'
|
376
|
-
RSpecModelFinderTest.acquire_with_id_substitute( @alt_attr_name )
|
377
|
-
end
|
378
|
-
|
379
|
-
after :each do
|
380
|
-
RSpecModelFinderTest.acquire_with_id_substitute( 'id' )
|
381
|
-
end
|
382
|
-
|
383
|
-
it 'SQL generation is as expected' do
|
384
|
-
sql = RSpecModelFinderTest.acquisition_scope( @id ).to_sql()
|
385
|
-
expect_sql( sql, @alt_attr_name )
|
386
|
-
end
|
387
|
-
end
|
388
|
-
end
|
389
|
-
|
390
|
-
# ==========================================================================
|
391
|
-
|
392
|
-
context 'lists' do
|
436
|
+
context '#list' do
|
393
437
|
it 'lists with pages, offsets and counts' do
|
394
438
|
@list_params.offset = 1 # 0 is first record
|
395
439
|
@list_params.limit = 1
|
@@ -695,7 +739,7 @@ describe Hoodoo::ActiveRecord::Finder do
|
|
695
739
|
|
696
740
|
# ==========================================================================
|
697
741
|
|
698
|
-
context 'list_in' do
|
742
|
+
context '#list_in' do
|
699
743
|
before :each do
|
700
744
|
@scoped_1 = RSpecModelFinderTest.new
|
701
745
|
@scoped_1.id = 'id 1'
|
@@ -74,6 +74,14 @@ describe Hoodoo::ActiveRecord::Support do
|
|
74
74
|
t.string :bar
|
75
75
|
t.timestamps :null => true
|
76
76
|
end
|
77
|
+
|
78
|
+
ActiveRecord::Migration.create_table( :r_spec_full_scope_for_manually_dateds ) do | t |
|
79
|
+
t.string :baz
|
80
|
+
t.string :uuid, :length => 32
|
81
|
+
t.datetime :effective_start
|
82
|
+
t.datetime :effective_end
|
83
|
+
t.timestamps :null => true
|
84
|
+
end
|
77
85
|
end
|
78
86
|
|
79
87
|
# Note inheritance from plain ActiveRecord::Base, important for
|
@@ -107,6 +115,16 @@ describe Hoodoo::ActiveRecord::Support do
|
|
107
115
|
class RSpecFullScopeForTestBaseSubclassWithoutOverrides < RSpecFullScopeForTestBaseWithDirectives
|
108
116
|
# No overrides at all
|
109
117
|
end
|
118
|
+
|
119
|
+
# Manual and automatic effective dating can live in the same mixin
|
120
|
+
# collection but can't both be enabled at the same time, so do this
|
121
|
+
# in a special test class with a database table that meets the
|
122
|
+
# related requirements.
|
123
|
+
#
|
124
|
+
class RSpecFullScopeForManuallyDated < Hoodoo::ActiveRecord::Base
|
125
|
+
secure_with( :baz => :baz )
|
126
|
+
manual_dating_enabled()
|
127
|
+
end
|
110
128
|
end
|
111
129
|
|
112
130
|
before :each do
|
@@ -221,5 +239,37 @@ describe Hoodoo::ActiveRecord::Support do
|
|
221
239
|
expect( auto_scope ).to eq( manual_scope )
|
222
240
|
end
|
223
241
|
end
|
242
|
+
|
243
|
+
context '(with manual dating enabled)' do
|
244
|
+
before :each do
|
245
|
+
@session.scoping.baz = [ @test_scoping_value ]
|
246
|
+
end
|
247
|
+
|
248
|
+
context 'gets customised scope:' do
|
249
|
+
it 'manually dated' do
|
250
|
+
manual_scope = RSpecFullScopeForManuallyDated.manually_dated( @context ).to_sql()
|
251
|
+
|
252
|
+
expect( manual_scope ).to include( 'FROM "r_spec_full_scope_for_manually_dateds"' )
|
253
|
+
expect( manual_scope ).to include( "\"effective_end\" > #{ RSpecFullScopeForTestSubclass.sanitize( @test_time_value.to_time.round( Hoodoo::ActiveRecord::ManuallyDated::SECONDS_DECIMAL_PLACES ) ) }" )
|
254
|
+
end
|
255
|
+
|
256
|
+
it 'secure' do
|
257
|
+
manual_scope = RSpecFullScopeForManuallyDated.secure( @context ).to_sql()
|
258
|
+
|
259
|
+
expect( manual_scope ).to include( "\"r_spec_full_scope_for_manually_dateds\".\"baz\" = '#{ @test_scoping_value }'" )
|
260
|
+
end
|
261
|
+
|
262
|
+
pending 'translated' do
|
263
|
+
raise "Scope verification for '\#translated'"
|
264
|
+
end
|
265
|
+
|
266
|
+
it 'everything' do
|
267
|
+
auto_scope = described_class.full_scope_for( RSpecFullScopeForManuallyDated, @context ).to_sql()
|
268
|
+
manual_scope = RSpecFullScopeForManuallyDated.manually_dated( @context ).secure( @context ).translated( @context ).to_sql()
|
269
|
+
|
270
|
+
expect( auto_scope ).to eq( manual_scope )
|
271
|
+
end
|
272
|
+
end
|
273
|
+
end
|
224
274
|
end
|
225
275
|
end
|
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.
|
4
|
+
version: 1.4.0
|
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-23 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: kgio
|