acfs 1.3.3 → 1.6.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (96) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +372 -0
  3. data/LICENSE +22 -0
  4. data/README.md +321 -0
  5. data/acfs.gemspec +38 -0
  6. data/lib/acfs.rb +51 -0
  7. data/lib/acfs/adapter/base.rb +26 -0
  8. data/lib/acfs/adapter/typhoeus.rb +82 -0
  9. data/lib/acfs/collection.rb +28 -0
  10. data/lib/acfs/collections/paginatable.rb +76 -0
  11. data/lib/acfs/configuration.rb +120 -0
  12. data/lib/acfs/errors.rb +147 -0
  13. data/lib/acfs/global.rb +101 -0
  14. data/lib/acfs/location.rb +76 -0
  15. data/lib/acfs/middleware/base.rb +24 -0
  16. data/lib/acfs/middleware/json.rb +31 -0
  17. data/lib/acfs/middleware/logger.rb +23 -0
  18. data/lib/acfs/middleware/msgpack.rb +32 -0
  19. data/lib/acfs/middleware/print.rb +23 -0
  20. data/lib/acfs/middleware/serializer.rb +41 -0
  21. data/lib/acfs/operation.rb +96 -0
  22. data/lib/acfs/request.rb +32 -0
  23. data/lib/acfs/request/callbacks.rb +54 -0
  24. data/lib/acfs/resource.rb +39 -0
  25. data/lib/acfs/resource/attributes.rb +270 -0
  26. data/lib/acfs/resource/attributes/base.rb +29 -0
  27. data/lib/acfs/resource/attributes/boolean.rb +39 -0
  28. data/lib/acfs/resource/attributes/date_time.rb +32 -0
  29. data/lib/acfs/resource/attributes/dict.rb +39 -0
  30. data/lib/acfs/resource/attributes/float.rb +33 -0
  31. data/lib/acfs/resource/attributes/integer.rb +29 -0
  32. data/lib/acfs/resource/attributes/list.rb +36 -0
  33. data/lib/acfs/resource/attributes/string.rb +26 -0
  34. data/lib/acfs/resource/attributes/uuid.rb +48 -0
  35. data/lib/acfs/resource/dirty.rb +37 -0
  36. data/lib/acfs/resource/initialization.rb +31 -0
  37. data/lib/acfs/resource/loadable.rb +35 -0
  38. data/lib/acfs/resource/locatable.rb +135 -0
  39. data/lib/acfs/resource/operational.rb +26 -0
  40. data/lib/acfs/resource/persistence.rb +258 -0
  41. data/lib/acfs/resource/query_methods.rb +266 -0
  42. data/lib/acfs/resource/service.rb +44 -0
  43. data/lib/acfs/resource/validation.rb +49 -0
  44. data/lib/acfs/response.rb +30 -0
  45. data/lib/acfs/response/formats.rb +27 -0
  46. data/lib/acfs/response/status.rb +33 -0
  47. data/lib/acfs/rspec.rb +13 -0
  48. data/lib/acfs/runner.rb +102 -0
  49. data/lib/acfs/service.rb +94 -0
  50. data/lib/acfs/service/middleware.rb +58 -0
  51. data/lib/acfs/service/middleware/stack.rb +65 -0
  52. data/lib/acfs/singleton_resource.rb +85 -0
  53. data/lib/acfs/stub.rb +199 -0
  54. data/lib/acfs/util.rb +22 -0
  55. data/lib/acfs/version.rb +16 -0
  56. data/lib/acfs/yard.rb +6 -0
  57. data/spec/acfs/adapter/typhoeus_spec.rb +55 -0
  58. data/spec/acfs/collection_spec.rb +157 -0
  59. data/spec/acfs/configuration_spec.rb +53 -0
  60. data/spec/acfs/global_spec.rb +140 -0
  61. data/spec/acfs/location_spec.rb +25 -0
  62. data/spec/acfs/middleware/json_spec.rb +79 -0
  63. data/spec/acfs/middleware/msgpack_spec.rb +62 -0
  64. data/spec/acfs/operation_spec.rb +12 -0
  65. data/spec/acfs/request/callbacks_spec.rb +48 -0
  66. data/spec/acfs/request_spec.rb +79 -0
  67. data/spec/acfs/resource/attributes/boolean_spec.rb +58 -0
  68. data/spec/acfs/resource/attributes/date_time_spec.rb +51 -0
  69. data/spec/acfs/resource/attributes/dict_spec.rb +77 -0
  70. data/spec/acfs/resource/attributes/float_spec.rb +61 -0
  71. data/spec/acfs/resource/attributes/integer_spec.rb +36 -0
  72. data/spec/acfs/resource/attributes/list_spec.rb +60 -0
  73. data/spec/acfs/resource/attributes/uuid_spec.rb +42 -0
  74. data/spec/acfs/resource/attributes_spec.rb +179 -0
  75. data/spec/acfs/resource/dirty_spec.rb +49 -0
  76. data/spec/acfs/resource/initialization_spec.rb +36 -0
  77. data/spec/acfs/resource/loadable_spec.rb +22 -0
  78. data/spec/acfs/resource/locatable_spec.rb +118 -0
  79. data/spec/acfs/resource/persistance_spec.rb +322 -0
  80. data/spec/acfs/resource/query_methods_spec.rb +548 -0
  81. data/spec/acfs/resource/validation_spec.rb +129 -0
  82. data/spec/acfs/response/formats_spec.rb +52 -0
  83. data/spec/acfs/response/status_spec.rb +71 -0
  84. data/spec/acfs/runner_spec.rb +95 -0
  85. data/spec/acfs/service/middleware_spec.rb +35 -0
  86. data/spec/acfs/service_spec.rb +48 -0
  87. data/spec/acfs/singleton_resource_spec.rb +17 -0
  88. data/spec/acfs/stub_spec.rb +345 -0
  89. data/spec/acfs_spec.rb +205 -0
  90. data/spec/fixtures/config.yml +14 -0
  91. data/spec/spec_helper.rb +42 -0
  92. data/spec/support/hash.rb +11 -0
  93. data/spec/support/response.rb +12 -0
  94. data/spec/support/service.rb +92 -0
  95. data/spec/support/shared/find_callbacks.rb +50 -0
  96. metadata +159 -26
