Skip to content

Commit e667384

Browse files
Remove some classes, use new ones, add di
1 parent 9ee5195 commit e667384

11 files changed

+119
-132
lines changed

Gemfile.lock

+3
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ PATH
22
remote: .
33
specs:
44
resol (1.0.0)
5+
dry-container
56

67
GEM
78
remote: https://rubygems.org/
@@ -36,6 +37,8 @@ GEM
3637
diff-lcs (1.5.1)
3738
docile (1.4.1)
3839
drb (2.2.1)
40+
dry-container (0.11.0)
41+
concurrent-ruby (~> 1.0)
3942
dry-inflector (1.1.0)
4043
dry-initializer (3.1.1)
4144
i18n (1.14.6)

lib/resol.rb

+6-6
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,20 @@
11
# frozen_string_literal: true
22

3+
require "dry-container"
4+
35
require_relative "resol/version"
46
require_relative "resol/configuration"
5-
require_relative "resol/initializers"
7+
8+
require_relative "resol/injector"
69
require_relative "resol/service"
710
require_relative "resol/plugins"
11+
require_relative "resol/dependency_container"
812

913
module Resol
1014
extend self
1115

1216
def config
13-
Configuration
14-
end
15-
16-
def configure
17-
yield config
17+
@config ||= Configuration.new
1818
end
1919

2020
# rubocop:disable Naming/MethodName

lib/resol/configuration.rb

+8-8
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,19 @@
11
# frozen_string_literal: true
22

33
module Resol
4-
module Configuration
5-
extend self
4+
class Configuration
5+
DEFAULT_CONFIG_VALUES = { classes_allowed_to_patch: ["Resol::Service"] }.freeze
66

7-
def smart_config
8-
return nil if smart_not_loaded?
7+
def initialize
8+
self.data = DEFAULT_CONFIG_VALUES.deep_dup
9+
end
910

10-
SmartCore::Initializer::Configuration.config
11+
DEFAULT_CONFIG_VALUES.each_key do |setting_name|
12+
define_method(setting_name) { data.fetch(setting_name) }
1113
end
1214

1315
private
1416

15-
def smart_not_loaded?
16-
!defined?(SmartCore::Initializer::Configuration)
17-
end
17+
attr_accessor :data
1818
end
1919
end

lib/resol/dependency_handler.rb

+27
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
# frozen_string_literal: true
2+
3+
module Resol
4+
class DependencyHandler
5+
extend Dry::Container::Mixin
6+
7+
namespace(:external_libs) do
8+
register(:smartcore_injector, memoize: true) do
9+
require "smart_core/initializer"
10+
11+
installer_proc = proc { include SmartCore::Initializer }
12+
Resol::Injector.new(installer_proc)
13+
end
14+
15+
register(:dry_injector, memoize: true) do
16+
require "dry/initializer"
17+
18+
installer_proc = proc { extend Dry::Initializer }
19+
Resol::Injector.new(installer_proc)
20+
end
21+
end
22+
23+
namespace(:lib) do
24+
register(:plugin_manager) { Plugins::Manager.new }
25+
end
26+
end
27+
end

lib/resol/initializers.rb

-53
This file was deleted.

lib/resol/injector.rb

+26
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
# frozen_string_literal: true
2+
3+
module Resol
4+
class Injector
5+
InjectMarker = Module.new
6+
7+
def initialize(proc_register)
8+
self.proc_register = proc_register
9+
end
10+
11+
def inject!(service_class)
12+
error!("parent or this class already injected") if service_class.is_a?(InjectMarker)
13+
14+
service_class.instance_eval(&proc_register)
15+
service_class.include(InjectMarker)
16+
end
17+
18+
private
19+
20+
attr_accessor :proc_register
21+
22+
def error!(msg)
23+
raise msg
24+
end
25+
end
26+
end

lib/resol/plugins.rb

+12-6
Original file line numberDiff line numberDiff line change
@@ -6,30 +6,36 @@ module Resol
66
module Plugins
77
PLUGINS_PATH = Pathname("resol/plugins")
88
class Manager
9-
def initialize(target_class = nil)
9+
def initialize
10+
self.allowed_classes = resolve_allowed_classes
1011
self.plugins = []
11-
self.target_class = target_class || Resol::Service
1212
end
1313

14-
def plugin(plugin_name)
14+
def plugin(caller_class, plugin_name)
1515
plugin_name = plugin_name.to_s
16+
17+
return if allowed_classes.exclude?(caller_class)
1618
return if plugins.include?(plugin_name)
1719

1820
plugin_module = find_plugin_module(plugin_name)
1921
if defined?(plugin_module::InstanceMethods)
20-
target_class.prepend(plugin_module::InstanceMethods)
22+
caller_class.prepend(plugin_module::InstanceMethods)
2123
end
2224

2325
if defined?(plugin_module::ClassMethods)
24-
target_class.singleton_class.prepend(plugin_module::ClassMethods)
26+
caller_class.singleton_class.prepend(plugin_module::ClassMethods)
2527
end
2628

