team_fastlane-domain_driven_design 1.0.0
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/CHANGELOG.adoc +39 -0
- data/README.adoc +7 -0
- data/lib/team_fastlane/domain_driven_design/entity_base.rb +46 -0
- data/lib/team_fastlane/domain_driven_design/repository_base.rb +128 -0
- data/lib/team_fastlane/domain_driven_design/version.rb +7 -0
- data/lib/team_fastlane/domain_driven_design.rb +10 -0
- metadata +51 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 6254016e8961513cb7097633e77fdda46e6bfb849a7776dc551f6a1531846256
|
4
|
+
data.tar.gz: ce3a1a9a7cbcf13246efd889dc9af63e10f2d4bd7873b8ca170b6842376c6196
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 9a16818fc6edd7c088aa458b5f83f86f869f402f31f21b3c77d2c518ff96edda5fe6efd76320a7456372364cfa0301fdb0daa570f83da445669bd27420d3e5b8
|
7
|
+
data.tar.gz: b64e3c3d4df0ec1e3fe68ff3e92e5ff7c836e2191a398fe4cd978130b9a2d6961dfc7cbb61d3fb1b89446a1fb4e4de98f6001dd73dbc8e119de1b2faf6c868c7
|
data/CHANGELOG.adoc
ADDED
@@ -0,0 +1,39 @@
|
|
1
|
+
= Changelog
|
2
|
+
|
3
|
+
All notable changes to this project will be documented in this file.
|
4
|
+
|
5
|
+
The format is based on https://keepachangelog.com[Keep a Changelog],
|
6
|
+
and this project adheres to https://semver.org[Semantic Versioning].
|
7
|
+
|
8
|
+
== Unreleased
|
9
|
+
|
10
|
+
== [1.0.0] - 2023-08-01
|
11
|
+
=== Changed
|
12
|
+
Renamed and restructured for release on rubygems
|
13
|
+
|
14
|
+
== [0.0.5] - 2022-01-03
|
15
|
+
=== Changed
|
16
|
+
- Small refactoring to comply to rubocop
|
17
|
+
|
18
|
+
== [0.0.4] - 2020-06-10
|
19
|
+
=== Added
|
20
|
+
- A basic readme
|
21
|
+
=== Changed
|
22
|
+
- Adjusted changelog more to keep-a-changelog-recommendation
|
23
|
+
- Cleanup gemspec
|
24
|
+
- Cleanup gem structure to match best practices
|
25
|
+
|
26
|
+
== [0.0.3] - 2020-05-19
|
27
|
+
=== Bugfix
|
28
|
+
- Applied Rubocop to all files
|
29
|
+
|
30
|
+
== [0.0.2] - 2020-05-18
|
31
|
+
=== Bugfix
|
32
|
+
- Added the possibility to require the Gem instead of the single lib files.
|
33
|
+
|
34
|
+
== [0.0.1] - 2020-05-18
|
35
|
+
=== Added
|
36
|
+
- Initial Gem version extracted from the Fastlane Backend.
|
37
|
+
|
38
|
+
The format is based on https://keepachangelog.com[Keep a Changelog],
|
39
|
+
and this project adheres to https://semver.org[Semantic Versioning].
|
data/README.adoc
ADDED
@@ -0,0 +1,46 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module TeamFastlane
|
4
|
+
# This is the base for all domain-driven design entities.
|
5
|
+
# A entity represents a unique object of a specific type in the domain, e.g. a customer. Entities won't be defined by
|
6
|
+
# their attributes but their unique identity.
|
7
|
+
#
|
8
|
+
# Entities are used most of the times to implement the business logic for a given domain, they don't know anything
|
9
|
+
# about outside systems (like persistence layer) and can only work with their attributes and the given parameters of
|
10
|
+
# the called method.
|
11
|
+
#
|
12
|
+
# To make use of this include it in your entity.
|
13
|
+
#
|
14
|
+
# @example How to include properly
|
15
|
+
# class TestEntity
|
16
|
+
# include DomainDrivenDesign::EntityBase
|
17
|
+
# end
|
18
|
+
#
|
19
|
+
# @ddd_base
|
20
|
+
# @author Robert Kranz
|
21
|
+
module DomainDrivenDesign
|
22
|
+
module EntityBase
|
23
|
+
extend ActiveSupport::Concern
|
24
|
+
include ActiveModel::Model
|
25
|
+
include Comparable
|
26
|
+
|
27
|
+
def <=>(other)
|
28
|
+
return id <=> other.id if respond_to?(:id)
|
29
|
+
|
30
|
+
attributes <=> other.attributes
|
31
|
+
end
|
32
|
+
|
33
|
+
def attributes
|
34
|
+
instance_values.transform_values do |value|
|
35
|
+
value.respond_to?(:attributes) ? value.attributes : value
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
class_methods do
|
40
|
+
def repository
|
41
|
+
@repository ||= "#{name}Repository".constantize
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
@@ -0,0 +1,128 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module TeamFastlane
|
4
|
+
# This is the base for all domain-driven design repositories.
|
5
|
+
# A repository bridges the gap between business ({EntityBase}) and persistence layer (database). It encapsulates
|
6
|
+
# storage, retrieval and search behavior for an amount of business objects.
|
7
|
+
#
|
8
|
+
# It achieves this by providing methods for object handling on the one hand and besides that also provides the mapping
|
9
|
+
# from the data structure to the business objects.
|
10
|
+
#
|
11
|
+
# This is not the right place to implement specific sql finder or similar, use the actual ActiveRecord model for this.
|
12
|
+
# Methods in here lean more to complex joins and chaining model methods together to retrieve or store its business
|
13
|
+
# objects.
|
14
|
+
#
|
15
|
+
# This is also not the place to define business logic, see {EntityBase} for this.
|
16
|
+
#
|
17
|
+
# To make use of this extend your repository with it.
|
18
|
+
#
|
19
|
+
# @example How to extend properly
|
20
|
+
# module TestRepository
|
21
|
+
# extend DomainDrivenDesign::RepositoryBase
|
22
|
+
# end
|
23
|
+
#
|
24
|
+
# @ddd_base
|
25
|
+
# @author Robert Kranz
|
26
|
+
module DomainDrivenDesign
|
27
|
+
module RepositoryBase
|
28
|
+
# Constructs an entity from the given data. The given data could either be an ActiveRecord model, or another data
|
29
|
+
# container class. Please be careful to adjust your mapping accordingly if you change the type of the data.
|
30
|
+
def build_entity(data)
|
31
|
+
entity.new map_arguments(entity_mapping, data)
|
32
|
+
end
|
33
|
+
|
34
|
+
# Represents the managed entity class, will be retrieved by reflecting over the repository name.
|
35
|
+
# For example consider this repository.
|
36
|
+
#
|
37
|
+
# module TestFeature
|
38
|
+
# module TestRepository
|
39
|
+
# extend DomainDrivenDesign::RepositoryBase
|
40
|
+
# end
|
41
|
+
# end
|
42
|
+
#
|
43
|
+
# Calling the entity method (with send cause it's private) we receive the Test entity.
|
44
|
+
# TestFeature::TestRepository.send :entity #=> TestFeature::Test
|
45
|
+
#
|
46
|
+
# It's possible to set this to something else instead, but it's highly discouraged.
|
47
|
+
def entity
|
48
|
+
@entity ||= name.gsub('Repository', '').constantize
|
49
|
+
end
|
50
|
+
|
51
|
+
def entity=(class_name)
|
52
|
+
@entity = class_name
|
53
|
+
end
|
54
|
+
|
55
|
+
protected
|
56
|
+
|
57
|
+
# Can be used to explicitly demand, that a finder method should only be called,
|
58
|
+
# if the object requested surely exists.
|
59
|
+
# For example for use cases where something should be done with an existing customer.
|
60
|
+
def ensure_existence(record)
|
61
|
+
raise ActiveRecord::RecordNotFound unless record
|
62
|
+
|
63
|
+
record
|
64
|
+
end
|
65
|
+
|
66
|
+
# This can be used to set the mapping for the {#build_entity} method or to retrieve it.
|
67
|
+
# @example Only data methods
|
68
|
+
# module TestFeature
|
69
|
+
# module TestRepository
|
70
|
+
# extend DomainDrivenDesign::RepositoryBase
|
71
|
+
#
|
72
|
+
# entity_mapping id: id,
|
73
|
+
# name: :firstname
|
74
|
+
# end
|
75
|
+
# end
|
76
|
+
#
|
77
|
+
# @example With lambdas
|
78
|
+
# module TestFeature
|
79
|
+
# module TestRepository
|
80
|
+
# extend DomainDrivenDesign::RepositoryBase
|
81
|
+
#
|
82
|
+
# entity_mapping id: id,
|
83
|
+
# name: ->(data) { data.firstname + ' ' + data.lastname }
|
84
|
+
# end
|
85
|
+
# end
|
86
|
+
#
|
87
|
+
# @see #mapping_function
|
88
|
+
# @see #map_to_entity
|
89
|
+
#
|
90
|
+
# @overload entity_mapping(entity_mapping)
|
91
|
+
# Sets a value on key
|
92
|
+
# @param entity_mapping [Hash] mapping from entity attributes to data methods or callables
|
93
|
+
# @return [Hash]
|
94
|
+
# @overload entity_mapping
|
95
|
+
# Gets the entity mapping
|
96
|
+
# @return [Hash]
|
97
|
+
def entity_mapping(entity_mapping = nil)
|
98
|
+
return @entity_mapping unless entity_mapping
|
99
|
+
|
100
|
+
@entity_mapping = entity_mapping
|
101
|
+
end
|
102
|
+
|
103
|
+
# simple mapping helper which wraps a call to the given method name in a lambda
|
104
|
+
def mapping_function(sym)
|
105
|
+
->(data) { send sym, data }
|
106
|
+
end
|
107
|
+
|
108
|
+
# simple mapping helper which wraps a call to the given entity repository in a lambda
|
109
|
+
def map_to_entity(entity, rule)
|
110
|
+
->(data) { entity.repository.build_entity retrieve_value(rule, data) }
|
111
|
+
end
|
112
|
+
|
113
|
+
private
|
114
|
+
|
115
|
+
def map_arguments(mapping, data_object)
|
116
|
+
mapping.transform_values { |rule| retrieve_value(rule, data_object) }
|
117
|
+
end
|
118
|
+
|
119
|
+
def retrieve_value(rule, data)
|
120
|
+
if rule.is_a? Symbol
|
121
|
+
data.method(rule).call
|
122
|
+
elsif rule.respond_to? :call
|
123
|
+
rule.call data
|
124
|
+
end
|
125
|
+
end
|
126
|
+
end
|
127
|
+
end
|
128
|
+
end
|
@@ -0,0 +1,10 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'team_fastlane/domain_driven_design/entity_base'
|
4
|
+
require 'team_fastlane/domain_driven_design/repository_base'
|
5
|
+
require 'team_fastlane/domain_driven_design/version'
|
6
|
+
|
7
|
+
module TeamFastlane
|
8
|
+
module DomainDrivenDesign
|
9
|
+
end
|
10
|
+
end
|
metadata
ADDED
@@ -0,0 +1,51 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: team_fastlane-domain_driven_design
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 1.0.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Team Fastlane
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2023-08-02 00:00:00.000000000 Z
|
12
|
+
dependencies: []
|
13
|
+
description:
|
14
|
+
email:
|
15
|
+
executables: []
|
16
|
+
extensions: []
|
17
|
+
extra_rdoc_files:
|
18
|
+
- README.adoc
|
19
|
+
- CHANGELOG.adoc
|
20
|
+
files:
|
21
|
+
- CHANGELOG.adoc
|
22
|
+
- README.adoc
|
23
|
+
- lib/team_fastlane/domain_driven_design.rb
|
24
|
+
- lib/team_fastlane/domain_driven_design/entity_base.rb
|
25
|
+
- lib/team_fastlane/domain_driven_design/repository_base.rb
|
26
|
+
- lib/team_fastlane/domain_driven_design/version.rb
|
27
|
+
homepage:
|
28
|
+
licenses:
|
29
|
+
- MIT
|
30
|
+
metadata:
|
31
|
+
rubygems_mfa_required: 'true'
|
32
|
+
post_install_message:
|
33
|
+
rdoc_options: []
|
34
|
+
require_paths:
|
35
|
+
- lib
|
36
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - ">="
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '2.7'
|
41
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
42
|
+
requirements:
|
43
|
+
- - ">="
|
44
|
+
- !ruby/object:Gem::Version
|
45
|
+
version: '0'
|
46
|
+
requirements: []
|
47
|
+
rubygems_version: 3.4.10
|
48
|
+
signing_key:
|
49
|
+
specification_version: 4
|
50
|
+
summary: Gem for an internal project
|
51
|
+
test_files: []
|