@@ -0,0 +1,14 @@
1
+ development: &dev
2
+ services:
3
+ user_service: http://localhost:3001/
4
+ comment_service:
5
+ locate: http://localhost:3002/
6
+
7
+ production:
8
+ services:
9
+ user_service:
10
+ locate: http://user.example.org/
11
+ comment_service: http://comment.example.org/
12
+
13
+ test:
14
+ <<: *dev
@@ -0,0 +1,42 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'rspec'
4
+ require 'webmock/rspec'
5
+
6
+ require 'simplecov'
7
+ SimpleCov.start do
8
+ add_filter 'spec'
9
+ end
10
+
11
+ if ENV['CI']
12
+ require 'codecov'
13
+ SimpleCov.formatter = SimpleCov::Formatter::Codecov
14
+ end
15
+
16
+ require 'bundler'
17
+ Bundler.require(:default, :test)
18
+
19
+ require 'acfs'
20
+
21
+ Dir[File.expand_path('spec/support/**/*.rb')].sort.each {|f| require f }
22
+
23
+ RSpec.configure do |config|
24
+ # ## Mock Framework
25
+ #
26
+ # If you prefer to use mocha, flexmock or RR, uncomment the appropriate line:
27
+ #
28
+ # config.mock_with :mocha
29
+ # config.mock_with :flexmock
30
+ # config.mock_with :rr
31
+
32
+ # Run specs in random order to surface order dependencies. If you find an
33
+ # order dependency and want to debug it, you can fix the order by providing
34
+ # the seed, which is printed after each run.
35
+ # --seed 1234
36
+ config.order = 'random'
37
+
38
+ config.before :each do
39
+ Acfs.runner.clear
40
+ Acfs::Stub.clear
41
+ end
42
+ end
@@ -0,0 +1,11 @@
1
+ # frozen_string_literal: true
2
+
3
+ class ActiveSupport::HashWithIndifferentAccess
4
+ def ==(other)
5
+ if other.respond_to? :with_indifferent_access
6
+ super other.with_indifferent_access
7
+ else
8
+ super
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,12 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'json'
4
+
5
+ def response(data = nil, opts = {})
6
+ if data
7
+ opts.merge! body: JSON.dump(data)
8
+ opts[:headers] ||= {}
9
+ opts[:headers].merge! 'Content-Type' => 'application/json'
10
+ end
11
+ opts
12
+ end
@@ -0,0 +1,92 @@
1
+ # frozen_string_literal: true
2
+
3
+ Acfs.configure do
4
+ locate :user_service, 'http://users.example.org'
5
+ locate :computer_service, 'http://computers.example.org'
6
+ locate :comments, 'http://comments.example.org'
7
+ end
8
+
9
+ class UserService < Acfs::Service
10
+ use Acfs::Middleware::MessagePackDecoder
11
+ use Acfs::Middleware::JsonDecoder
12
+ use Acfs::Middleware::JsonEncoder
13
+ end
14
+
15
+ class CommentService < Acfs::Service
16
+ identity :comments
17
+
18
+ use Acfs::Middleware::JsonDecoder
19
+ end
20
+
21
+ class MyUser < Acfs::Resource
22
+ service UserService, path: 'users'
23
+
24
+ attribute :id, :integer
25
+ attribute :name, :string, default: 'Anon'
26
+ attribute :age, :integer
27
+ end
28
+
29
+ class Profile < Acfs::SingletonResource
30
+ service UserService, path: 'users/:user_id/profile'
31
+
32
+ attribute :user_id, :integer
33
+ attribute :twitter_handle, :string
34
+ end
35
+
36
+ class Customer < MyUser
37
+ end
38
+
39
+ class MyUserWithValidations < MyUser
40
+ validates_presence_of :name, :age
41
+ validates_format_of :name, with: /\A\w+\s+\w+.?\z/
42
+ end
43
+
44
+ class Session < Acfs::Resource
45
+ service UserService, path: {
46
+ list: 'users/:user_id/sessions',
47
+ delete: 'users/:user_id/sessions/del/:id',
48
+ update: nil
49
+ }
50
+
51
+ attribute :id, :string
52
+ attribute :user, :integer
53
+ end
54
+
55
+ class Comment < Acfs::Resource
56
+ service CommentService
57
+
58
+ attribute :id, :integer
59
+ attribute :text, :string
60
+ end
61
+
62
+ class ComputerService < Acfs::Service
63
+ use Acfs::Middleware::MessagePackDecoder
64
+ use Acfs::Middleware::JsonDecoder
65
+ use Acfs::Middleware::JsonEncoder
66
+ end
67
+
68
+ class Computer < Acfs::Resource
69
+ service ComputerService, path: 'computers'
70
+
71
+ attribute :id, :integer
72
+ end
73
+
74
+ class PC < Computer
75
+ end
76
+
77
+ class Mac < Computer
78
+ end
79
+
80
+ class Single < Acfs::SingletonResource
81
+ service UserService
82
+
83
+ attribute :score, :integer
84
+ attribute :user_id, :integer
85
+ end
86
+
87
+ class PathArguments < Acfs::Resource
88
+ service UserService, path: ':required_arg/users/'
89
+
90
+ attribute :id, :integer
91
+ attribute :required_arg, :string
92
+ end
@@ -0,0 +1,50 @@
1
+ # frozen_string_literal: true
2
+
3
+ shared_examples 'a query method with multi-callback support' do
4
+ let(:cb) { Proc.new }
5
+
6
+ it 'should invoke callback' do
7
+ expect do |cb|
8
+ action.call cb
9
+ Acfs.run
10
+ end.to yield_with_args
11
+ end
12
+
13
+ it 'should invoke multiple callbacks' do
14
+ expect do |cb|
15
+ object = action.call cb
16
+ Acfs.add_callback object, &cb
17
+ Acfs.run
18
+ end.to yield_control.exactly(2).times
19
+ end
20
+
21
+ describe 'callback' do
22
+ it 'should be invoked with resource' do
23
+ proc = proc {}
24
+ expect(proc).to receive(:call) do |res|
25
+ expect(res).to equal @object
26
+ expect(res).to be_loaded
27
+ end
28
+
29
+ @object = action.call proc
30
+ Acfs.run
31
+ end
32
+
33
+ it 'should invoke multiple callback with loaded resource' do
34
+ proc1 = proc {}
35
+ proc2 = proc {}
36
+ expect(proc1).to receive(:call) do |user|
37
+ expect(user).to equal @object
38
+ expect(user).to be_loaded
39
+ end
40
+ expect(proc2).to receive(:call) do |user|
41
+ expect(user).to equal @object
42
+ expect(user).to be_loaded
43
+ end
44
+
45
+ @object = action.call proc1
46
+ Acfs.add_callback(@object, &proc2)
47
+ Acfs.run
48
+ end
49
+ end
50
+ end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: acfs
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.3.3
4
+ version: 1.6.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jan Graichen
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2020-03-22 00:00:00.000000000 Z
11
+ date: 2021-01-07 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: actionpack
@@ -16,58 +16,44 @@ dependencies:
16
16
  requirements:
