active_dry_deps 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 3e34547d07b50b0e36072bb5123235a49d239207c3c9bb9b24ed83522e4f5d61
4
+ data.tar.gz: 8373575064af5701a718d33326d24e916acca2554ddf86281668cd7fb4f2fd97
5
+ SHA512:
6
+ metadata.gz: c4db158d948e6ece58fe516c6e3417c15be87c863470cc881ae66dfa7b131e13c9ee5f8883472fe6a3aaf64c46509ce08eefa3c0a3c375f86b466477cf4779eb
7
+ data.tar.gz: fd0255de69130a9a9bebe07e95032d06bf77fe940f37bdaacfd1439afce4972b6ec83db58c154a5a824dbee80ceb73f516cbb89cded78e20ff25c6bda48e9993
data/.rspec ADDED
@@ -0,0 +1,3 @@
1
+ --format documentation
2
+ --color
3
+ --require spec_helper
data/.rubocop.yml ADDED
@@ -0,0 +1,17 @@
1
+ inherit_gem:
2
+ rubocop-gp:
3
+ - ./config/default.yml
4
+
5
+ Gp/OptArgParameters:
6
+ Enabled: false
7
+
8
+ Gp/ClassOrModuleDeclaredInWrongFile:
9
+ Exclude:
10
+ - lib/active_dry_deps/stub.rb
11
+
12
+ Gp/ModuleMethodInWrongFile:
13
+ Exclude:
14
+ - lib/active_dry_deps/stub.rb
15
+
16
+ AllCops:
17
+ TargetRubyVersion: 3.0
data/CHANGELOG.md ADDED
@@ -0,0 +1,5 @@
1
+ ## [Unreleased]
2
+
3
+ ## [0.1.0] - 2023-08-15
4
+
5
+ - Initial release
data/Gemfile ADDED
@@ -0,0 +1,15 @@
1
+ # frozen_string_literal: true
2
+
3
+ source 'https://rubygems.org'
4
+
5
+ gemspec
6
+
7
+ gem 'rake', '~> 13.0'
8
+
9
+ gem 'rspec', '~> 3.0'
10
+
11
+ gem 'activesupport'
12
+ gem 'combustion'
13
+ gem 'dry-container'
14
+ gem 'dry-system'
15
+ gem 'rubocop-gp', github: 'corp-gp/rubocop-gp', require: false
data/Gemfile.lock ADDED
@@ -0,0 +1,169 @@
1
+ GIT
2
+ remote: https://github.com/corp-gp/rubocop-gp.git
3
+ revision: 94d07b3b370a199f7d26094d3606d79a0cf92f57
4
+ specs:
5
+ rubocop-gp (0.0.3)
6
+ rubocop
7
+ rubocop-performance
8
+ rubocop-rails
9
+ rubocop-rspec
10
+
11
+ PATH
12
+ remote: .
13
+ specs:
14
+ active_dry_deps (0.1.0)
15
+ dry-configurable
16
+
17
+ GEM
18
+ remote: https://rubygems.org/
19
+ specs:
20
+ actionpack (7.0.7)
21
+ actionview (= 7.0.7)
22
+ activesupport (= 7.0.7)
23
+ rack (~> 2.0, >= 2.2.4)
24
+ rack-test (>= 0.6.3)
25
+ rails-dom-testing (~> 2.0)
26
+ rails-html-sanitizer (~> 1.0, >= 1.2.0)
27
+ actionview (7.0.7)
28
+ activesupport (= 7.0.7)
29
+ builder (~> 3.1)
30
+ erubi (~> 1.4)
31
+ rails-dom-testing (~> 2.0)
32
+ rails-html-sanitizer (~> 1.1, >= 1.2.0)
33
+ activesupport (7.0.7)
34
+ concurrent-ruby (~> 1.0, >= 1.0.2)
35
+ i18n (>= 1.6, < 2)
36
+ minitest (>= 5.1)
37
+ tzinfo (~> 2.0)
38
+ ast (2.4.2)
39
+ base64 (0.1.1)
40
+ builder (3.2.4)
41
+ combustion (1.3.7)
42
+ activesupport (>= 3.0.0)
43
+ railties (>= 3.0.0)
44
+ thor (>= 0.14.6)
45
+ concurrent-ruby (1.2.2)
46
+ crass (1.0.6)
47
+ diff-lcs (1.5.0)
48
+ dry-auto_inject (1.0.1)
49
+ dry-core (~> 1.0)
50
+ zeitwerk (~> 2.6)
51
+ dry-configurable (1.1.0)
52
+ dry-core (~> 1.0, < 2)
53
+ zeitwerk (~> 2.6)
54
+ dry-container (0.11.0)
55
+ concurrent-ruby (~> 1.0)
56
+ dry-core (1.0.1)
57
+ concurrent-ruby (~> 1.0)
58
+ zeitwerk (~> 2.6)
59
+ dry-inflector (1.0.0)
60
+ dry-system (1.0.1)
61
+ dry-auto_inject (~> 1.0, < 2)
62
+ dry-configurable (~> 1.0, < 2)
63
+ dry-core (~> 1.0, < 2)
64
+ dry-inflector (~> 1.0, < 2)
65
+ erubi (1.12.0)
66
+ i18n (1.14.1)
67
+ concurrent-ruby (~> 1.0)
68
+ json (2.6.3)
69
+ language_server-protocol (3.17.0.3)
70
+ loofah (2.21.3)
71
+ crass (~> 1.0.2)
72
+ nokogiri (>= 1.12.0)
73
+ method_source (1.0.0)
74
+ minitest (5.19.0)
75
+ nokogiri (1.15.4-arm64-darwin)
76
+ racc (~> 1.4)
77
+ nokogiri (1.15.4-x86_64-linux)
78
+ racc (~> 1.4)
79
+ parallel (1.23.0)
80
+ parser (3.2.2.3)
81
+ ast (~> 2.4.1)
82
+ racc
83
+ racc (1.7.1)
84
+ rack (2.2.8)
85
+ rack-test (2.1.0)
86
+ rack (>= 1.3)
87
+ rails-dom-testing (2.2.0)
88
+ activesupport (>= 5.0.0)
89
+ minitest
90
+ nokogiri (>= 1.6)
91
+ rails-html-sanitizer (1.6.0)
92
+ loofah (~> 2.21)
93
+ nokogiri (~> 1.14)
94
+ railties (7.0.7)
95
+ actionpack (= 7.0.7)
96
+ activesupport (= 7.0.7)
97
+ method_source
98
+ rake (>= 12.2)
99
+ thor (~> 1.0)
100
+ zeitwerk (~> 2.5)
101
+ rainbow (3.1.1)
102
+ rake (13.0.6)
103
+ regexp_parser (2.8.1)
104
+ rexml (3.2.6)
105
+ rspec (3.12.0)
106
+ rspec-core (~> 3.12.0)
107
+ rspec-expectations (~> 3.12.0)
108
+ rspec-mocks (~> 3.12.0)
109
+ rspec-core (3.12.2)
110
+ rspec-support (~> 3.12.0)
111
+ rspec-expectations (3.12.3)
112
+ diff-lcs (>= 1.2.0, < 2.0)
113
+ rspec-support (~> 3.12.0)
114
+ rspec-mocks (3.12.6)
115
+ diff-lcs (>= 1.2.0, < 2.0)
116
+ rspec-support (~> 3.12.0)
117
+ rspec-support (3.12.1)
118
+ rubocop (1.56.0)
119
+ base64 (~> 0.1.1)
120
+ json (~> 2.3)
121
+ language_server-protocol (>= 3.17.0)
122
+ parallel (~> 1.10)
123
+ parser (>= 3.2.2.3)
124
+ rainbow (>= 2.2.2, < 4.0)
125
+ regexp_parser (>= 1.8, < 3.0)
126
+ rexml (>= 3.2.5, < 4.0)
127
+ rubocop-ast (>= 1.28.1, < 2.0)
128
+ ruby-progressbar (~> 1.7)
129
+ unicode-display_width (>= 2.4.0, < 3.0)
130
+ rubocop-ast (1.29.0)
131
+ parser (>= 3.2.1.0)
132
+ rubocop-capybara (2.18.0)
133
+ rubocop (~> 1.41)
134
+ rubocop-factory_bot (2.23.1)
135
+ rubocop (~> 1.33)
136
+ rubocop-performance (1.19.0)
137
+ rubocop (>= 1.7.0, < 2.0)
138
+ rubocop-ast (>= 0.4.0)
139
+ rubocop-rails (2.20.2)
140
+ activesupport (>= 4.2.0)
141
+ rack (>= 1.1)
142
+ rubocop (>= 1.33.0, < 2.0)
143
+ rubocop-rspec (2.23.2)
144
+ rubocop (~> 1.33)
145
+ rubocop-capybara (~> 2.17)
146
+ rubocop-factory_bot (~> 2.22)
147
+ ruby-progressbar (1.13.0)
148
+ thor (1.2.2)
149
+ tzinfo (2.0.6)
150
+ concurrent-ruby (~> 1.0)
151
+ unicode-display_width (2.4.2)
152
+ zeitwerk (2.6.11)
153
+
154
+ PLATFORMS
155
+ arm64-darwin-21
156
+ x86_64-linux
157
+
158
+ DEPENDENCIES
159
+ active_dry_deps!
160
+ activesupport
161
+ combustion
162
+ dry-container
163
+ dry-system
164
+ rake (~> 13.0)
165
+ rspec (~> 3.0)
166
+ rubocop-gp!
167
+
168
+ BUNDLED WITH
169
+ 2.4.6
data/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2023 corp-gp
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,244 @@
1
+ ## Installation
2
+
3
+ Install the gem and add to the application's Gemfile by executing:
4
+
5
+ $ bundle add active_dry_deps
6
+
7
+ ## Dependency Injection
8
+
9
+ Dependency injection helps to break explicit dependencies between objects making
10
+ it much easier to maintain a [single
11
+ responsibility](https://en.wikipedia.org/wiki/Single_responsibility_principle)
12
+ and reduce [coupling](https://en.wikipedia.org/wiki/Coupling_(computer_programming))
13
+ in our class designs. This leads to more testable code and code that is more
14
+ resilient to change.
15
+
16
+ For a deeper background on Dependency Injection consider the
17
+ [Wikipedia](https://en.wikipedia.org/wiki/Dependency_injection) article on the
18
+ subject.
19
+
20
+ ## Usage
21
+
22
+ ### Basic
23
+ Under the hood `active_dry_deps` uses a container like [dry-container](https://dry-rb.org/gems/dry-container) and convert key to underscore for fetch from container.
24
+ For auto-registration dependencies use [dry-system](https://dry-rb.org/gems/dry-system/).
25
+
26
+ ```ruby
27
+ MyApp::Container.register('warehouse.create_departure_service', Class.new { def self.call = 'failure' })
28
+ include Deps['Warehouse::CreateDepartureService.call']
29
+ ```
30
+
31
+ `Deps['Warehouse::CreateDepartureService.call']` this notation is familiar to Ruby developers, helps to find code in the project, and simplifies the migration from constants in code to defining dependencies.
32
+
33
+ ```ruby
34
+ class CreateOrderService < ServiceObject
35
+
36
+ include Deps[
37
+ 'Warehouse::CreateDepartureService.call',
38
+ 'Warehouse::ReserveJob.perform_later',
39
+ 'OrderMailer',
40
+ 'redis',
41
+ track: 'StatsApi.message',
42
+ ]
43
+
44
+ def call(params)
45
+ order = Order.create(params)
46
+
47
+ ReserveJob(order)
48
+ track(order.id, order.created_at)
49
+
50
+ redis.with do |conn|
51
+ conn.incr('order_count')
52
+ end
53
+
54
+ OrderMailer().with(user: user).deliver_later
55
+
56
+ CreateDepartureService(order.slice(:id, :departure_at))
57
+ end
58
+
59
+ end
60
+ ```
61
+
62
+ ```ruby
63
+ describe 'CreateOrderService' do
64
+ it 'success create order' do
65
+ service = described_class.new(user: create(:user), zip_code: 67_345)
66
+ expect(service).to deps(CreateDepartureService: double(success?: true), ReserveJob: spy, track: spy)
67
+
68
+ expect(service.call.success?).to be true
69
+ end
70
+ end
71
+
72
+ ```
73
+
74
+ ### Import methods
75
+ You can inject any method from object in your container
76
+
77
+ ```ruby
78
+ MyApp::Container.register(:str, 'str')
79
+ MyApp::Container.register(:service, Module.new { def self.success? = true } )
80
+
81
+ include Deps['str.reverse', 'service.success?']
82
+ reverse # => "rts"
83
+ success? # => true
84
+ ```
85
+
86
+ ### Import callable methods
87
+ By default, when `call` or `perform_later` methods are imported, the name of the dependency is taken from the name of the constant:
88
+ ```ruby
89
+ include Deps[
90
+ 'Warehouse::CreateDepartureService.call', # callable
91
+ 'Warehouse::ReserveJob.perform_later', # callable
92
+ 'Warehouse::ReserveJob.perform_now',
93
+ 'Warehouse::ProductActivateQuery',
94
+ ]
95
+
96
+ # use as
97
+ CreateDepartureService()
98
+ ReserveJob()
99
+ perform_now
100
+ ProductActivateQuery().run
101
+ ```
102
+
103
+ Recommends using prefixes (`Service`, `Job`, `Query`) in the name of the constant for easy reading of the dependency type.
104
+
105
+ ### Aliases
106
+
107
+ ```ruby
108
+ include Deps[string: 'str.reverse', m: 'module']
109
+ string # => "rts"
110
+ m # => "success"
111
+ ```
112
+
113
+ ### Tests (Rspec)
114
+ #### deps
115
+ gem adds rspec matcher for stub dependency, put `require 'active_dry_deps/rspec'` to rspec setup
116
+
117
+ ```ruby
118
+ GpApp::Container.register('order.dependency', Class.new { def self.call = 'failure' })
119
+
120
+ let(:service_klass) do
121
+ Class.new do
122
+ include Deps['Order::Dependency.call']
123
+
124
+ def call = Dependency()
125
+ end
126
+ end
127
+
128
+ it 'failure' do
129
+ expect(service_klass.new.call).to be 'failure'
130
+ end
131
+
132
+ it 'success' do
133
+ service = service_klass.new
134
+ expect(service).to deps(Dependency: 'success')
135
+
136
+ expect(service.call).to be 'success'
137
+ end
138
+ ```
139
+
140
+ #### stub, unstub
141
+ ```ruby
142
+ it 'stub' do
143
+ Deps.stub('Order::Dependency', double(call: 'success'))
144
+ expect(service_klass.new.call).to be 'success'
145
+
146
+ Deps.unstub('Order::Dependency') # or simple Deps.unstub for unsub all keys
147
+ expect(service_klass.new.call).to be 'failure'
148
+ end
149
+ ```
150
+ ## Configuration
151
+ gem auto-configuring, but you can override settings
152
+
153
+ ```ruby
154
+ ActiveDryDeps.config.container = 'MyApp::Container'
155
+ ActiveDryDeps.config.inflector = ActiveSupport::Inflector
156
+ ActiveDryDeps.config.inject_global_constant = 'Deps'
157
+ ```
158
+
159
+ ### Recommended container setup with [dry-system](https://dry-rb.org/gems/dry-system/) for Rails
160
+
161
+ `config/initializers/system.rb`
162
+
163
+ ```ruby
164
+ require 'dry/system/container'
165
+
166
+ module GpApp
167
+ class ContainerRailtie < Rails::Railtie
168
+
169
+ LOADER =
170
+ Class.new(Dry::System::Loader) do
171
+ def self.call(component, *args)
172
+ constant = self.constant(component)
173
+
174
+ if singleton?(constant)
175
+ constant.instance(*args)
176
+ else
177
+ constant # constant.new(*args) - THIS LINE REWRITED from Dry::System::Loader
178
+ end
179
+ end
180
+ end
181
+
182
+ # https://api.rubyonrails.org/classes/Rails/Railtie.html
183
+ # Add a to_prepare block which is executed once in production
184
+ # and before each request in development.
185
+ config.to_prepare do
186
+ ContainerRailtie.finalize
187
+ end
188
+
189
+ def finalize
190
+ set_or_reload(:Container, create_container)
191
+ Dry::System.register_provider_sources(Pathname(__dir__).join('../system/providers').realpath)
192
+ create_container.finalize!(freeze: !(::Rails.env.test? || ::Rails.env.development?))
193
+ end
194
+
195
+ def create_container
196
+ Class.new(Dry::System::Container) do
197
+ configure do |config|
198
+ config.inflector = ActiveSupport::Inflector
199
+ config.root = Rails.root.join('app')
200
+
201
+ %w[domains jobs queries services mailers].each do |dir_name|
202
+ config.component_dirs.add dir_name do |dir|
203
+ dir.loader = LOADER
204
+ dir.memoize = true
205
+ end
206
+ end
207
+
208
+ config.component_dirs.add '../lib' do |dir|
209
+ dir.loader = LOADER
210
+ dir.memoize = true
211
+ end
212
+ end
213
+ end
214
+ end
215
+
216
+ def set_or_reload(const_name, const)
217
+ remove_constant(const_name)
218
+ GpApp.const_set(const_name, const)
219
+ end
220
+
221
+ def remove_constant(const_name)
222
+ if GpApp.const_defined?(const_name, false)
223
+ GpApp.__send__(:remove_const, const_name)
224
+ end
225
+ end
226
+
227
+ end
228
+ end
229
+
230
+ ```
231
+
232
+ ## Development
233
+
234
+ After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
235
+
236
+ To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and the created tag, and push the `.gem` file to [rubygems.org](https://rubygems.org).
237
+
238
+ ## Contributing
239
+
240
+ Bug reports and pull requests are welcome on GitHub at https://github.com/corp-gp/active_dry_deps.
241
+
242
+ ## License
243
+
244
+ The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
data/Rakefile ADDED
@@ -0,0 +1,12 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'bundler/gem_tasks'
4
+ require 'rspec/core/rake_task'
5
+
6
+ RSpec::Core::RakeTask.new(:spec)
7
+
8
+ require 'rubocop/rake_task'
9
+
10
+ RuboCop::RakeTask.new
11
+
12
+ task default: %i[spec rubocop]
@@ -0,0 +1,13 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'dry-configurable'
4
+
5
+ module ActiveDryDeps
6
+
7
+ extend Dry::Configurable
8
+
9
+ setting :container
10
+ setting :inflector, default: ActiveSupport::Inflector
11
+ setting :inject_global_constant, default: 'Deps'
12
+
13
+ end
@@ -0,0 +1,68 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ActiveDryDeps
4
+ module Deps
5
+
6
+ VALID_NAME = /([a-zA-Z_0-9]*)$/
7
+ METHODS_AS_KLASS = %w[perform_later call].freeze
8
+
9
+ module_function
10
+
11
+ # include Deps[routes_admin: 'Lib::Routes.admin'] use as `routes_admin`
12
+ # include Deps['Lib::Routes.admin'] use as `admin`
13
+ # include Deps['Lib::Routes'] use as `Routes()`
14
+ # include Deps['OrderService::Recalculate.call'] use as `Recalculate()`
15
+ def [](*keys, **aliases)
16
+ str_methods = +''
17
+
18
+ keys.each { |resolver| str_methods << str_method(resolver, nil) }
19
+ aliases.each { |alias_method, resolver| str_methods << str_method(resolver, alias_method) }
20
+
21
+ m = Module.new
22
+ m.module_eval(str_methods)
23
+ m
24
+ end
25
+
26
+ private def str_method(resolve, alias_method)
27
+ resolve_klass, extract_method = resolve.split('.')
28
+
29
+ alias_method ||=
30
+ if extract_method && METHODS_AS_KLASS.exclude?(extract_method)
31
+ extract_method
32
+ else
33
+ resolve_klass.split('::').last
34
+ end
35
+
36
+ if alias_method && !VALID_NAME.match?(alias_method.to_s)
37
+ raise DependencyNameInvalid, "name +#{alias_method}+ is not a valid Ruby identifier"
38
+ end
39
+
40
+ key = ActiveDryDeps.config.inflector.underscore(resolve_klass).tr('/', '.')
41
+
42
+ if extract_method
43
+ %(def #{alias_method}(...); ::#{ActiveDryDeps.config.container}['#{key}'].#{extract_method}(...) end\n)
44
+ else
45
+ %(def #{alias_method}; ::#{ActiveDryDeps.config.container}['#{key}'] end\n)
46
+ end
47
+ end
48
+
49
+ def resolve_key(key)
50
+ if key.include?('::')
51
+ ActiveDryDeps.config.inflector.underscore(key).tr('/', '.')
52
+ else
53
+ key
54
+ end
55
+ end
56
+
57
+ instance_eval <<~RUBY, __FILE__, __LINE__ + 1
58
+ # def resolve(key)
59
+ # ::MyApp::Container[resolve_key(key)]
60
+ # end
61
+
62
+ def resolve(key)
63
+ ::#{ActiveDryDeps.config.container}[resolve_key(key)]
64
+ end
65
+ RUBY
66
+
67
+ end
68
+ end
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ActiveDryDeps
4
+ class Railtie < ::Rails::Railtie
5
+
6
+ config.before_initialize do
7
+ app_namespace = ::Rails.application.class.to_s.split('::').first
8
+ ActiveDryDeps.config.container ||= "#{app_namespace}::Container"
9
+
10
+ require_relative 'deps'
11
+
12
+ Object.const_set(ActiveDryDeps.config.inject_global_constant, ::ActiveDryDeps::Deps)
13
+ ActiveDryDeps.config.finalize!(freeze_values: true)
14
+ end
15
+
16
+ end
17
+ end
@@ -0,0 +1,33 @@
1
+ # frozen_string_literal: true
2
+
3
+ RSpec::Matchers.define :deps do |*methods|
4
+ include RSpec::Mocks::Matchers::Matcher
5
+
6
+ # expect(described_instance).to deps(send_blanks: spy)
7
+ match do |stubbed_object|
8
+ methods[0].each do |method, returned_value|
9
+ expect(stubbed_object).to receive(method).and_return(returned_value)
10
+ end
11
+ end
12
+
13
+ # expect(described_instance).not_to deps(:send_blanks)
14
+ match_when_negated do |stubbed_object|
15
+ methods.each do |method|
16
+ expect(stubbed_object).not_to receive(method)
17
+ end
18
+ end
19
+
20
+ # allow(described_instance).to deps(send_blanks: spy)
21
+ def setup_allowance(subject)
22
+ proxy_subject = proxy_on(subject)
23
+
24
+ expected.each do |method, returned_value|
25
+ proxy_on(returned_value).add_simple_stub(:call, returned_value.call)
26
+ proxy_subject.add_simple_stub(method, returned_value)
27
+ end
28
+ end
29
+
30
+ private def proxy_on(subject)
31
+ RSpec::Mocks.space.proxy_for(subject)
32
+ end
33
+ end
@@ -0,0 +1,3 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'rspec/matchers'
@@ -0,0 +1,27 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ActiveDryDeps
4
+
5
+ module Stub
6
+
7
+ CONTAINER_CONST = Object.const_get(ActiveDryDeps.config.container)
8
+
9
+ def stub(path, ...)
10
+ CONTAINER_CONST.stub(Deps.resolve_key(path), ...)
11
+ end
12
+
13
+ def unstub(*keys)
14
+ CONTAINER_CONST.unstub(*keys.map { resolve_key(_1) })
15
+ end
16
+
17
+ end
18
+
19
+ module Deps
20
+
21
+ def self.enable_stubs!
22
+ extend Stub
23
+ end
24
+
25
+ end
26
+
27
+ end
@@ -0,0 +1,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ActiveDryDeps
4
+
5
+ VERSION = '0.1.0'
6
+
7
+ end
@@ -0,0 +1,12 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'active_dry_deps/version'
4
+ require_relative 'active_dry_deps/configuration'
5
+ require_relative 'active_dry_deps/railtie'
6
+
7
+ module ActiveDryDeps
8
+
9
+ class Error < StandardError; end
10
+ class DependencyNameInvalid < Error; end
11
+
12
+ end
metadata ADDED
@@ -0,0 +1,81 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: active_dry_deps
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Ermolaev Andrey
8
+ autorequire:
9
+ bindir: exe
10
+ cert_chain: []
11
+ date: 2023-08-25 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: dry-configurable
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
27
+ description: |-
28
+ ActiveDryDeps not modify constructor and support Dependency Injection for modules.
29
+ Also you can import method from any object in your container.
30
+ Adding extra dependencies is easy and improve readability your code.
31
+ email:
32
+ - andruhafirst@yandex.ru
33
+ executables: []
34
+ extensions: []
35
+ extra_rdoc_files: []
36
+ files:
37
+ - ".rspec"
38
+ - ".rubocop.yml"
39
+ - CHANGELOG.md
40
+ - Gemfile
41
+ - Gemfile.lock
42
+ - LICENSE
43
+ - README.md
44
+ - Rakefile
45
+ - lib/active_dry_deps.rb
46
+ - lib/active_dry_deps/configuration.rb
47
+ - lib/active_dry_deps/deps.rb
48
+ - lib/active_dry_deps/railtie.rb
49
+ - lib/active_dry_deps/rspec.rb
50
+ - lib/active_dry_deps/rspec/matchers.rb
51
+ - lib/active_dry_deps/stub.rb
52
+ - lib/active_dry_deps/version.rb
53
+ homepage: https://github.com/corp-gp/active_dry_deps
54
+ licenses:
55
+ - MIT
56
+ metadata:
57
+ allowed_push_host: https://rubygems.org
58
+ homepage_uri: https://github.com/corp-gp/active_dry_deps
59
+ source_code_uri: https://github.com/corp-gp/active_dry_deps
60
+ changelog_uri: https://github.com/corp-gp/active_dry_deps/CHANGELOG.md
61
+ rubygems_mfa_required: 'true'
62
+ post_install_message:
63
+ rdoc_options: []
64
+ require_paths:
65
+ - lib
66
+ required_ruby_version: !ruby/object:Gem::Requirement
67
+ requirements:
68
+ - - ">="
69
+ - !ruby/object:Gem::Version
70
+ version: 3.0.0
71
+ required_rubygems_version: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ requirements: []
77
+ rubygems_version: 3.3.17
78
+ signing_key:
79
+ specification_version: 4
80
+ summary: Dependency injection and resolution support for classes and modules.
81
+ test_files: []