Skip to content

Commit c179520

Browse files
Fix and write specs, fix bugs, change minimal ruby version
1 parent 3a674f9 commit c179520

18 files changed

+425
-72
lines changed

.github/workflows/test.yml

+2-2
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ jobs:
1616
- uses: actions/checkout@v2
1717
- uses: ruby/setup-ruby@v1
1818
with:
19-
ruby-version: "3.1"
19+
ruby-version: "3.3"
2020
bundler-cache: true
2121
- name: Run Linter
2222
run: bundle exec ci-helper RubocopLint
@@ -43,7 +43,7 @@ jobs:
4343
strategy:
4444
fail-fast: false
4545
matrix:
46-
ruby: ["2.7", "3.0"]
46+
ruby: ["3.1", "3.2"]
4747
experimental: [false]
4848
include:
4949
- ruby: head

.rubocop.yml

+1-1
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ inherit_gem:
33

44
AllCops:
55
DisplayCopNames: true
6-
TargetRubyVersion: 3.2
6+
TargetRubyVersion: 3.1
77

88
Naming/MethodParameterName:
99
AllowedNames: ["x", "y", "z"]

Gemfile

+3-2
Original file line numberDiff line numberDiff line change
@@ -6,12 +6,13 @@ gemspec
66

77
gem "bundler-audit"
88
gem "ci-helper"
9-
gem "dry-initializer"
109
gem "pry"
10+
gem "qonfig"
1111
gem "rake"
1212
gem "rspec"
1313
gem "rubocop-config-umbrellio"
1414
gem "simplecov"
1515
gem "simplecov-lcov"
16+
17+
gem "dry-initializer"
1618
gem "smart_initializer"
17-
gem "qonfig", "0.28.0"

Gemfile.lock

+2-6
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,11 @@ PATH
22
remote: .
33
specs:
44
resol (1.0.0)
5-
dry-initializer (~> 3.1)
6-
smart_initializer (~> 0.7)
75

86
GEM
97
remote: https://rubygems.org/
108
specs:
11-
activesupport (8.0.1)
9+
activesupport (7.2.2.1)
1210
base64
1311
benchmark (>= 0.3)
1412
bigdecimal
@@ -20,7 +18,6 @@ GEM
2018
minitest (>= 5.1)
2119
securerandom (>= 0.3)
2220
tzinfo (~> 2.0, >= 2.0.5)
23-
uri (>= 0.13.1)
2421
ast (2.4.2)
2522
base64 (0.2.0)
2623
benchmark (0.4.0)
@@ -134,7 +131,6 @@ GEM
134131
umbrellio-sequel-plugins (0.17.0)
135132
sequel
136133
unicode-display_width (2.6.0)
137-
uri (1.0.2)
138134

139135
PLATFORMS
140136
arm64-darwin-21
@@ -149,7 +145,7 @@ DEPENDENCIES
149145
ci-helper
150146
dry-initializer
151147
pry
152-
qonfig (= 0.28.0)
148+
qonfig
153149
rake
154150
resol!
155151
rspec

lib/resol/initializers.rb

+13-3
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@ def apply!(service_class, initializer_name)
2020
else
2121
raise ArgumentError, "unknown initializer #{initializer_name}"
2222
end
23+
24+
self.applied_classes << service_class.name
2325
end
2426

2527
private
@@ -28,16 +30,24 @@ def apply!(service_class, initializer_name)
2830

2931
def validate_state!(service_class)
3032
applied_parent = service_class
31-
return if service_class.ancestors.none? { |klass| klass.name.start_with?(MOD_MATCH_REGEX) }
33+
return if service_class.ancestors.none? { |klass| klass.inspect.start_with?(MOD_MATCH_REGEX) }
3234

3335
loop do
3436
applied_parent = applied_parent.superclass or break
3537

3638
break if applied_classes.include?(applied_parent.name)
3739
end
3840

39-
err_message = "#{applied_parent.name} or his superclasses manually include initializer dsl"
40-
raise ArgumentError, err_message
41+
if applied_parent.nil?
42+
error!("use ::use_initializer! method on desired service class")
43+
end
44+
45+
err_message = "#{applied_parent.name} or his superclasses already used initialize lib"
46+
error!(err_message)
47+
end
48+
49+
def error!(message)
50+
raise ArgumentError, message
4151
end
4252
end
4353
end