17
17
  - - ">="
18
18
  - !ruby/object:Gem::Version
19
- version: '4.2'
19
+ version: '5.2'
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
24
  - - ">="
25
25
  - !ruby/object:Gem::Version
26
- version: '4.2'
26
+ version: '5.2'
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: activemodel
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
31
  - - ">="
32
32
  - !ruby/object:Gem::Version
33
- version: '4.2'
33
+ version: '5.2'
34
34
  type: :runtime
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
38
  - - ">="
39
39
  - !ruby/object:Gem::Version
40
- version: '4.2'
40
+ version: '5.2'
41
41
  - !ruby/object:Gem::Dependency
42
42
  name: activesupport
43
43
  requirement: !ruby/object:Gem::Requirement
44
44
  requirements:
45
45
  - - ">="
46
46
  - !ruby/object:Gem::Version
47
- version: '4.2'
47
+ version: '5.2'
48
48
  type: :runtime
49
49
  prerelease: false
50
50
  version_requirements: !ruby/object:Gem::Requirement
51
51
  requirements:
52
52
  - - ">="
53
53
  - !ruby/object:Gem::Version
54
- version: '4.2'
54
+ version: '5.2'
55
55
  - !ruby/object:Gem::Dependency
56
56
  name: multi_json
57
- requirement: !ruby/object:Gem::Requirement
58
- requirements:
59
- - - ">="
60
- - !ruby/object:Gem::Version
61
- version: '0'
62
- type: :runtime
63
- prerelease: false
64
- version_requirements: !ruby/object:Gem::Requirement
65
- requirements:
66
- - - ">="
67
- - !ruby/object:Gem::Version
68
- version: '0'
69
- - !ruby/object:Gem::Dependency
70
- name: typhoeus
71
57
  requirement: !ruby/object:Gem::Requirement
