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 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,7 @@
1
+ = Domain Driven Design Helper
2
+
3
+ This are some small helpers to use with a domain driven design style. Check out the code comments, these are pretty extensive.
4
+
5
+ == Installation & Usage
6
+
7
+ As described by the link:../README.adoc[main readme].
@@ -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,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ module TeamFastlane
4
+ module DomainDrivenDesign
5
+ VERSION = '1.0.0'
6
+ end
7
+ 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: []