lib/resol/plugins.rb

+10-8
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,13 @@ module Resol
66
module Plugins
77
PLUGINS_PATH = Pathname("resol/plugins")
88
class Manager
9-
def initialize
9+
def initialize(target_class = nil)
1010
self.plugins = []
11+
self.target_class = target_class || Resol::Service
1112
end
1213

1314
def plugin(plugin_name)
15+
plugin_name = plugin_name.to_s
1416
return if plugins.include?(plugin_name)
1517

1618
plugin_module = find_plugin_module(plugin_name)
@@ -27,21 +29,21 @@ def plugin(plugin_name)
2729

2830
private
2931

30-
attr_accessor :plugins
32+
attr_accessor :plugins, :target_class
3133

3234
def find_plugin_module(plugin_name)
3335
require PLUGINS_PATH.join(plugin_name)
34-
Plugins.const_get(classify_plugin_name(plugin_name))
36+
resolve_module(classify_plugin_name(plugin_name))
3537
rescue LoadError, NameError => e
36-
raise "Failed to load plugin '#{plugin_name}': #{e.message}"
38+
raise ArgumentError, "Failed to load plugin '#{plugin_name}': #{e.message}"
3739
end
3840

39-
def classify_plugin_name(string)
40-
string.split(/_|-/).map!(&:capitalize).join
41+
def resolve_module(module_name)
42+
Plugins.const_get(module_name)
4143
end
4244

43-
def target_class
44-
Resol::Service
45+
def classify_plugin_name(string)
46+
string.split(/_|-/).map!(&:capitalize).join
4547
end
4648
end
4749
end

lib/resol/plugins/dummy.rb

+7
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
# frozen_string_literal: true
2+
3+
module Resol
4+
module Plugins
5+
module Dummy; end
6+
end
7+
end

lib/resol/plugins/return_in_service.rb

+3-1
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,9 @@ def handle_catch(_service)
1111
end
1212

1313
def call_service(service)
14-
service.call.tap { |res| return unless res.is_a?(Service::Result) }
14+
service.call.tap do |res|
15+
return Resol::Service::NOT_EXITED unless res.is_a?(Service::Result)
16+
end
1517
end
1618
end
1719

lib/resol/result.rb

+2
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,9 @@
33
module Resol
44
class UnwrapError < StandardError; end
55

6+
# rubocop:disable Lint/EmptyClass
67
class Result; end
8+
# rubocop:enable Lint/EmptyClass
79

810
class Success < Result
911
def initialize(value)

lib/resol/service.rb

+11-16
Original file line numberDiff line numberDiff line change
@@ -27,26 +27,17 @@ def message
2727
end
2828
end
2929

30-
module ChildMethodRestriction
31-
def plugin(*)
32-
raise NoMethodError
33-
end
34-
35-
def manager
36-
raise NoMethodError
37-
end
38-
end
39-
4030
include Resol::Builder
4131
include Resol::Callbacks
4232

43-
Result = Struct.new(:data)
4433
NOT_EXITED = Object.new.freeze
34+
BASE_CLASS = self
35+
36+
Result = Struct.new(:data)
4537

4638
class << self
4739
def inherited(klass)
4840
klass.const_set(:Failure, Class.new(klass::Failure))
49-
klass.extend(ChildMethodRestriction)
5041
super
5142
end
5243

@@ -55,11 +46,15 @@ def use_initializer!(initializer_lib)
5546
end
5647

5748
def plugin(...)
49+
if self::BASE_CLASS != self
50+
raise ArgumentError, "can load plugins only on base Resol::Service"
51+
end
52+
5853
manager.plugin(...)
5954
end
6055

61-
def call(*, **)
62-
service = build(*, **)
56+
def call(...)
57+
service = build(...)
6358

6459
result = handle_catch(service) do
6560
service.instance_variable_set(:@__performing__, true)
@@ -130,8 +125,8 @@ def check_performing
130125
end
131126
end
132127