72
58
  requirements:
73
59
  - - "~>"
@@ -94,6 +80,20 @@ dependencies:
94
80
  - - ">="
95
81
  - !ruby/object:Gem::Version
96
82
  version: '0'
83
+ - !ruby/object:Gem::Dependency
84
+ name: typhoeus
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - "~>"
88
+ - !ruby/object:Gem::Version
89
+ version: '1.0'
90
+ type: :runtime
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - "~>"
95
+ - !ruby/object:Gem::Version
96
+ version: '1.0'
97
97
  - !ruby/object:Gem::Dependency
98
98
  name: bundler
99
99
  requirement: !ruby/object:Gem::Requirement
@@ -114,7 +114,101 @@ email:
114
114
  executables: []
115
115
  extensions: []
116
116
  extra_rdoc_files: []
117
- files: []
117
+ files:
118
+ - CHANGELOG.md
119
+ - LICENSE
120
+ - README.md
121
+ - acfs.gemspec
122
+ - lib/acfs.rb
123
+ - lib/acfs/adapter/base.rb
124
+ - lib/acfs/adapter/typhoeus.rb
125
+ - lib/acfs/collection.rb
126
+ - lib/acfs/collections/paginatable.rb
127
+ - lib/acfs/configuration.rb
128
+ - lib/acfs/errors.rb
129
+ - lib/acfs/global.rb
130
+ - lib/acfs/location.rb
131
+ - lib/acfs/middleware/base.rb
132
+ - lib/acfs/middleware/json.rb
133
+ - lib/acfs/middleware/logger.rb
134
+ - lib/acfs/middleware/msgpack.rb
135
+ - lib/acfs/middleware/print.rb
136
+ - lib/acfs/middleware/serializer.rb
137
+ - lib/acfs/operation.rb
138
+ - lib/acfs/request.rb
139
+ - lib/acfs/request/callbacks.rb
140
+ - lib/acfs/resource.rb
141
+ - lib/acfs/resource/attributes.rb
142
+ - lib/acfs/resource/attributes/base.rb
143
+ - lib/acfs/resource/attributes/boolean.rb
144
+ - lib/acfs/resource/attributes/date_time.rb
145
+ - lib/acfs/resource/attributes/dict.rb
146
+ - lib/acfs/resource/attributes/float.rb
147
+ - lib/acfs/resource/attributes/integer.rb
148
+ - lib/acfs/resource/attributes/list.rb
149
+ - lib/acfs/resource/attributes/string.rb
150
+ - lib/acfs/resource/attributes/uuid.rb
151
+ - lib/acfs/resource/dirty.rb
152
+ - lib/acfs/resource/initialization.rb
153
+ - lib/acfs/resource/loadable.rb
154
+ - lib/acfs/resource/locatable.rb
155
+ - lib/acfs/resource/operational.rb
156
+ - lib/acfs/resource/persistence.rb
157
+ - lib/acfs/resource/query_methods.rb
158
+ - lib/acfs/resource/service.rb
159
+ - lib/acfs/resource/validation.rb
160
+ - lib/acfs/response.rb
161
+ - lib/acfs/response/formats.rb
162
+ - lib/acfs/response/status.rb
163
+ - lib/acfs/rspec.rb
164
+ - lib/acfs/runner.rb
165
+ - lib/acfs/service.rb
166
+ - lib/acfs/service/middleware.rb
167
+ - lib/acfs/service/middleware/stack.rb
168
+ - lib/acfs/singleton_resource.rb
169
+ - lib/acfs/stub.rb
170
+ - lib/acfs/util.rb
171
+ - lib/acfs/version.rb
172
+ - lib/acfs/yard.rb
173
+ - spec/acfs/adapter/typhoeus_spec.rb
174
+ - spec/acfs/collection_spec.rb
175
+ - spec/acfs/configuration_spec.rb
176
+ - spec/acfs/global_spec.rb
177
+ - spec/acfs/location_spec.rb
178
+ - spec/acfs/middleware/json_spec.rb
179
+ - spec/acfs/middleware/msgpack_spec.rb
180
+ - spec/acfs/operation_spec.rb
181
+ - spec/acfs/request/callbacks_spec.rb
182
+ - spec/acfs/request_spec.rb
183
+ - spec/acfs/resource/attributes/boolean_spec.rb
184
+ - spec/acfs/resource/attributes/date_time_spec.rb
185
+ - spec/acfs/resource/attributes/dict_spec.rb
186
+ - spec/acfs/resource/attributes/float_spec.rb
187
+ - spec/acfs/resource/attributes/integer_spec.rb
188
+ - spec/acfs/resource/attributes/list_spec.rb
189
+ - spec/acfs/resource/attributes/uuid_spec.rb
190
+ - spec/acfs/resource/attributes_spec.rb
191
+ - spec/acfs/resource/dirty_spec.rb
192
+ - spec/acfs/resource/initialization_spec.rb
193
+ - spec/acfs/resource/loadable_spec.rb
194
+ - spec/acfs/resource/locatable_spec.rb
195
+ - spec/acfs/resource/persistance_spec.rb
196
+ - spec/acfs/resource/query_methods_spec.rb
197
+ - spec/acfs/resource/validation_spec.rb
198
+ - spec/acfs/response/formats_spec.rb
199
+ - spec/acfs/response/status_spec.rb
200
+ - spec/acfs/runner_spec.rb
201
+ - spec/acfs/service/middleware_spec.rb
202
+ - spec/acfs/service_spec.rb
203
+ - spec/acfs/singleton_resource_spec.rb
204
+ - spec/acfs/stub_spec.rb
205
+ - spec/acfs_spec.rb
206
+ - spec/fixtures/config.yml
207
+ - spec/spec_helper.rb
208
+ - spec/support/hash.rb
209
+ - spec/support/response.rb
210
+ - spec/support/service.rb
211
+ - spec/support/shared/find_callbacks.rb
118
212
  homepage: https://github.com/jgraichen/acfs
