rider-kick 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.rspec +3 -0
- data/.rubocop.yml +1141 -0
- data/CHANGELOG.md +5 -0
- data/LICENSE.txt +21 -0
- data/README.md +62 -0
- data/Rakefile +12 -0
- data/lib/rider-kick.rb +14 -0
- data/lib/rider_kick/builders/abstract_active_record_entity_builder.rb +124 -0
- data/lib/rider_kick/entities/failure_details.rb +30 -0
- data/lib/rider_kick/matchers/use_case_result.rb +51 -0
- data/lib/rider_kick/matchers/use_case_result_spec.rb +63 -0
- data/lib/rider_kick/types.rb +10 -0
- data/lib/rider_kick/use_cases/abstract_use_case.rb +36 -0
- data/lib/rider_kick/use_cases/contract.rb +9 -0
- data/lib/rider_kick/version.rb +6 -0
- data/sig/rider_kick.rbs +4 -0
- metadata +185 -0
data/CHANGELOG.md
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
The MIT License (MIT)
|
2
|
+
|
3
|
+
Copyright (c) 2024 kotarominami
|
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
|
13
|
+
all 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
|
21
|
+
THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,62 @@
|
|
1
|
+
# RiderKick
|
2
|
+
This gem provides helper interfaces and classes to assist in the construction of application with
|
3
|
+
Clean Architecture, as described in [Robert Martin's seminal book](https://www.amazon.com/gp/product/0134494164).
|
4
|
+
|
5
|
+
|
6
|
+
## Installation
|
7
|
+
|
8
|
+
Add this line to your application's Gemfile:
|
9
|
+
|
10
|
+
```ruby
|
11
|
+
gem 'rider-kick'
|
12
|
+
```
|
13
|
+
|
14
|
+
And then execute:
|
15
|
+
|
16
|
+
$ bundle install
|
17
|
+
$ bundle binstubs rider-kick
|
18
|
+
|
19
|
+
## Philosophy
|
20
|
+
|
21
|
+
The intention of this gem is to help you build applications that are built from the use case down,
|
22
|
+
and decisions about I/O can be deferred until the last possible moment.
|
23
|
+
|
24
|
+
## Clean Architecture
|
25
|
+
This structure provides helper interfaces and classes to assist in the construction of application with Clean Architecture, as described in Robert Martin's seminal book.
|
26
|
+
|
27
|
+
```
|
28
|
+
- app
|
29
|
+
- services
|
30
|
+
- api
|
31
|
+
- ...
|
32
|
+
- domains
|
33
|
+
- entities (Contract Response)
|
34
|
+
- builder
|
35
|
+
- repositories (Business logic)
|
36
|
+
- use_cases (Just Usecase)
|
37
|
+
- utils (Class Reusable)
|
38
|
+
```
|
39
|
+
## Screaming architecture - use cases as an organisational principle
|
40
|
+
Uncle Bob suggests that your source code organisation should allow developers to easily find a listing of all use cases your application provides. Here's an example of how this might look in a this application.
|
41
|
+
```
|
42
|
+
- app
|
43
|
+
- domains
|
44
|
+
- core
|
45
|
+
...
|
46
|
+
- usecase
|
47
|
+
- retail_customer_opens_bank_account.rb
|
48
|
+
- retail_customer_makes_deposit.rb
|
49
|
+
- ...
|
50
|
+
```
|
51
|
+
Note that the use case name contains:
|
52
|
+
|
53
|
+
- the user role
|
54
|
+
- the action
|
55
|
+
- the (sometimes implied) subject
|
56
|
+
```ruby
|
57
|
+
[user role][action][subject].rb
|
58
|
+
# retail_customer_opens_bank_account.rb
|
59
|
+
# admin_fetch_info.rb [specific usecase]
|
60
|
+
# fetch_info.rb [generic usecase] every role can access it
|
61
|
+
```
|
62
|
+
|
data/Rakefile
ADDED
data/lib/rider-kick.rb
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'rider_kick/entities/failure_details'
|
4
|
+
require 'rider_kick/builders/abstract_active_record_entity_builder'
|
5
|
+
require 'rider_kick/matchers/use_case_result'
|
6
|
+
require 'rider_kick/use_cases/abstract_use_case'
|
7
|
+
require 'rider_kick/use_cases/contract'
|
8
|
+
|
9
|
+
require 'rider_kick/types'
|
10
|
+
require 'rider_kick/version'
|
11
|
+
|
12
|
+
module RiderKick
|
13
|
+
class Error < StandardError; end
|
14
|
+
end
|
@@ -0,0 +1,124 @@
|
|
1
|
+
# typed: false
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
module RiderKick
|
5
|
+
module Builders
|
6
|
+
# Helps to take an instance of an AR model and wrap it up in the given Entity
|
7
|
+
# Any columns from the AR model that do not directly map to an attribute on the Entity
|
8
|
+
# can be specified by overriding #attributes_for_entity.
|
9
|
+
class AbstractActiveRecordEntityBuilder
|
10
|
+
# @param [Class] A Dry::Struct based entity that this builder will construct instances of
|
11
|
+
def self.acts_as_builder_for_entity(entity_class)
|
12
|
+
@has_many_builders = []
|
13
|
+
@belongs_to_builders = []
|
14
|
+
|
15
|
+
define_singleton_method :has_many_builders do
|
16
|
+
@has_many_builders
|
17
|
+
end
|
18
|
+
|
19
|
+
define_singleton_method :belongs_to_builders do
|
20
|
+
@belongs_to_builders
|
21
|
+
end
|
22
|
+
|
23
|
+
define_method :entity_class do
|
24
|
+
entity_class
|
25
|
+
end
|
26
|
+
|
27
|
+
private :entity_class
|
28
|
+
end
|
29
|
+
|
30
|
+
def self.has_many(relation_name, use:)
|
31
|
+
@has_many_builders << [relation_name, use]
|
32
|
+
end
|
33
|
+
|
34
|
+
def self.belongs_to(relation_name, use:)
|
35
|
+
@belongs_to_builders << [relation_name, use]
|
36
|
+
end
|
37
|
+
|
38
|
+
# @param [ActiveRecord::Base] An ActiveRecord model to map to the entity
|
39
|
+
def initialize(params)
|
40
|
+
@params = params
|
41
|
+
end
|
42
|
+
|
43
|
+
def build
|
44
|
+
entity_class.new(all_attributes_for_entity)
|
45
|
+
end
|
46
|
+
|
47
|
+
private
|
48
|
+
|
49
|
+
attr_reader :params
|
50
|
+
|
51
|
+
def entity_attribute_names
|
52
|
+
@entity_attributes ||= begin
|
53
|
+
if entity_class.respond_to?(:schema) # Dry::Struct
|
54
|
+
schema_keys = entity_class.schema.keys
|
55
|
+
elsif entity_class.respond_to?(:decorator) # T::Struct
|
56
|
+
schema_keys = entity_class.decorator.props.keys
|
57
|
+
else
|
58
|
+
raise 'Cannot determine schema format'
|
59
|
+
end
|
60
|
+
first_key = schema_keys.first
|
61
|
+
if first_key.is_a?(Symbol)
|
62
|
+
schema_keys
|
63
|
+
elsif first_key.respond_to?(:name)
|
64
|
+
schema_keys.map(&:name)
|
65
|
+
else
|
66
|
+
raise 'Cannot determine schema format'
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
def params_attributes
|
72
|
+
@params_attributes ||= @params.attributes
|
73
|
+
end
|
74
|
+
|
75
|
+
def symbolized_params_attributes
|
76
|
+
@symbolized_params_attributes ||= Hash[
|
77
|
+
params_attributes.map { |(key, value)| [key.to_sym, value] }
|
78
|
+
]
|
79
|
+
end
|
80
|
+
|
81
|
+
def ar_attributes_for_entity
|
82
|
+
symbolized_params_attributes.slice(*entity_attribute_names)
|
83
|
+
end
|
84
|
+
|
85
|
+
def attributes_for_belongs_to_relations
|
86
|
+
self.class.belongs_to_builders.map do |belongs_to_builder_config|
|
87
|
+
relation_name, builder_class = belongs_to_builder_config
|
88
|
+
relation = @params.public_send(relation_name)
|
89
|
+
|
90
|
+
[
|
91
|
+
relation_name,
|
92
|
+
relation ? builder_class.new(relation).build : nil
|
93
|
+
]
|
94
|
+
end.to_h
|
95
|
+
end
|
96
|
+
|
97
|
+
def attributes_for_has_many_relations
|
98
|
+
self.class.has_many_builders.map do |has_many_builder_config|
|
99
|
+
relation_name, builder_class = has_many_builder_config
|
100
|
+
relations = @params.public_send(relation_name)
|
101
|
+
built_relations = relations.map do |relation|
|
102
|
+
builder_class.new(relation).build
|
103
|
+
end
|
104
|
+
|
105
|
+
[
|
106
|
+
relation_name,
|
107
|
+
built_relations
|
108
|
+
]
|
109
|
+
end.to_h
|
110
|
+
end
|
111
|
+
|
112
|
+
def attributes_for_entity
|
113
|
+
{}
|
114
|
+
end
|
115
|
+
|
116
|
+
def all_attributes_for_entity
|
117
|
+
ar_attributes_for_entity
|
118
|
+
.merge(attributes_for_belongs_to_relations)
|
119
|
+
.merge(attributes_for_has_many_relations)
|
120
|
+
.merge(attributes_for_entity)
|
121
|
+
end
|
122
|
+
end
|
123
|
+
end
|
124
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
# typed: false
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
require 'rider_kick/types'
|
5
|
+
require 'dry/struct'
|
6
|
+
|
7
|
+
module RiderKick
|
8
|
+
module Entities
|
9
|
+
class FailureDetails < Dry::Struct
|
10
|
+
failure_types = Types::Strict::String.enum(
|
11
|
+
'error',
|
12
|
+
'expectation_failed',
|
13
|
+
'not_found',
|
14
|
+
'unauthorized',
|
15
|
+
'unprocessable_entity'
|
16
|
+
)
|
17
|
+
attribute :type, failure_types
|
18
|
+
attribute :message, Types::Strict::String
|
19
|
+
attribute :other_properties, Types::Strict::Hash.default({}.freeze)
|
20
|
+
|
21
|
+
def self.from_array(array)
|
22
|
+
new(message: 'failure 1, failure 2', other_properties: {}, type: 'error')
|
23
|
+
end
|
24
|
+
|
25
|
+
def self.from_string(string)
|
26
|
+
new(message: string, other_properties: {}, type: 'error')
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,51 @@
|
|
1
|
+
# typed: true
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
require 'rider_kick/entities/failure_details'
|
5
|
+
require 'dry-matcher'
|
6
|
+
require 'dry/monads/all'
|
7
|
+
|
8
|
+
module RiderKick
|
9
|
+
module Matchers
|
10
|
+
class UseCaseResult
|
11
|
+
def self.call(result, &block)
|
12
|
+
new.matcher.call(result, &block)
|
13
|
+
end
|
14
|
+
|
15
|
+
def matcher
|
16
|
+
Dry::Matcher.new(success: success_case, failure: failure_case)
|
17
|
+
end
|
18
|
+
|
19
|
+
private
|
20
|
+
|
21
|
+
def success_case
|
22
|
+
Dry::Matcher::Case.new(
|
23
|
+
match: ->(value) { value.is_a?(Dry::Monads::Success) },
|
24
|
+
resolve: ->(value) { value.value! }
|
25
|
+
)
|
26
|
+
end
|
27
|
+
|
28
|
+
def failure_case
|
29
|
+
Dry::Matcher::Case.new(
|
30
|
+
match: ->(value) { value.is_a?(Dry::Monads::Failure) },
|
31
|
+
resolve: ->(value) { resolve_failure_value(value) }
|
32
|
+
)
|
33
|
+
end
|
34
|
+
|
35
|
+
def resolve_failure_value(value)
|
36
|
+
failure = value.failure
|
37
|
+
case failure
|
38
|
+
when Array
|
39
|
+
Entities::FailureDetails.from_array(failure)
|
40
|
+
when String
|
41
|
+
Entities::FailureDetails.from_string(failure)
|
42
|
+
when Entities::FailureDetails
|
43
|
+
failure
|
44
|
+
else
|
45
|
+
type_list = [Array, String, Entities::FailureDetails].map(&:to_s).join(' or ')
|
46
|
+
raise ArgumentError, "Unexpected failure value - must be #{type_list}"
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
@@ -0,0 +1,63 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'rider_kick/matchers/use_case_result'
|
4
|
+
|
5
|
+
RSpec.describe RiderKick::Matchers::UseCaseResult do
|
6
|
+
describe '.call' do
|
7
|
+
subject(:call) do
|
8
|
+
described_class.call(result) do |matcher|
|
9
|
+
matcher.success(&:to_s)
|
10
|
+
matcher.failure { |failure_details| failure_details }
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
context do
|
15
|
+
let(:result) { Dry::Monads::Success('success!') }
|
16
|
+
|
17
|
+
it { is_expected.to eq 'success!' }
|
18
|
+
end
|
19
|
+
|
20
|
+
context do
|
21
|
+
let(:result) { Dry::Monads::Failure('failure!') }
|
22
|
+
|
23
|
+
specify do
|
24
|
+
expect(call).to eq RiderKick::Entities::FailureDetails.new(
|
25
|
+
message: 'failure!',
|
26
|
+
other_properties: {},
|
27
|
+
type: 'error'
|
28
|
+
)
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
context do
|
33
|
+
let(:result) { Dry::Monads::Failure(['failure 1', 'failure 2']) }
|
34
|
+
|
35
|
+
specify do
|
36
|
+
expect(call).to eq RiderKick::Entities::FailureDetails.new(
|
37
|
+
message: 'failure 1, failure 2',
|
38
|
+
other_properties: {},
|
39
|
+
type: 'error'
|
40
|
+
)
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
context do
|
45
|
+
let(:failure_details) do
|
46
|
+
RiderKick::Entities::FailureDetails.new(
|
47
|
+
message: 'failure!',
|
48
|
+
other_properties: { a: :b },
|
49
|
+
type: 'unauthorized'
|
50
|
+
)
|
51
|
+
end
|
52
|
+
let(:result) { Dry::Monads::Failure(failure_details) }
|
53
|
+
|
54
|
+
it { is_expected.to eq failure_details }
|
55
|
+
end
|
56
|
+
|
57
|
+
context do
|
58
|
+
let(:result) { Dry::Monads::Failure(:no) }
|
59
|
+
|
60
|
+
specify { expect { call }.to raise_error ArgumentError }
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
# typed: true
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
require 'dry/monads/result'
|
5
|
+
require 'dry/validation'
|
6
|
+
require 'dry/matcher/result_matcher'
|
7
|
+
require 'rider_kick/use_cases/contract'
|
8
|
+
|
9
|
+
module RiderKick
|
10
|
+
module UseCases
|
11
|
+
class AbstractUseCase
|
12
|
+
include Dry::Monads[:result]
|
13
|
+
|
14
|
+
def self.contract(base_contract = Contract, &proc)
|
15
|
+
@contract ||= Class.new(base_contract, &proc)
|
16
|
+
end
|
17
|
+
|
18
|
+
def self.contract!(args)
|
19
|
+
context = args.fetch(:context, {})
|
20
|
+
@results = @contract.new(context).call(args)
|
21
|
+
end
|
22
|
+
|
23
|
+
def initialize(contract)
|
24
|
+
@contract = contract
|
25
|
+
end
|
26
|
+
|
27
|
+
def build_parameter!
|
28
|
+
if @contract.success?
|
29
|
+
Success(Hashie::Mash.new(@contract.to_h))
|
30
|
+
else
|
31
|
+
Failure(@contract.errors.to_h)
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
data/sig/rider_kick.rbs
ADDED
metadata
ADDED
@@ -0,0 +1,185 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: rider-kick
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Kotaro Minami
|
8
|
+
autorequire:
|
9
|
+
bindir: exe
|
10
|
+
cert_chain: []
|
11
|
+
date: 2024-09-01 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: dry-matcher
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: 1.0.0
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: 1.0.0
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: dry-monads
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: 1.6.0
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: 1.6.0
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: dry-struct
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - "~>"
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: 1.6.0
|
48
|
+
type: :runtime
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - "~>"
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: 1.6.0
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: dry-transaction
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - "~>"
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: 0.16.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.16.0
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: dry-types
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - "~>"
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: 1.7.2
|
76
|
+
type: :runtime
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - "~>"
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: 1.7.2
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: dry-validation
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - "~>"
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: 1.10.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.10.0
|
97
|
+
- !ruby/object:Gem::Dependency
|
98
|
+
name: bundler
|
99
|
+
requirement: !ruby/object:Gem::Requirement
|
100
|
+
requirements:
|
101
|
+
- - "~>"
|
102
|
+
- !ruby/object:Gem::Version
|
103
|
+
version: 2.5.18
|
104
|
+
type: :development
|
105
|
+
prerelease: false
|
106
|
+
version_requirements: !ruby/object:Gem::Requirement
|
107
|
+
requirements:
|
108
|
+
- - "~>"
|
109
|
+
- !ruby/object:Gem::Version
|
110
|
+
version: 2.5.18
|
111
|
+
- !ruby/object:Gem::Dependency
|
112
|
+
name: rake
|
113
|
+
requirement: !ruby/object:Gem::Requirement
|
114
|
+
requirements:
|
115
|
+
- - "~>"
|
116
|
+
- !ruby/object:Gem::Version
|
117
|
+
version: 13.2.1
|
118
|
+
type: :development
|
119
|
+
prerelease: false
|
120
|
+
version_requirements: !ruby/object:Gem::Requirement
|
121
|
+
requirements:
|
122
|
+
- - "~>"
|
123
|
+
- !ruby/object:Gem::Version
|
124
|
+
version: 13.2.1
|
125
|
+
- !ruby/object:Gem::Dependency
|
126
|
+
name: rspec
|
127
|
+
requirement: !ruby/object:Gem::Requirement
|
128
|
+
requirements:
|
129
|
+
- - "~>"
|
130
|
+
- !ruby/object:Gem::Version
|
131
|
+
version: 3.13.0
|
132
|
+
type: :development
|
133
|
+
prerelease: false
|
134
|
+
version_requirements: !ruby/object:Gem::Requirement
|
135
|
+
requirements:
|
136
|
+
- - "~>"
|
137
|
+
- !ruby/object:Gem::Version
|
138
|
+
version: 3.13.0
|
139
|
+
description: An attempt at building a reusable Clean Architecture framework for Ruby.
|
140
|
+
email:
|
141
|
+
- kotaroisme@gmail.com
|
142
|
+
executables: []
|
143
|
+
extensions: []
|
144
|
+
extra_rdoc_files: []
|
145
|
+
files:
|
146
|
+
- ".rspec"
|
147
|
+
- ".rubocop.yml"
|
148
|
+
- CHANGELOG.md
|
149
|
+
- LICENSE.txt
|
150
|
+
- README.md
|
151
|
+
- Rakefile
|
152
|
+
- lib/rider-kick.rb
|
153
|
+
- lib/rider_kick/builders/abstract_active_record_entity_builder.rb
|
154
|
+
- lib/rider_kick/entities/failure_details.rb
|
155
|
+
- lib/rider_kick/matchers/use_case_result.rb
|
156
|
+
- lib/rider_kick/matchers/use_case_result_spec.rb
|
157
|
+
- lib/rider_kick/types.rb
|
158
|
+
- lib/rider_kick/use_cases/abstract_use_case.rb
|
159
|
+
- lib/rider_kick/use_cases/contract.rb
|
160
|
+
- lib/rider_kick/version.rb
|
161
|
+
- sig/rider_kick.rbs
|
162
|
+
homepage: https://github.com/kotaroisme/rider-kick
|
163
|
+
licenses:
|
164
|
+
- MIT
|
165
|
+
metadata: {}
|
166
|
+
post_install_message:
|
167
|
+
rdoc_options: []
|
168
|
+
require_paths:
|
169
|
+
- lib
|
170
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
171
|
+
requirements:
|
172
|
+
- - ">="
|
173
|
+
- !ruby/object:Gem::Version
|
174
|
+
version: 3.0.0
|
175
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
176
|
+
requirements:
|
177
|
+
- - ">="
|
178
|
+
- !ruby/object:Gem::Version
|
179
|
+
version: '0'
|
180
|
+
requirements: []
|
181
|
+
rubygems_version: 3.5.18
|
182
|
+
signing_key:
|
183
|
+
specification_version: 4
|
184
|
+
summary: Clean Architecture Framework.
|
185
|
+
test_files: []
|