133-
def proceed_return(data)
134-
throw(self, data)
128+
def proceed_return(service, data)
129+
throw(service, data)
135130
end
136131
end
137132
end

resol.gemspec

+1-4
Original file line numberDiff line numberDiff line change
@@ -13,10 +13,7 @@ Gem::Specification.new do |spec|
1313
spec.homepage = "https://github.com/umbrellio/resol"
1414
spec.license = "MIT"
1515

16-
spec.required_ruby_version = Gem::Requirement.new(">= 3.2.0")
16+
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-initializer", "~> 3.1"
21-
spec.add_dependency "smart_initializer", "~> 0.7"
2219
end

spec/configuration_spec.rb

+23
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,27 @@
11
# frozen_string_literal: true
22

33
RSpec.describe Resol::Configuration do
4+
before { allow(described_class).to receive(:smart_not_loaded?).and_return(const_not_loaded?) }
5+
6+
let(:const_not_loaded?) { true }
7+
8+
it "#smart_config returns nil" do
9+
expect(described_class.smart_config).to eq(nil)
10+
end
11+
12+
context "with loaded const" do
13+
let(:const_not_loaded?) { false }
14+
15+
it "returns config" do
16+
expect(described_class.smart_config).to eq(SmartCore::Initializer::Configuration.config)
17+
end
18+
end
19+
20+
context "with original method" do
21+
before { allow(described_class).to receive(:smart_not_loaded?).and_call_original }
22+
23+
it "returns smartcore config" do
24+
expect(described_class.smart_config).to eq(SmartCore::Initializer::Configuration.config)
25+
end
26+
end
427
end

spec/initializers_spec.rb

+79
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,83 @@
11
# frozen_string_literal: true
22

33
RSpec.describe Resol::Initializers do
4+
def apply_initializer(forced_service_class = nil)
5+
described_class.apply!(forced_service_class || service_class, initializer_name)
6+
end
7+
8+
before { stub_const("InitializerTestClass", service_class) }
9+
10+
let(:service_class) do
11+
Class.new(Resol::Service) do
12+
def call
13+
success!
14+
end
15+
end
16+
end
17+
18+
let(:initializer_name) { :dry }
19+
let(:dry_modules) do
20+
["Dry::Initializer::Mixin::Root", start_with("Dry::Initializer::Mixin::Local")]
21+
end
22+
23+
it "properly extend service class with initializer" do
24+
apply_initializer
25+
expect(service_class.ancestors.map(&:to_s)).to include(*dry_modules)
26+
end
27+
28+
context "with unknown initializer lib" do
29+
let(:initializer_name) { :kek }
30+
31+
specify do
32+
expect { apply_initializer }.to raise_error(ArgumentError, "unknown initializer kek")
33+
end
34+
end
35+
36+
context "with already prepared parent" do
37+
before { stub_const("SecondChildService", second_child_service) }
38+
39+
let(:service_class) do
40+
Class.new(ReturnEngineService) do
41+
def call
42+
success!
43+
end
44+
end
45+
end
46+
47+
let(:second_child_service) do
48+
Class.new(InitializerTestClass)
49+
end
50+
51+
let(:error_message) do
52+
"ReturnEngineService or his superclasses already used initialize lib"
53+
end
54+
55+
specify do
56+
expect { apply_initializer(SecondChildService) }.to raise_error(ArgumentError, error_message)
57+
end
58+
end
59+
60+
context "with manually extended service" do
61+
before { stub_const("SecondChildService", second_child_service) }
62+
63+
let(:service_class) do
64+
Class.new(Resol::Service) do
65+
extend Dry::Initializer
66+
67+
def call
68+
success!
69+
end
70+
end
71+
end
72+
73+
let(:second_child_service) do
74+
Class.new(InitializerTestClass)
75+
end
76+
77+
let(:error_message) { "use ::use_initializer! method on desired service class" }
78+
79+
specify do
80+
expect { apply_initializer(SecondChildService) }.to raise_error(ArgumentError, error_message)
81+
end
82+
end
483
end

0 commit comments

Comments
 (0)