119
213
  licenses:
120
214
  - MIT
@@ -127,15 +221,54 @@ required_ruby_version: !ruby/object:Gem::Requirement
127
221
  requirements:
128
222
  - - ">="
129
223
  - !ruby/object:Gem::Version
130
- version: '0'
224
+ version: 2.5.0
131
225
  required_rubygems_version: !ruby/object:Gem::Requirement
132
226
  requirements:
133
227
  - - ">="
134
228
  - !ruby/object:Gem::Version
135
229
  version: '0'
136
230
  requirements: []
137
- rubygems_version: 3.1.2
231
+ rubygems_version: 3.2.4
138
232
  signing_key:
139
233
  specification_version: 4
140
234
  summary: An abstract API base client for service oriented application.
141
- test_files: []
235
+ test_files:
236
+ - spec/acfs/adapter/typhoeus_spec.rb
237
+ - spec/acfs/collection_spec.rb
238
+ - spec/acfs/configuration_spec.rb
239
+ - spec/acfs/global_spec.rb
240
+ - spec/acfs/location_spec.rb
241
+ - spec/acfs/middleware/json_spec.rb
242
+ - spec/acfs/middleware/msgpack_spec.rb
243
+ - spec/acfs/operation_spec.rb
244
+ - spec/acfs/request/callbacks_spec.rb
245
+ - spec/acfs/request_spec.rb
246
+ - spec/acfs/resource/attributes/boolean_spec.rb
247
+ - spec/acfs/resource/attributes/date_time_spec.rb
248
+ - spec/acfs/resource/attributes/dict_spec.rb
249
+ - spec/acfs/resource/attributes/float_spec.rb
250
+ - spec/acfs/resource/attributes/integer_spec.rb
251
+ - spec/acfs/resource/attributes/list_spec.rb
252
+ - spec/acfs/resource/attributes/uuid_spec.rb
253
+ - spec/acfs/resource/attributes_spec.rb
254
+ - spec/acfs/resource/dirty_spec.rb
255
+ - spec/acfs/resource/initialization_spec.rb
256
+ - spec/acfs/resource/loadable_spec.rb
257
+ - spec/acfs/resource/locatable_spec.rb
258
+ - spec/acfs/resource/persistance_spec.rb
259
+ - spec/acfs/resource/query_methods_spec.rb
260
+ - spec/acfs/resource/validation_spec.rb
261
+ - spec/acfs/response/formats_spec.rb
262
+ - spec/acfs/response/status_spec.rb
263
+ - spec/acfs/runner_spec.rb
264
+ - spec/acfs/service/middleware_spec.rb
265
+ - spec/acfs/service_spec.rb
266
+ - spec/acfs/singleton_resource_spec.rb
267
+ - spec/acfs/stub_spec.rb
268
+ - spec/acfs_spec.rb
269
+ - spec/fixtures/config.yml
270
+ - spec/spec_helper.rb
271
+ - spec/support/hash.rb
272
+ - spec/support/response.rb
273
+ - spec/support/service.rb
274
+ - spec/support/shared/find_callbacks.rb