2729
plugins << plugin_name
2830
end
2931

3032
private
3133

32-
attr_accessor :plugins, :target_class
34+
attr_accessor :plugins
35+
36+
def resolve_allowed_classes
37+
Resol.config.classes_allowed_to_patch.map { |name| Object.const_get(name) }
38+
end
3339

3440
def find_plugin_module(plugin_name)
3541
require PLUGINS_PATH.join(plugin_name)

lib/resol/plugins/return_in_service.rb

-6
Original file line numberDiff line numberDiff line change
@@ -9,12 +9,6 @@ module ClassMethods
99
def handle_catch(_service)
1010
yield
1111
end
12-
13-
def call_service(service)
14-
service.call.tap do |res|
15-
return Resol::Service::NOT_EXITED unless res.is_a?(Service::Result)
16-
end
17-
end
1812
end
1913

2014
module InstanceMethods

lib/resol/service.rb

+29-43
Original file line numberDiff line numberDiff line change
@@ -30,9 +30,6 @@ def message
3030
include Resol::Builder
3131
include Resol::Callbacks
3232

33-
NOT_EXITED = Object.new.freeze
34-
BASE_CLASS = self
35-
3633
Result = Struct.new(:data)
3734

3835
class << self
@@ -41,16 +38,13 @@ def inherited(klass)
4138
super
4239
end
4340

44-
def use_initializer!(initializer_lib)
45-
Initializers.apply!(self, initializer_lib)
41+
def inject_initializer!(injector_name)
42+
injector = DependencyContainer.resolve("libs.#{injector_name}")
43+
injector.inject!(self)
4644
end
4745

4846
def plugin(...)
49-
if self::BASE_CLASS != self
50-
raise ArgumentError, "can load plugins only on base Resol::Service"
51-
end
52-
53-
manager.plugin(...)
47+
manager.plugin(self, ...)
5448
end
5549

5650
def call(...)
@@ -59,15 +53,12 @@ def call(...)
5953
result = handle_catch(service) do
6054
service.instance_variable_set(:@__performing__, true)
6155
__run_callbacks__(service)
62-
call_service(service)
56+
service.call
6357
end
58+
return Resol::Success(result.data) if service.__result_method__called__
6459

65-
if result == NOT_EXITED
66-
error_message = "No `#success!` or `#fail!` called in `#call` method in #{service.class}."
67-
raise InvalidCommandImplementation, error_message
68-
else
69-
Resol::Success(result.data)
70-
end
60+
error_message = "No `#success!` or `#fail!` called in `#call` method in #{service.class}."
61+
raise InvalidCommandImplementation, error_message
7162
rescue self::Failure => e
7263
Resol::Failure(e)
7364
end
@@ -79,50 +70,45 @@ def call!(...)
7970
private
8071

8172
def manager
82-
@manager ||= Plugins::Manager.new
83-
end
84-
85-
def handle_catch(service)
86-
catch(service) do
87-
yield
88-
NOT_EXITED
89-
end
73+
@manager ||= DependencyContainer.resolve(:base_plugin_manager)
9074
end
9175

92-
def call_service(service)
93-
service.call
94-
NOT_EXITED
76+
def handle_catch(service, &)
77+
catch(service, &)
9578
end
9679
end
9780

9881
# @!method call
9982

83+
attr_accessor :__result_method__called__
84+
10085
private
10186

10287
attr_reader :__performing__
10388

10489
def fail!(code, data = nil)
105-
check_performing do
106-
raise self.class::Failure.new(code, data)
107-
end
90+
check_performing!
91+
raise self.class::Failure.new(code, data)
10892
end
10993

11094
def success!(data = nil)
111-
check_performing do
112-
proceed_return(self, Result.new(data))
113-
end
95+
check_performing!
96+
result_method_called!
97+
proceed_return(self, Result.new(data))
11498
end
11599

116-
def check_performing
117-
if __performing__
118-
yield
119-
else
120-
error_message =
121-
"It looks like #call instance method was called directly in #{self.class}. " \
122-
"You must always use class-level `.call` or `.call!` method."
100+
def check_performing!
101+
return if __performing__
123102

124-
raise InvalidCommandCall, error_message
125-
end
103+
error_message =
104+
"It looks like #call instance method was called directly in #{self.class}. " \
105+
"You must always use class-level `.call` or `.call!` method."
106+
107+
raise InvalidCommandCall, error_message
108+
end
109+
110+
def result_method_called!
111+
self.__result_method__called__ = true
126112
end
127113

128114
def proceed_return(service, data)

resol.gemspec

+2
Original file line numberDiff line numberDiff line change
@@ -16,4 +16,6 @@ Gem::Specification.new do |spec|
1616
spec.required_ruby_version = Gem::Requirement.new(">= 3.1.0")
1717
spec.files = `git ls-files -z`.split("\x0").reject { |f| f.include?("spec") }
1818
spec.require_paths = ["lib"]
19+
20+
spec.add_dependency "dry-container"
1921
end

0 commit comments

Comments
 (0)