receptacle 0.3.1 → 2.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/.github/workflows/matrix.yml +32 -0
- data/.gitignore +1 -1
- data/.rubocop.yml +6 -8
- data/CHANGELOG.md +31 -19
- data/Gemfile +2 -7
- data/Gemfile.lock +92 -0
- data/LICENSE.txt +1 -1
- data/README.md +22 -52
- data/Rakefile +8 -18
- data/bin/console +3 -3
- data/examples/simple_repo.rb +17 -15
- data/lib/receptacle/errors.rb +2 -1
- data/lib/receptacle/repo.rb +51 -0
- data/lib/receptacle/test_support.rb +2 -17
- data/lib/receptacle/version.rb +2 -1
- data/lib/receptacle.rb +3 -9
- data/receptacle.gemspec +31 -26
- data/upgrade_notes.md +45 -0
- metadata +55 -70
- data/.dir-locals.el +0 -1
- data/.travis.yml +0 -36
- data/Dangerfile +0 -26
- data/Guardfile +0 -31
- data/lib/receptacle/interface_methods.rb +0 -49
- data/lib/receptacle/method_cache.rb +0 -42
- data/lib/receptacle/method_delegation.rb +0 -136
- data/lib/receptacle/registration.rb +0 -34
- data/performance/benchmark.rb +0 -44
- data/performance/profile.rb +0 -39
- data/performance/speed_receptacle.rb +0 -104
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: eaa2e6a1b1e530f37984a21a68e20f465a0a5dc5c5549074879a9ef52dc44776
|
4
|
+
data.tar.gz: 691bee1a039ad306c3ca3e9e8cf4e71f139649a3c47b81b54e5feff8a7908b56
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 03ae765ccf54fe2ee01c20b9a2bb69d8ee8005c6f16e13b7787473512c1ce3848f9118911df840aebc2b1a1523f6c105417c62b96474893ed58c62b49c338ccb
|
7
|
+
data.tar.gz: c2fe5fa8b67040271899b1ab0ac0fadbdd33c6a2e0eeb32b2b4cb762961eeb8b9169913d2e88cdfd2c4172d3a18965c46bc6d88050d9f00f6c63ee40bb2cc607
|
@@ -0,0 +1,32 @@
|
|
1
|
+
---
|
2
|
+
name: matrix-testing
|
3
|
+
|
4
|
+
on:
|
5
|
+
push:
|
6
|
+
branches: [ main, master ]
|
7
|
+
pull_request:
|
8
|
+
branches: [ main, master ]
|
9
|
+
|
10
|
+
permissions:
|
11
|
+
contents: read
|
12
|
+
|
13
|
+
jobs:
|
14
|
+
test:
|
15
|
+
runs-on: ubuntu-latest
|
16
|
+
continue-on-error: ${{ matrix.experimental }}
|
17
|
+
strategy:
|
18
|
+
fail-fast: false
|
19
|
+
matrix:
|
20
|
+
experimental: [false]
|
21
|
+
ruby-version: ["2.7", "3.0", "3.1", "3.2", "jruby-9.3"]
|
22
|
+
include:
|
23
|
+
- ruby-version: jruby-9.4
|
24
|
+
experimental: true
|
25
|
+
steps:
|
26
|
+
- uses: actions/checkout@v3
|
27
|
+
- uses: ruby/setup-ruby@v1
|
28
|
+
with:
|
29
|
+
ruby-version: ${{ matrix.ruby-version }}
|
30
|
+
bundler-cache: true
|
31
|
+
- run: bundle exec rspec
|
32
|
+
- run: bundle exec rubocop
|
data/.gitignore
CHANGED
data/.rubocop.yml
CHANGED
@@ -1,14 +1,15 @@
|
|
1
|
-
|
2
|
-
TargetRubyVersion: 2.1
|
1
|
+
require: rt_rubocop_defaults
|
3
2
|
|
4
|
-
|
5
|
-
|
3
|
+
AllCops:
|
4
|
+
TargetRubyVersion: 2.6
|
5
|
+
# vendor directory is used by github actions and causes issues if not excluded here
|
6
6
|
Exclude:
|
7
|
-
-
|
7
|
+
- vendor/bundle/**/*
|
8
8
|
|
9
9
|
Metrics/BlockLength:
|
10
10
|
Exclude:
|
11
11
|
- '*.gemspec'
|
12
|
+
- 'spec/*'
|
12
13
|
|
13
14
|
Metrics/AbcSize:
|
14
15
|
Exclude:
|
@@ -21,6 +22,3 @@ Metrics/ClassLength:
|
|
21
22
|
Metrics/MethodLength:
|
22
23
|
Exclude:
|
23
24
|
- test/*
|
24
|
-
|
25
|
-
Style/Documentation:
|
26
|
-
Enabled: false
|
data/CHANGELOG.md
CHANGED
@@ -1,35 +1,47 @@
|
|
1
|
-
Changelog
|
2
|
-
===
|
1
|
+
# Changelog
|
3
2
|
|
4
|
-
|
5
|
-
---
|
3
|
+
All notable changes to this project will be documented in this file.
|
6
4
|
|
5
|
+
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
6
|
+
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
7
7
|
|
8
|
-
|
9
|
-
---
|
8
|
+
## [Unreleased]
|
10
9
|
|
11
|
-
|
10
|
+
## [2.0.0] - 2023-01-17
|
11
|
+
### Changed
|
12
|
+
* switch CI to github actions
|
13
|
+
* remove danger
|
14
|
+
* remove codecov
|
15
|
+
* Support for ruby 3
|
16
|
+
* The wrapper interface has been redesigned (breaking change, see [upgrade notes](./upgrade_notes.md))
|
17
|
+
|
18
|
+
|
19
|
+
## [1.0.0]
|
20
|
+
### Changed
|
21
|
+
* repackage 0.3.1 as 1.0.0
|
22
|
+
* setup circleci
|
23
|
+
* drop ruby < 2.4
|
12
24
|
|
13
|
-
0.3.0
|
14
|
-
---
|
15
25
|
|
26
|
+
## [0.3.1]
|
27
|
+
### Fixed
|
28
|
+
* fix after wrapper ordering bug [PR#6](https://github.com/andreaseger/receptacle/pull/6)
|
29
|
+
|
30
|
+
## [0.3.0}
|
31
|
+
### Added
|
16
32
|
* add danger
|
17
33
|
* also support higher arity methods (== method with more than one argument)
|
18
34
|
|
19
|
-
0.2.0
|
20
|
-
|
21
|
-
|
35
|
+
## [0.2.0]
|
36
|
+
### Changed
|
22
37
|
* update documentation
|
23
38
|
* enable ruby 2.1+
|
24
39
|
|
25
|
-
0.1.1
|
26
|
-
|
27
|
-
|
40
|
+
## [0.1.1]
|
41
|
+
## Added
|
28
42
|
* add changelog, update copyright
|
29
43
|
* add test helper method `ensure_method_delegators` to make rspec stubs/mocks work as expected
|
30
44
|
|
31
|
-
0.1.0
|
32
|
-
|
33
|
-
|
45
|
+
## [0.1.0]
|
46
|
+
## Added
|
34
47
|
* initial release
|
35
|
-
|
data/Gemfile
CHANGED
data/Gemfile.lock
ADDED
@@ -0,0 +1,92 @@
|
|
1
|
+
PATH
|
2
|
+
remote: .
|
3
|
+
specs:
|
4
|
+
receptacle (2.0.0)
|
5
|
+
|
6
|
+
GEM
|
7
|
+
remote: https://rubygems.org/
|
8
|
+
specs:
|
9
|
+
ast (2.4.2)
|
10
|
+
coderay (1.1.3)
|
11
|
+
diff-lcs (1.5.0)
|
12
|
+
docile (1.4.0)
|
13
|
+
ffi (1.15.5-java)
|
14
|
+
json (2.6.2)
|
15
|
+
json (2.6.2-java)
|
16
|
+
method_source (1.0.0)
|
17
|
+
parallel (1.22.1)
|
18
|
+
parser (3.1.2.1)
|
19
|
+
ast (~> 2.4.1)
|
20
|
+
pry (0.14.1)
|
21
|
+
coderay (~> 1.1)
|
22
|
+
method_source (~> 1.0)
|
23
|
+
pry (0.14.1-java)
|
24
|
+
coderay (~> 1.1)
|
25
|
+
method_source (~> 1.0)
|
26
|
+
spoon (~> 0.0)
|
27
|
+
rainbow (3.1.1)
|
28
|
+
rake (10.5.0)
|
29
|
+
regexp_parser (2.6.0)
|
30
|
+
rexml (3.2.5)
|
31
|
+
rspec (3.12.0)
|
32
|
+
rspec-core (~> 3.12.0)
|
33
|
+
rspec-expectations (~> 3.12.0)
|
34
|
+
rspec-mocks (~> 3.12.0)
|
35
|
+
rspec-core (3.12.0)
|
36
|
+
rspec-support (~> 3.12.0)
|
37
|
+
rspec-expectations (3.12.0)
|
38
|
+
diff-lcs (>= 1.2.0, < 2.0)
|
39
|
+
rspec-support (~> 3.12.0)
|
40
|
+
rspec-mocks (3.12.0)
|
41
|
+
diff-lcs (>= 1.2.0, < 2.0)
|
42
|
+
rspec-support (~> 3.12.0)
|
43
|
+
rspec-support (3.12.0)
|
44
|
+
rspec_junit_formatter (0.6.0)
|
45
|
+
rspec-core (>= 2, < 4, != 2.12.0)
|
46
|
+
rt_rubocop_defaults (2.4.0)
|
47
|
+
rubocop (~> 1.25)
|
48
|
+
rubocop (1.38.0)
|
49
|
+
json (~> 2.3)
|
50
|
+
parallel (~> 1.10)
|
51
|
+
parser (>= 3.1.2.1)
|
52
|
+
rainbow (>= 2.2.2, < 4.0)
|
53
|
+
regexp_parser (>= 1.8, < 3.0)
|
54
|
+
rexml (>= 3.2.5, < 4.0)
|
55
|
+
rubocop-ast (>= 1.23.0, < 2.0)
|
56
|
+
ruby-progressbar (~> 1.7)
|
57
|
+
unicode-display_width (>= 1.4.0, < 3.0)
|
58
|
+
rubocop-ast (1.23.0)
|
59
|
+
parser (>= 3.1.1.0)
|
60
|
+
rubocop-rspec (2.14.2)
|
61
|
+
rubocop (~> 1.33)
|
62
|
+
rubocop_runner (2.2.1)
|
63
|
+
ruby-progressbar (1.11.0)
|
64
|
+
simplecov (0.21.2)
|
65
|
+
docile (~> 1.1)
|
66
|
+
simplecov-html (~> 0.11)
|
67
|
+
simplecov_json_formatter (~> 0.1)
|
68
|
+
simplecov-html (0.12.3)
|
69
|
+
simplecov_json_formatter (0.1.4)
|
70
|
+
spoon (0.0.6)
|
71
|
+
ffi
|
72
|
+
unicode-display_width (2.3.0)
|
73
|
+
|
74
|
+
PLATFORMS
|
75
|
+
universal-java-11
|
76
|
+
x86_64-linux
|
77
|
+
|
78
|
+
DEPENDENCIES
|
79
|
+
bundler (>= 1.13, < 3)
|
80
|
+
pry
|
81
|
+
rake (~> 10.0)
|
82
|
+
receptacle!
|
83
|
+
rspec (~> 3.11)
|
84
|
+
rspec_junit_formatter
|
85
|
+
rt_rubocop_defaults (~> 2.4)
|
86
|
+
rubocop (~> 1.37)
|
87
|
+
rubocop-rspec (~> 2.14)
|
88
|
+
rubocop_runner (~> 2.2)
|
89
|
+
simplecov (~> 0.13)
|
90
|
+
|
91
|
+
BUNDLED WITH
|
92
|
+
2.3.26
|
data/LICENSE.txt
CHANGED
data/README.md
CHANGED
@@ -2,15 +2,14 @@
|
|
2
2
|
|
3
3
|
[![Gem Version](https://badge.fury.io/rb/receptacle.svg)](https://badge.fury.io/rb/receptacle)
|
4
4
|
[![Gem Downloads](https://img.shields.io/gem/dt/receptacle.svg)](https://rubygems.org/gems/receptacle)
|
5
|
-
|
6
|
-
[![codecov](https://codecov.io/gh/andreaseger/receptacle/branch/master/graph/badge.svg)](https://codecov.io/gh/andreaseger/receptacle)
|
5
|
+
|
7
6
|
|
8
7
|
## About
|
9
8
|
|
10
9
|
Provides easy and fast means to use the repository pattern to create separation
|
11
10
|
between your business logic and your data sources.
|
12
11
|
|
13
|
-
|
12
|
+
The ownership of this project has been taken over from https://github.com/andreaseger/receptacle, where you can still find version 1.0
|
14
13
|
|
15
14
|
## Installation
|
16
15
|
|
@@ -82,14 +81,14 @@ Optionally wrapper classes can be defined
|
|
82
81
|
```ruby
|
83
82
|
module Wrapper
|
84
83
|
class Validator
|
85
|
-
def
|
84
|
+
def find(id:)
|
86
85
|
raise ArgumentError if id.nil?
|
87
|
-
|
86
|
+
yield(id: id)
|
88
87
|
end
|
89
88
|
end
|
90
89
|
class ModelMapper
|
91
|
-
def
|
92
|
-
Model::User.new(
|
90
|
+
def find(id:)
|
91
|
+
Model::User.new(yield(id: id))
|
93
92
|
end
|
94
93
|
end
|
95
94
|
end
|
@@ -122,14 +121,14 @@ module Repository
|
|
122
121
|
|
123
122
|
module Wrapper
|
124
123
|
class Validator
|
125
|
-
def
|
124
|
+
def find(id:)
|
126
125
|
raise ArgumentError if id.nil?
|
127
|
-
|
126
|
+
yield(id: id)
|
128
127
|
end
|
129
128
|
end
|
130
129
|
class ModelMapper
|
131
|
-
def
|
132
|
-
Model::User.new(
|
130
|
+
def find(id:)
|
131
|
+
Model::User.new(yield(id: id))
|
133
132
|
end
|
134
133
|
end
|
135
134
|
end
|
@@ -225,47 +224,28 @@ applying them in the business logic by using wrappers.
|
|
225
224
|
|
226
225
|
One or multiple wrappers sit logically between the repository and the
|
227
226
|
strategies. Based on the repository configuration it knows when and in which
|
228
|
-
order they should be applied.
|
229
|
-
actions.
|
230
|
-
|
231
|
-
1. a _before_ method action: This action is called before the final strategy
|
232
|
-
method is executed. It has access to the method parameter and can even modify
|
233
|
-
them.
|
234
|
-
2. a _after_ method action: This action is called after the strategy method was
|
235
|
-
executed and has access to the method parameters passed to the strategy
|
236
|
-
method and the return value. The return value could be modified here too.
|
237
|
-
|
238
|
-
The extra 1/2 action type is born by the fact that if a single wrapper class
|
239
|
-
implements both an before and after action for the same method the same wrapper
|
240
|
-
instance is used to execute both. Although this doesn't cover the all use cases
|
241
|
-
an _around_ method action would but many which need state before and after the
|
242
|
-
data source is accessed are covered.
|
227
|
+
order they should be applied.
|
243
228
|
|
244
229
|
#### Implementation
|
245
230
|
|
246
231
|
Wrapper actions are implemented as plain ruby classes which provide instance
|
247
|
-
methods named like
|
248
|
-
`<method_name>` is the repository/strategy method this action should be applied
|
249
|
-
to.
|
232
|
+
methods named like the method that the repository/strategy method this action should be applied to.
|
250
233
|
|
251
234
|
```ruby
|
252
235
|
module Wrapper
|
253
236
|
class Validator
|
254
|
-
def
|
237
|
+
def find(id:)
|
255
238
|
raise ArgumentError if id.nil?
|
256
|
-
|
239
|
+
yield(id: id)
|
257
240
|
end
|
258
241
|
end
|
259
242
|
end
|
260
243
|
```
|
261
244
|
|
262
|
-
This wrapper class would
|
263
|
-
|
264
|
-
|
265
|
-
|
266
|
-
If multiple wrapper classes are defined the before wrapper actions are executed
|
267
|
-
in the order the wrapper classes are defined while the after actions are applied
|
268
|
-
in reverse order.
|
245
|
+
This wrapper class would execute on any `find` call. You can use it to execute code
|
246
|
+
before or after the next wrapper/strategy is called. Calling `yield` executes the next
|
247
|
+
wrapper in line or the strategy, if this is the last wrapper that is called. The return
|
248
|
+
value is passed down to the previous wrapper and in the end to the repository caller.
|
269
249
|
|
270
250
|
### Memory Strategy
|
271
251
|
|
@@ -315,8 +295,8 @@ Some alternative have some interesting features nevertheless:
|
|
315
295
|
|
316
296
|
This gem on the other hand makes absolutely no assumptions about your data
|
317
297
|
source or general structure of your code. It can be simply plugged in between
|
318
|
-
your business logic and data source to abstract the two. Of
|
319
|
-
repository pattern implementations strategy details should be hidden from the
|
298
|
+
your business logic and data source to abstract the two. Of course, like the other
|
299
|
+
repository pattern implementations, strategy details should be hidden from the
|
320
300
|
interface. The data source can essentially be anything. A SQL database, a no-SQL
|
321
301
|
database, a JSON API or even a gem. Placing a gem behind a repository can be
|
322
302
|
useful if you're not yet sure this is the correct or best possible gem,
|
@@ -327,15 +307,11 @@ this by giving all the different http libraries a common interface).
|
|
327
307
|
|
328
308
|
A module called `TestSupport` can be found
|
329
309
|
[here](https://github.com/andreaseger/receptacle/blob/master/lib/receptacle/test_support.rb).
|
330
|
-
Right now it provides
|
331
|
-
temporarily to another strategy and `ensure_method_delegators` to solve issues
|
332
|
-
caused by Rspec when attempting to stub a repository method. Both methods and
|
333
|
-
how to use them is described in more detail in the inline documentation.
|
310
|
+
Right now it provides a helper method `with_strategy` to easily toggle temporarily to another strategy. How to use it is described in more detail in the inline documentation.
|
334
311
|
|
335
312
|
## Goals of this implementation
|
336
313
|
|
337
314
|
- small core codebase
|
338
|
-
- minimal processing overhead - fast method dispatching
|
339
315
|
- flexible - all kind of methods should possible to be mediated
|
340
316
|
- basic but powerful callbacks/hooks/observer possibilities
|
341
317
|
|
@@ -354,16 +330,10 @@ to [rubygems.org](https://rubygems.org).
|
|
354
330
|
## Contributing
|
355
331
|
|
356
332
|
Bug reports and pull requests are welcome on GitHub at
|
357
|
-
https://github.com/
|
333
|
+
https://github.com/runtastic/receptacle. This project is intended to be a safe,
|
358
334
|
welcoming space for collaboration, and contributors are expected to adhere to
|
359
335
|
the [Contributor Covenant](http://contributor-covenant.org) code of conduct.
|
360
336
|
|
361
|
-
## Attribution
|
362
|
-
|
363
|
-
[Runtastic][runtastic] is using the repository pattern extensively in its
|
364
|
-
backend services and inspired the creation of this library. Nevertheless no code
|
365
|
-
developed at [Runtastic][runtastic] was used in this library.
|
366
|
-
|
367
337
|
## License
|
368
338
|
|
369
339
|
The gem is available as open source under the terms of
|
data/Rakefile
CHANGED
@@ -1,25 +1,15 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require
|
2
|
+
|
3
|
+
require "bundler/gem_tasks"
|
4
|
+
require "rake/testtask"
|
4
5
|
|
5
6
|
Rake::TestTask.new(:test) do |t|
|
6
|
-
t.libs <<
|
7
|
-
t.libs <<
|
8
|
-
t.test_files = FileList[
|
7
|
+
t.libs << "test"
|
8
|
+
t.libs << "lib"
|
9
|
+
t.test_files = FileList["test/**/test_*.rb"]
|
9
10
|
end
|
10
11
|
|
11
|
-
|
12
|
-
|
13
|
-
RuboCop::RakeTask.new
|
14
|
-
namespace :rubocop do
|
15
|
-
desc 'Install Rubocop as pre-commit hook'
|
16
|
-
task :install do
|
17
|
-
require 'rubocop_runner'
|
18
|
-
RubocopRunner.install
|
19
|
-
end
|
20
|
-
end
|
21
|
-
rescue LoadError
|
22
|
-
p 'rubocop not installed'
|
23
|
-
end
|
12
|
+
require "rubocop/rake_task"
|
13
|
+
RuboCop::RakeTask.new
|
24
14
|
|
25
15
|
task default: :test
|
data/bin/console
CHANGED
@@ -1,11 +1,11 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
2
|
# frozen_string_literal: true
|
3
3
|
|
4
|
-
require
|
5
|
-
require
|
4
|
+
require "bundler/setup"
|
5
|
+
require "receptacle"
|
6
6
|
|
7
7
|
# You can add fixtures and/or initialization code here to make experimenting
|
8
8
|
# with your gem easier. You can also use a different console, if you like.
|
9
9
|
|
10
|
-
require
|
10
|
+
require "pry"
|
11
11
|
Pry.start
|
data/examples/simple_repo.rb
CHANGED
@@ -1,12 +1,13 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
|
+
# frozen_string_literal: true
|
2
3
|
|
3
|
-
require
|
4
|
+
require "bundler/inline"
|
4
5
|
gemfile true do
|
5
|
-
source
|
6
|
-
gem
|
7
|
-
gem
|
6
|
+
source "https://rubygems.org"
|
7
|
+
gem "receptacle", "~> 2"
|
8
|
+
gem "mongo"
|
8
9
|
end
|
9
|
-
require
|
10
|
+
require "irb"
|
10
11
|
|
11
12
|
# a simple struct to act as business entity
|
12
13
|
User = Struct.new(:id, :name)
|
@@ -18,10 +19,11 @@ module Connection
|
|
18
19
|
|
19
20
|
def initialize
|
20
21
|
::Mongo::Logger.logger.level = Logger::INFO
|
21
|
-
@client = ::Mongo::Client.new([
|
22
|
+
@client = ::Mongo::Client.new(["127.0.0.1:27017"], database: "receptacle")
|
22
23
|
client[:users].delete_many # empty collection
|
23
24
|
end
|
24
25
|
attr_reader :client
|
26
|
+
|
25
27
|
def self.client
|
26
28
|
instance.client
|
27
29
|
end
|
@@ -45,7 +47,7 @@ module Repository
|
|
45
47
|
class Mongo
|
46
48
|
def find(id:)
|
47
49
|
mongo_to_model(collection.find(_id: id).first)
|
48
|
-
rescue
|
50
|
+
rescue StandardError
|
49
51
|
nil
|
50
52
|
end
|
51
53
|
|
@@ -61,7 +63,7 @@ module Repository
|
|
61
63
|
private
|
62
64
|
|
63
65
|
def mongo_to_model(doc)
|
64
|
-
::User.new(doc[
|
66
|
+
::User.new(doc["_id"], doc["name"])
|
65
67
|
end
|
66
68
|
|
67
69
|
def collection
|
@@ -100,21 +102,21 @@ end
|
|
100
102
|
# configure the repository and use it
|
101
103
|
Repository::User.strategy Repository::User::Strategy::InMemory
|
102
104
|
|
103
|
-
user = Repository::User.create(name:
|
104
|
-
print
|
105
|
+
user = Repository::User.create(name: "foo")
|
106
|
+
print "created user: "
|
105
107
|
p user
|
106
|
-
print
|
108
|
+
print "find user by id: "
|
107
109
|
p Repository::User.find(id: user.id)
|
108
110
|
|
109
111
|
# switching to mongo and we see it's using a different store but keeps the same interface
|
110
112
|
Repository::User.strategy Repository::User::Strategy::Mongo
|
111
113
|
|
112
|
-
print
|
114
|
+
print "search same user in other strategy: "
|
113
115
|
p Repository::User.find(id: user.id)
|
114
116
|
#-> nil
|
115
117
|
|
116
|
-
user = Repository::User.create(name:
|
117
|
-
print
|
118
|
+
user = Repository::User.create(name: "foo mongo")
|
119
|
+
print "create new user: "
|
118
120
|
p user
|
119
|
-
print
|
121
|
+
print "find new user by id: "
|
120
122
|
p Repository::User.find(id: user.id)
|
data/lib/receptacle/errors.rb
CHANGED
@@ -1,13 +1,14 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
|
+
|
2
3
|
module Receptacle
|
3
4
|
module Errors
|
4
5
|
class NotConfigured < StandardError
|
5
6
|
attr_reader :repo
|
7
|
+
|
6
8
|
def initialize(repo:)
|
7
9
|
@repo = repo
|
8
10
|
super("Missing Configuration for repository: <#{repo}>")
|
9
11
|
end
|
10
12
|
end
|
11
|
-
class ReservedMethodName < StandardError; end
|
12
13
|
end
|
13
14
|
end
|
@@ -0,0 +1,51 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "receptacle/errors"
|
4
|
+
|
5
|
+
module Receptacle
|
6
|
+
module Repo
|
7
|
+
module ClassMethods
|
8
|
+
def mediate(method_name)
|
9
|
+
define_singleton_method(method_name) do |*args, **kwargs|
|
10
|
+
raise Errors::NotConfigured.new(repo: self) unless @strategy
|
11
|
+
|
12
|
+
with_wrappers(@wrappers.dup, method_name, *args, **kwargs) do |*sub_args, **sub_kwargs|
|
13
|
+
strategy.new.public_send(method_name, *sub_args, **sub_kwargs)
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
def wrappers(wrappers)
|
19
|
+
@wrappers = wrappers
|
20
|
+
end
|
21
|
+
|
22
|
+
def strategy(value = nil)
|
23
|
+
if value
|
24
|
+
@strategy = value
|
25
|
+
else
|
26
|
+
@strategy
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
private
|
31
|
+
|
32
|
+
def with_wrappers(wrappers, method_name, *args, **kwargs, &block)
|
33
|
+
next_wrapper = wrappers.shift
|
34
|
+
if next_wrapper&.method_defined?(method_name)
|
35
|
+
next_wrapper.new.public_send(method_name, *args, **kwargs) do |*sub_args, **sub_kwargs|
|
36
|
+
with_wrappers(wrappers, method_name, *sub_args, **sub_kwargs, &block)
|
37
|
+
end
|
38
|
+
elsif next_wrapper
|
39
|
+
with_wrappers(wrappers, method_name, *args, **kwargs, &block)
|
40
|
+
else
|
41
|
+
yield(*args, **kwargs)
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
def self.included(base)
|
47
|
+
base.instance_variable_set(:@wrappers, [])
|
48
|
+
base.extend(ClassMethods)
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
@@ -1,4 +1,5 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
|
+
|
2
3
|
module Receptacle
|
3
4
|
module TestSupport
|
4
5
|
# with_strategy
|
@@ -7,7 +8,7 @@ module Receptacle
|
|
7
8
|
#
|
8
9
|
# can be used in rspec like this
|
9
10
|
#
|
10
|
-
# require 'receptacle/test_support'
|
11
|
+
# require 'receptacle/test_support'
|
11
12
|
# RSpec.configure do |c|
|
12
13
|
# c.include Receptacle::TestSupport
|
13
14
|
# end
|
@@ -46,21 +47,5 @@ module Receptacle
|
|
46
47
|
ensure
|
47
48
|
repo.strategy original_strategy
|
48
49
|
end
|
49
|
-
|
50
|
-
# ensure_method_delegators
|
51
|
-
#
|
52
|
-
# When using something like `allow(SomeRepo).to receive(:find)` (where find
|
53
|
-
# is a mediated method) before the method was called the first time Rspec
|
54
|
-
# would stub the method with the wrong arity of 0 when also using jruby.
|
55
|
-
# This seems to be caused by the lazily defined methods. Simply calling the
|
56
|
-
# following method in a before hook when method stubbing is need solves this
|
57
|
-
# issue. As it's a problem which only affects mocking libraries it's
|
58
|
-
# currently not planned to change this behavior.
|
59
|
-
#
|
60
|
-
def ensure_method_delegators(repo)
|
61
|
-
Receptacle::Registration.repositories[repo].methods.each do |method_name|
|
62
|
-
repo.__build_method(method_name)
|
63
|
-
end
|
64
|
-
end
|
65
50
|
end
|
66
51
|
end
|
data/lib/receptacle/version.rb
CHANGED