foobara 0.6.2 → 0.6.3

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.
Files changed (40) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +6 -0
  3. data/README.md +6 -3
  4. data/projects/command/lib/foobara/command.rb +2 -0
  5. data/projects/command/src/command_pattern_implementation/concerns/callbacks.rb +6 -4
  6. data/projects/command/src/command_pattern_implementation/concerns/command_data.rb +1 -2
  7. data/projects/command/src/command_pattern_implementation/concerns/runtime.rb +15 -20
  8. data/projects/command/src/extensions/domain/domain_module_extension_extension.rb +0 -2
  9. data/projects/command/src/state_machine.rb +3 -15
  10. data/projects/command_connectors/src/authenticator_selector.rb +0 -8
  11. data/projects/command_connectors/src/command_connector/request.rb +0 -32
  12. data/projects/command_connectors/src/command_registry/exposed_command.rb +1 -53
  13. data/projects/command_connectors/src/serializers/json_serializer.rb +1 -1
  14. data/projects/entities/projects/detached_entity/src/extensions/type_declarations/handlers/registered_type_declaration/validate_primary_key_present.rb +1 -1
  15. data/projects/entities/projects/entity/src/new_prepend.rb +2 -4
  16. data/projects/entities/projects/model_attribute_helpers/lib/foobara/model_attribute_helpers.rb +0 -4
  17. data/projects/entities/projects/persistence/src/entity_base/transaction_table.rb +1 -2
  18. data/projects/entities_plumbing/lib/foobara/entities_plumbing.rb +60 -5
  19. data/projects/entities_plumbing/src/extensions/command_connector/authenticator_selector.rb +13 -0
  20. data/projects/entities_plumbing/src/extensions/command_connector/request.rb +37 -0
  21. data/projects/entities_plumbing/src/extensions/command_pattern_implementation/concerns/transactional_runtime.rb +29 -0
  22. data/projects/entities_plumbing/src/extensions/command_registry/exposed_command_entities.rb +71 -0
  23. data/projects/{command_connectors → entities_plumbing}/src/serializers/entities_to_primary_keys_serializer.rb +0 -2
  24. data/projects/{command_connectors → entities_plumbing}/src/serializers/record_store_serializer.rb +0 -2
  25. data/projects/{command_connectors → entities_plumbing}/src/transformers/entity_to_primary_key_inputs_transformer.rb +1 -1
  26. data/projects/typesystem/projects/builtin_types/src/datetime/casters/hash.rb +2 -1
  27. data/projects/typesystem/projects/project/src/foobara.rb +2 -2
  28. data/projects/typesystem/projects/project/src/project.rb +8 -5
  29. data/projects/typesystem/projects/state_machine/src/callbacks.rb +4 -0
  30. data/projects/typesystem/projects/state_machine/src/state_machine.rb +0 -2
  31. data/projects/typesystem/projects/types/src/type.rb +1 -1
  32. data/version.rb +1 -1
  33. metadata +15 -11
  34. /data/projects/{command_connectors → entities_plumbing}/src/serializers/aggregate_serializer.rb +0 -0
  35. /data/projects/{command_connectors → entities_plumbing}/src/serializers/atomic_serializer.rb +0 -0
  36. /data/projects/{command_connectors → entities_plumbing}/src/transformers/load_aggregates_pre_commit_transformer.rb +0 -0
  37. /data/projects/{command_connectors → entities_plumbing}/src/transformers/load_aggregates_transformer.rb +0 -0
  38. /data/projects/{command_connectors → entities_plumbing}/src/transformers/load_atoms_pre_commit_transformer.rb +0 -0
  39. /data/projects/{command_connectors → entities_plumbing}/src/transformers/load_atoms_transformer.rb +0 -0
  40. /data/projects/{command_connectors → entities_plumbing}/src/transformers/load_delegated_attributes_entities_pre_commit_transformer.rb +0 -0
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 82cde9f69a93f602dfc7c64ae307642920cd755c0406a549e7247e47992982a4
4
- data.tar.gz: dd875dcf264ab47d1bc4af1ae08cd391e2bac8771fde7681f213402c3a8ad269
3
+ metadata.gz: 936be6174137c2740ff9ba0bf5470251901aa9dc61bd841baf4af7dc0041e899
4
+ data.tar.gz: fc49e694263c62adefef802dfa8e469aff130237ec815602cab0aaa92983a132
5
5
  SHA512:
6
- metadata.gz: b37ae22e17b00b133153a71924c1657b0d64f37c141a48ea0d05309f8316a6afe5387627052d83dadc2b58c09b1906190b4633921615420a26c449d3e660c75c
7
- data.tar.gz: 5887b2e59372917e3b2535dd1b918cedf49c5fd7011e241036ace90b0a45478753d394f93f4f5d473079443ad3092ee4bf3865d42a0dadda66fbadf3e68065d6
6
+ metadata.gz: bacfb096227c140aace0cd32ed77b1f436872936b07a346a2fac976b83b478a4d9babcb217454874e39c3c944cb664562edf777d863856f8e510bfbccea1105a
7
+ data.tar.gz: 63d4cf117cadd2f5e6d9f5a8e220f28e1f726c5781578097899d9a7cda2f2727036d7354338bef46465452c44d36e4c0ddd878ec9c89a6ec976316240c2a452f
data/CHANGELOG.md CHANGED
@@ -1,3 +1,9 @@
1
+ # [0.6.3] - 2026-09-11
2
+
3
+ - Eliminate usage of removed JSON.fast_generate
4
+ - A lot of persistence stuff relocated into entities_plumbing project
5
+ - Allow :datetime to handle fractional seconds
6
+
1
7
  # [0.6.2] - 2026-08-24
2
8
 
3
9
  - Eliminate all direct uses of Foobara.manifest in the test suite and deprecate it
data/README.md CHANGED
@@ -1385,12 +1385,15 @@ And we can see the error in the command's list of possible errors:
1385
1385
  ```
1386
1386
 
1387
1387
  And of course, as expected, tooling has access to information about this error and the command's possible error through manifest
1388
- metadata:
1388
+ metadata. Let's take a look at how it surfaces through a generic command connector:
1389
1389
 
1390
1390
  ```
1391
- > Foobara.manifest[:command][:Divide][:possible_errors]["data.divisor.divide_by_zero"][:error]
1391
+ > require "foobara/command_connectors"
1392
+ > connector = Foobara::CommandConnector.new
1393
+ > connector.connect(Divide)
1394
+ > connector.foobara_manifest[:command][:Divide][:possible_errors]["data.divisor.divide_by_zero"][:error]
1392
1395
  ==> "Divide::DivideByZeroError"
1393
- > Foobara.manifest[:error][:"Divide::DivideByZeroError"][:parent]
1396
+ > connector.foobara_manifest[:error][:"Divide::DivideByZeroError"][:parent]
1394
1397
  ==> [:command, "Divide"]
1395
1398
  ```
1396
1399
 
@@ -9,6 +9,8 @@ module Foobara
9
9
  Domain::DomainModuleExtension::ClassMethods.prepend(
10
10
  DomainModuleExtensionExtension::ClassMethods
11
11
  )
12
+
13
+ CommandPatternImplementation.install_state_machine_callback_methods
12
14
  end
13
15
  end
14
16
  end
@@ -31,6 +31,12 @@ module Foobara
31
31
  end
32
32
  end
33
33
 
34
+ def state_machine_callback_registry = state_machine.callback_registry
35
+ end
36
+ end
37
+
38
+ class << self
39
+ def install_state_machine_callback_methods
34
40
  [self, ClassMethods].each do |target|
35
41
  [:before, :after].each do |type|
36
42
  target.define_method "#{type}_any_transition" do |&block|
@@ -84,10 +90,6 @@ module Foobara
84
90
  end
85
91
  end
86
92
  end
87
-
88
- def state_machine_callback_registry
89
- state_machine.callback_registry
90
- end
91
93
  end
92
94
  end
93
95
  end
@@ -21,7 +21,7 @@ module Foobara
21
21
  @is_query = true
22
22
  end
23
23
 
24
- # rubocop:disable Naming/MemoizedInstanceVariableName
24
+ # rubocop:disable-next Naming/MemoizedInstanceVariableName
25
25
  def query?
26
26
  return @is_query if defined?(@is_query)
27
27
 
@@ -29,7 +29,6 @@ module Foobara
29
29
  superclass.query?
30
30
  end
31
31
  end
32
- # rubocop:enable Naming/MemoizedInstanceVariableName
33
32
  end
34
33
  end
35
34
  end
@@ -26,24 +26,11 @@ module Foobara
26
26
 
27
27
  def run
28
28
  Foobara::Namespace.use self.class do
29
- invoke_with_callbacks_and_transition(:open_transaction)
30
-
31
- invoke_with_callbacks_and_transition_in_transaction([
32
- :cast_and_validate_inputs,
33
- :load_records,
34
- :validate_records,
35
- :validate,
36
- :run_execute,
37
- :commit_transaction
38
- ])
39
-
40
- invoke_with_callbacks_and_transition(:succeed)
29
+ _run_all_steps
41
30
  end
42
31
 
43
32
  @outcome
44
33
  rescue Halt
45
- rollback_transaction
46
-
47
34
  return outcome if state_machine.currently_errored?
48
35
 
49
36
  if error_collection.empty?
@@ -73,6 +60,20 @@ module Foobara
73
60
 
74
61
  private
75
62
 
63
+ def _run_all_steps
64
+ # TODO: start moving tests that depend on entities_plumbing into entities_plumbing
65
+ # so that we can hit this code path naturally by not requiring entities_plumbing
66
+ # in this project
67
+ # simplecov:disable
68
+ invoke_with_callbacks_and_transition([
69
+ :cast_and_validate_inputs,
70
+ :validate,
71
+ :run_execute,
72
+ :succeed
73
+ ])
74
+ # simplecov:enable
75
+ end
76
+
76
77
  def run_execute
77
78
  self.raw_result = execute
78
79
  result = process_result_using_result_type(raw_result)
@@ -90,12 +91,6 @@ module Foobara
90
91
  # can override if desired, default is a no-op
91
92
  end
92
93
 
93
- def invoke_with_callbacks_and_transition_in_transaction(transition_or_transitions)
94
- Persistence::EntityBase.using_transactions(transactions) do
95
- invoke_with_callbacks_and_transition(transition_or_transitions)
96
- end
97
- end
98
-
99
94
  def invoke_with_callbacks_and_transition(transition_or_transitions)
100
95
  result = nil
101
96
 
@@ -1,4 +1,3 @@
1
- # rubocop:disable Naming/FileName
2
1
  module Foobara
3
2
  class Command
4
3
  module DomainModuleExtensionExtension
@@ -19,4 +18,3 @@ module Foobara
19
18
  end
20
19
  end
21
20
  end
22
- # rubocop:enable Naming/FileName
@@ -2,13 +2,9 @@ module Foobara
2
2
  class Command
3
3
  class StateMachine < Foobara::StateMachine
4
4
  transitions = [
5
- :open_transaction,
6
5
  :cast_and_validate_inputs,
7
- :load_records,
8
- :validate_records,
9
6
  :validate,
10
7
  :run_execute,
11
- :commit_transaction,
12
8
  :succeed,
13
9
  :error,
14
10
  :fail,
@@ -19,26 +15,18 @@ module Foobara
19
15
 
20
16
  states = [
21
17
  :initialized,
22
- :transaction_opened,
23
18
  :inputs_casted_and_validated,
24
- :loaded_records,
25
- :validated_records,
26
19
  :validated_execution,
27
20
  :executing,
28
- :transaction_committed
29
21
  ] + terminal_states
30
22
 
31
23
  can_fail_states = states - terminal_states
32
24
 
33
25
  transition_map = {
34
- initialized: { open_transaction: :transaction_opened },
35
- transaction_opened: { cast_and_validate_inputs: :inputs_casted_and_validated },
36
- inputs_casted_and_validated: { load_records: :loaded_records },
37
- loaded_records: { validate_records: :validated_records },
38
- validated_records: { validate: :validated_execution },
26
+ initialized: { cast_and_validate_inputs: :inputs_casted_and_validated },
27
+ inputs_casted_and_validated: { validate: :validated_execution },
39
28
  validated_execution: { run_execute: :executing },
40
- executing: { commit_transaction: :transaction_committed },
41
- transaction_committed: { succeed: :succeeded },
29
+ executing: { succeed: :succeeded },
42
30
  terminal_states => { reset: :initialized },
43
31
  can_fail_states => {
44
32
  error: :errored,
@@ -24,14 +24,6 @@ module Foobara
24
24
  def authenticate(request)
25
25
  selector.process_value!(request)
26
26
  end
27
-
28
- def relevant_entity_classes(request)
29
- outcome = selector.processor_for(request)
30
-
31
- if outcome.success?
32
- outcome.result&.relevant_entity_classes(request)
33
- end
34
- end
35
27
  end
36
28
  end
37
29
  end
@@ -2,7 +2,6 @@ module Foobara
2
2
  class CommandConnector
3
3
  class Request
4
4
  include TruncatedInspect
5
- include NestedTransactionable
6
5
 
7
6
  # TODO: this feels like a smell of some sort...
8
7
  attr_accessor :command,
@@ -163,39 +162,8 @@ module Foobara
163
162
  outcome.error_collection
164
163
  end
165
164
 
166
- # TODO: move this to entity_plumbing
167
- def relevant_entity_classes
168
- if command_class.is_a?(::Class) && command_class < TransformedCommand
169
- if authenticator.respond_to?(:relevant_entity_classes)
170
- entity_classes = authenticator.relevant_entity_classes(self)
171
- [*entity_classes, *relevant_entity_classes_from_inputs_transformer]
172
- else
173
- relevant_entity_classes_from_inputs_transformer
174
- end
175
- end || EMPTY_ARRAY
176
- end
177
-
178
165
  private
179
166
 
180
- def relevant_entity_classes_from_inputs_transformer(
181
- object = [*command_class.inputs_transformer, *command_class.result_transformer]
182
- )
183
- case object
184
- when TypeDeclarations::TypedTransformer
185
- relevant_entity_classes_from_inputs_transformer([*object.from_type, *object.to_type])
186
- when Types::Type
187
- relevant_entity_classes_for_type(object)
188
- when ::Array
189
- object.map do |o|
190
- relevant_entity_classes_from_inputs_transformer(o)
191
- end.flatten
192
- when Value::Processor::Pipeline
193
- relevant_entity_classes_from_inputs_transformer(object.processors)
194
- else
195
- []
196
- end
197
- end
198
-
199
167
  def objects_to_serializers(objects)
200
168
  objects.map do |object|
201
169
  case object
@@ -35,9 +35,7 @@ module Foobara
35
35
  allowed_rule: nil,
36
36
  requires_authentication: nil,
37
37
  authentication_optional: nil,
38
- authenticator: nil,
39
- aggregate_entities: nil,
40
- atomic_entities: nil
38
+ authenticator: nil
41
39
  )
42
40
  if allowed_rule && authenticator && requires_authentication.nil?
43
41
  requires_authentication = true
@@ -57,42 +55,6 @@ module Foobara
57
55
  command_class.scoped_path
58
56
  end
59
57
 
60
- if aggregate_entities
61
- pre_commit_transformers = [
62
- *pre_commit_transformers,
63
- CommandConnectors::Transformers::LoadAggregatesPreCommitTransformer
64
- ]
65
-
66
- pre_commit_transformers.uniq!
67
- pre_commit_transformers.delete(CommandConnectors::Transformers::LoadAtomsPreCommitTransformer)
68
-
69
- serializers = [*serializers, CommandConnectors::Serializers::AggregateSerializer]
70
-
71
- serializers.uniq!
72
- serializers.delete(Foobara::CommandConnectors::Serializers::AtomicSerializer)
73
- # TODO: either both should have special behavior for false or neither should
74
- elsif aggregate_entities == false
75
- pre_commit_transformers = pre_commit_transformers&.reject do |t|
76
- t == Foobara::CommandConnectors::Transformers::LoadAggregatesPreCommitTransformer
77
- end
78
- serializers = serializers&.reject do |s|
79
- s == Foobara::CommandConnectors::Serializers::AggregateSerializer
80
- end
81
- elsif atomic_entities
82
- pre_commit_transformers = [
83
- *pre_commit_transformers,
84
- CommandConnectors::Transformers::LoadAtomsPreCommitTransformer
85
- ]
86
-
87
- pre_commit_transformers.uniq!
88
- pre_commit_transformers.delete(CommandConnectors::Transformers::LoadAggregatesPreCommitTransformer)
89
-
90
- serializers = [*serializers, Foobara::CommandConnectors::Serializers::AtomicSerializer]
91
-
92
- serializers.uniq!
93
- serializers.delete(CommandConnectors::Serializers::AggregateSerializer)
94
- end
95
-
96
58
  self.command_class = command_class
97
59
  self.scoped_path = scoped_path
98
60
  self.capture_unknown_error = capture_unknown_error
@@ -108,20 +70,6 @@ module Foobara
108
70
  self.authentication_optional = authentication_optional
109
71
  self.authenticator = authenticator
110
72
 
111
- # A bit hacky... we should check if we need to shim in a LoadDelegatedAttributesEntitiesPreCommitTransformer
112
- unless aggregate_entities
113
- # It's possible delegates have been added or removed via the result transformers...
114
- # We should figure out a way to check the transformed result type instead.
115
- if _has_delegated_attributes?(command_class.result_type)
116
- self.pre_commit_transformers = [
117
- *self.pre_commit_transformers,
118
- CommandConnectors::Transformers::LoadDelegatedAttributesEntitiesPreCommitTransformer
119
- ]
120
-
121
- pre_commit_transformers.uniq!
122
- end
123
- end
124
-
125
73
  Namespace.on_change(self, :clear_caches)
126
74
  end
127
75
 
@@ -4,7 +4,7 @@ module Foobara
4
4
  # TODO: move this to its own project
5
5
  class JsonSerializer < Serializer
6
6
  def serialize(object)
7
- JSON.fast_generate(object)
7
+ JSON.generate(object)
8
8
  end
9
9
 
10
10
  def deserialize(string)
@@ -22,7 +22,7 @@ module Foobara
22
22
  end
23
23
  end
24
24
 
25
- def error_context(_value) ={}
25
+ def error_context(_value) = {}
26
26
  end
27
27
  end
28
28
  end
@@ -1,21 +1,19 @@
1
1
  module Foobara
2
2
  class Entity < DetachedEntity
3
3
  module NewPrepend
4
- # rubocop:disable Lint/UselessMethodDefinition
4
+ # rubocop:disable-next Lint/UselessMethodDefinition
5
5
  def new(...)
6
6
  super
7
7
  end
8
- # rubocop:enable Lint/UselessMethodDefinition
9
8
 
10
9
  alias __private_new__ new
11
10
 
12
- # rubocop:disable Lint/DuplicateMethods
11
+ # rubocop:disable-next Lint/DuplicateMethods
13
12
  def new(...)
14
13
  # simplecov:disable
15
14
  raise "Cannot initialize a #{name}. Use .create, .thunk, .loaded, or .build instead."
16
15
  # simplecov:enable
17
16
  end
18
- # rubocop:enable Lint/DuplicateMethods
19
17
  end
20
18
  end
21
19
  end
@@ -1,7 +1,3 @@
1
- require "date"
2
- require "time"
3
- require "bigdecimal"
4
-
5
1
  module Foobara
6
2
  module ModelAttributeHelpers
7
3
  class << self
@@ -86,7 +86,7 @@ module Foobara
86
86
  # simplecov:enable
87
87
  end
88
88
 
89
- # rubocop:disable Lint/IdentityComparison
89
+ # rubocop:disable-next Lint/IdentityComparison
90
90
  if entity &&
91
91
  (!entity.equal?(entity_or_record_id) || entity.object_id != entity_or_record_id.object_id)
92
92
  # simplecov:disable
@@ -94,7 +94,6 @@ module Foobara
94
94
  "Try passing in the primary key instead of constructing an unloaded entity to pass in."
95
95
  # simplecov:enable
96
96
  end
97
- # rubocop:enable Lint/IdentityComparison
98
97
 
99
98
  record_id = entity.primary_key
100
99
  else
@@ -7,29 +7,84 @@ module Foobara
7
7
  CommandPatternImplementation.include CommandPatternImplementation::Concerns::EntityInputs
8
8
  CommandPatternImplementation.include CommandPatternImplementation::Concerns::EntityErrorsType
9
9
  CommandPatternImplementation.include CommandPatternImplementation::Concerns::EntityReflection
10
+ CommandPatternImplementation.include CommandPatternImplementation::Concerns::TransactionalRuntime
10
11
 
11
12
  if Foobara.project_installed?("command_connectors")
12
13
  # simplecov:disable
13
- install_command_connector_extension
14
+ install_command_connector_extensions
14
15
  # simplecov:enable
15
16
  end
16
17
  end
17
18
 
18
19
  def new_project_added(new_project)
19
20
  if new_project.symbol == "command_connectors"
20
- install_command_connector_extension
21
+ install_command_connector_extensions
21
22
  end
22
23
  end
23
24
 
24
- def install_command_connector_extension
25
+ def add_persistence_states_and_transitions
26
+ original_terminal_states = Command::StateMachine.terminal_states
27
+ original_transition_map = Command::StateMachine.transition_map
28
+
29
+ new_transition_map = {}
30
+
31
+ new_transition_map[:initialized] = { open_transaction: :transaction_opened }
32
+ new_transition_map[:transaction_opened] = { cast_and_validate_inputs: :inputs_casted_and_validated }
33
+ new_transition_map[:inputs_casted_and_validated] = { load_records: :loaded_records }
34
+ new_transition_map[:loaded_records] = { validate_records: :validated_records }
35
+ new_transition_map[:validated_records] = { validate: :validated_execution }
36
+ new_transition_map[:validated_execution] = {
37
+ run_execute: original_transition_map[:validated_execution][:run_execute]
38
+ }
39
+ new_transition_map[:executing] = { commit_transaction: :transaction_committed }
40
+ new_transition_map[:transaction_committed] = { succeed: :succeeded }
41
+
42
+ new_transition_map[new_transition_map.keys] = {
43
+ error: :errored,
44
+ fail: :failed
45
+ }
46
+
47
+ [:succeeded, :errored, :failed].each do |state|
48
+ new_transition_map[state] = original_transition_map[state]
49
+ end
50
+
51
+ Command::StateMachine.remove_all_callbacks
52
+ Command::StateMachine.allow_recreating_callback_methods
53
+
54
+ Command::StateMachine.set_transition_map(
55
+ new_transition_map,
56
+ terminal_states: original_terminal_states
57
+ )
58
+ end
59
+
60
+ def install_command_connector_extensions
25
61
  CommandConnector.singleton_class.prepend(
26
62
  Foobara::EntitiesPlumbing::CommandConnectorsExtension::ClassMethods
27
63
  )
28
64
 
29
65
  CommandConnector::Authenticator.include CommandConnector::AuthenticatorMethods
66
+ CommandConnector::Request.include NestedTransactionable
67
+ CommandRegistry::ExposedCommand.prepend CommandRegistry::ExposedCommandEntities
68
+
69
+ project_path = "#{__dir__}/../.."
70
+
71
+ Util.require_directory("#{project_path}/src/extensions/command_connector")
72
+ Util.require_directory("#{project_path}/src/serializers")
73
+ Util.require_directory("#{project_path}/src/transformers")
30
74
  end
31
75
  end
76
+
77
+ add_persistence_states_and_transitions
32
78
  end
33
- end
34
79
 
35
- Foobara.project("entities_plumbing", project_path: "#{__dir__}/../..")
80
+ project_path = "#{__dir__}/../.."
81
+
82
+ Foobara.project("entities_plumbing",
83
+ project_path:,
84
+ eager_load_src: false)
85
+
86
+ Util.require_directory("#{project_path}/src/extensions/command_pattern_implementation")
87
+ Util.require_directory("#{project_path}/src/extensions/command_registry")
88
+ Util.require_pattern("#{project_path}/src/extensions/authenticator_methods.rb")
89
+ Util.require_pattern("#{project_path}/src/command_connectors_extension.rb")
90
+ end
@@ -0,0 +1,13 @@
1
+ module Foobara
2
+ class CommandConnector
3
+ class AuthenticatorSelector < Authenticator
4
+ def relevant_entity_classes(request)
5
+ outcome = selector.processor_for(request)
6
+
7
+ if outcome.success?
8
+ outcome.result&.relevant_entity_classes(request)
9
+ end
10
+ end
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,37 @@
1
+ module Foobara
2
+ class CommandConnector
3
+ class Request
4
+ def relevant_entity_classes
5
+ if command_class.is_a?(::Class) && command_class < TransformedCommand
6
+ if authenticator.respond_to?(:relevant_entity_classes)
7
+ entity_classes = authenticator.relevant_entity_classes(self)
8
+ [*entity_classes, *relevant_entity_classes_from_inputs_transformer]
9
+ else
10
+ relevant_entity_classes_from_inputs_transformer
11
+ end
12
+ end || EMPTY_ARRAY
13
+ end
14
+
15
+ private
16
+
17
+ def relevant_entity_classes_from_inputs_transformer(
18
+ object = [*command_class.inputs_transformer, *command_class.result_transformer]
19
+ )
20
+ case object
21
+ when TypeDeclarations::TypedTransformer
22
+ relevant_entity_classes_from_inputs_transformer([*object.from_type, *object.to_type])
23
+ when Types::Type
24
+ relevant_entity_classes_for_type(object)
25
+ when ::Array
26
+ object.map do |o|
27
+ relevant_entity_classes_from_inputs_transformer(o)
28
+ end.flatten
29
+ when Value::Processor::Pipeline
30
+ relevant_entity_classes_from_inputs_transformer(object.processors)
31
+ else
32
+ []
33
+ end
34
+ end
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,29 @@
1
+ module Foobara
2
+ module CommandPatternImplementation
3
+ module Concerns
4
+ module TransactionalRuntime
5
+ private
6
+
7
+ def _run_all_steps
8
+ invoke_with_callbacks_and_transition(:open_transaction)
9
+
10
+ Persistence::EntityBase.using_transactions(transactions) do
11
+ invoke_with_callbacks_and_transition([
12
+ :cast_and_validate_inputs,
13
+ :load_records,
14
+ :validate_records,
15
+ :validate,
16
+ :run_execute,
17
+ :commit_transaction
18
+ ])
19
+ end
20
+
21
+ invoke_with_callbacks_and_transition(:succeed)
22
+ rescue
23
+ rollback_transaction
24
+ raise
25
+ end
26
+ end
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,71 @@
1
+ module Foobara
2
+ class CommandRegistry
3
+ module ExposedCommandEntities
4
+ def initialize(
5
+ command_class,
6
+ pre_commit_transformers: nil,
7
+ serializers: nil,
8
+ aggregate_entities: nil,
9
+ atomic_entities: nil,
10
+ **
11
+ )
12
+ if aggregate_entities
13
+ pre_commit_transformers = [
14
+ *pre_commit_transformers,
15
+ CommandConnectors::Transformers::LoadAggregatesPreCommitTransformer
16
+ ]
17
+
18
+ pre_commit_transformers.uniq!
19
+ pre_commit_transformers.delete(CommandConnectors::Transformers::LoadAtomsPreCommitTransformer)
20
+
21
+ serializers = [*serializers, CommandConnectors::Serializers::AggregateSerializer]
22
+
23
+ serializers.uniq!
24
+ serializers.delete(Foobara::CommandConnectors::Serializers::AtomicSerializer)
25
+ # TODO: either both should have special behavior for false or neither should
26
+ elsif aggregate_entities == false
27
+ pre_commit_transformers = pre_commit_transformers&.reject do |t|
28
+ t == Foobara::CommandConnectors::Transformers::LoadAggregatesPreCommitTransformer
29
+ end
30
+ serializers = serializers&.reject do |s|
31
+ s == Foobara::CommandConnectors::Serializers::AggregateSerializer
32
+ end
33
+ elsif atomic_entities
34
+ pre_commit_transformers = [
35
+ *pre_commit_transformers,
36
+ CommandConnectors::Transformers::LoadAtomsPreCommitTransformer
37
+ ]
38
+
39
+ pre_commit_transformers.uniq!
40
+ pre_commit_transformers.delete(CommandConnectors::Transformers::LoadAggregatesPreCommitTransformer)
41
+
42
+ serializers = [*serializers, Foobara::CommandConnectors::Serializers::AtomicSerializer]
43
+
44
+ serializers.uniq!
45
+ serializers.delete(CommandConnectors::Serializers::AggregateSerializer)
46
+ end
47
+
48
+ # A bit hacky... we should check if we need to shim in a LoadDelegatedAttributesEntitiesPreCommitTransformer
49
+ unless aggregate_entities
50
+ # It's possible delegates have been added or removed via the result transformers...
51
+ # We should figure out a way to check the transformed result type instead.
52
+ if _has_delegated_attributes?(command_class.result_type)
53
+ pre_commit_transformers = [
54
+ *pre_commit_transformers,
55
+ CommandConnectors::Transformers::LoadDelegatedAttributesEntitiesPreCommitTransformer
56
+ ]
57
+
58
+ pre_commit_transformers.uniq!
59
+ end
60
+ end
61
+
62
+ super(
63
+ command_class,
64
+ pre_commit_transformers:,
65
+ serializers:,
66
+ **
67
+ )
68
+ end
69
+ end
70
+ end
71
+ end
@@ -1,5 +1,3 @@
1
- require_relative "success_serializer"
2
-
3
1
  module Foobara
4
2
  module CommandConnectors
5
3
  module Serializers
@@ -1,5 +1,3 @@
1
- require_relative "success_serializer"
2
-
3
1
  module Foobara
4
2
  module CommandConnectors
5
3
  module Serializers
@@ -49,7 +49,7 @@ module Foobara
49
49
  declaration = to_type.target_class.primary_key_type.reference_or_declaration_data
50
50
 
51
51
  if declaration.is_a?(::Symbol)
52
- declaration = { type: declaration }
52
+ declaration = { type: declaration }
53
53
  end
54
54
 
55
55
  description = "#{to_type.target_class.model_name} #{to_type.target_class.primary_key_attribute}"
@@ -43,7 +43,8 @@ module Foobara
43
43
  day: { type: :integer, min: 1, max: 31 },
44
44
  hours: { type: :integer, min: 0, max: 23, required: false, default: 0 },
45
45
  minutes: { type: :integer, min: 0, max: 59, required: false, default: 0 },
46
- seconds: { type: :big_decimal, min: 0, max: 59, required: false, default: 0 },
46
+ # TODO: add a :rational foobara type
47
+ seconds: { type: :duck, required: false, default: 0 },
47
48
  milliseconds: { type: :integer, min: 0, max: 1000, required: false },
48
49
  zone: { type: :string, required: false }
49
50
  )
@@ -18,14 +18,14 @@ module Foobara
18
18
  @all_projects ||= {}
19
19
  end
20
20
 
21
- def project(symbol, project_path: nil)
21
+ def project(symbol, project_path: nil, eager_load_src: true)
22
22
  if all_projects.key?(symbol)
23
23
  # simplecov:disable
24
24
  raise ArgumentError, "Project #{symbol} already loaded"
25
25
  # simplecov:enable
26
26
  end
27
27
 
28
- project = Project.new(symbol, project_path:)
28
+ project = Project.new(symbol, project_path:, eager_load_src:)
29
29
  project.load
30
30
 
31
31
  all_projects[symbol] = project
@@ -1,8 +1,9 @@
1
1
  module Foobara
2
2
  class Project
3
- attr_accessor :symbol, :project_path
3
+ attr_accessor :symbol, :project_path, :eager_load_src
4
4
 
5
- def initialize(symbol, project_path: nil)
5
+ def initialize(symbol, project_path: nil, eager_load_src: true)
6
+ self.eager_load_src = eager_load_src
6
7
  self.symbol = symbol
7
8
  self.project_path = project_path || "#{__dir__}/../../#{symbol}"
8
9
  end
@@ -22,10 +23,12 @@ module Foobara
22
23
  def load
23
24
  require require_path
24
25
 
25
- src_dir = "#{project_path}/src"
26
+ if eager_load_src
27
+ src_dir = "#{project_path}/src"
26
28
 
27
- if Dir.exist?(src_dir)
28
- Util.require_directory(src_dir)
29
+ if Dir.exist?(src_dir)
30
+ Util.require_directory(src_dir)
31
+ end
29
32
  end
30
33
  end
31
34
 
@@ -70,6 +70,10 @@ module Foobara
70
70
 
71
71
  attr_reader :register_callback_methods
72
72
 
73
+ def allow_recreating_callback_methods
74
+ @register_callback_methods = nil
75
+ end
76
+
73
77
  # 0 before_any_transition
74
78
  # 1 before_transition_to_<state>
75
79
  # 2 before_transition_from_<state>
@@ -4,8 +4,6 @@ module Foobara
4
4
  require_relative "validations"
5
5
  require_relative "transitions"
6
6
 
7
- # TODO: allow quick creation of a statemachine either through better options to #initialize or a
8
- # .for method.
9
7
  class StateMachine
10
8
  include Sugar
11
9
  include Callbacks
@@ -448,7 +448,7 @@ module Foobara
448
448
  if data.key?(:defaults)
449
449
  defaults = data[:defaults]
450
450
 
451
- if defaults.is_a?(::Hash) && defaults.values.any? { it.is_a?(Proc) }
451
+ if defaults.is_a?(::Hash) && defaults.values.any?(Proc)
452
452
  cleaned_defaults = defaults.transform_values do |value|
453
453
  if value.is_a?(Proc)
454
454
  "[<Lazily Set>]"
data/version.rb CHANGED
@@ -1,6 +1,6 @@
1
1
  module Foobara
2
2
  module Version
3
- VERSION = "0.6.2".freeze
3
+ VERSION = "0.6.3".freeze
4
4
  MINIMUM_RUBY_VERSION = [">= 3.4.0", "< 4.1"].freeze
5
5
  end
6
6
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: foobara
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.6.2
4
+ version: 0.6.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Miles Georgi
@@ -143,23 +143,13 @@ files:
143
143
  - projects/command_connectors/src/request_mutator.rb
144
144
  - projects/command_connectors/src/response_mutator.rb
145
145
  - projects/command_connectors/src/serializer.rb
146
- - projects/command_connectors/src/serializers/aggregate_serializer.rb
147
- - projects/command_connectors/src/serializers/atomic_serializer.rb
148
- - projects/command_connectors/src/serializers/entities_to_primary_keys_serializer.rb
149
146
  - projects/command_connectors/src/serializers/errors_serializer.rb
150
147
  - projects/command_connectors/src/serializers/json_serializer.rb
151
148
  - projects/command_connectors/src/serializers/noop_serializer.rb
152
- - projects/command_connectors/src/serializers/record_store_serializer.rb
153
149
  - projects/command_connectors/src/serializers/success_serializer.rb
154
150
  - projects/command_connectors/src/serializers/yaml_serializer.rb
155
151
  - projects/command_connectors/src/transformed_command.rb
156
152
  - projects/command_connectors/src/transformers/auth_errors_transformer.rb
157
- - projects/command_connectors/src/transformers/entity_to_primary_key_inputs_transformer.rb
158
- - projects/command_connectors/src/transformers/load_aggregates_pre_commit_transformer.rb
159
- - projects/command_connectors/src/transformers/load_aggregates_transformer.rb
160
- - projects/command_connectors/src/transformers/load_atoms_pre_commit_transformer.rb
161
- - projects/command_connectors/src/transformers/load_atoms_transformer.rb
162
- - projects/command_connectors/src/transformers/load_delegated_attributes_entities_pre_commit_transformer.rb
163
153
  - projects/domain_mapper/lib/foobara/domain_mapper.rb
164
154
  - projects/domain_mapper/src/domain_mapper.rb
165
155
  - projects/domain_mapper/src/domain_mapper_lookups.rb
@@ -250,12 +240,26 @@ files:
250
240
  - projects/entities_plumbing/lib/foobara/entities_plumbing.rb
251
241
  - projects/entities_plumbing/src/command_connectors_extension.rb
252
242
  - projects/entities_plumbing/src/extensions/authenticator_methods.rb
243
+ - projects/entities_plumbing/src/extensions/command_connector/authenticator_selector.rb
244
+ - projects/entities_plumbing/src/extensions/command_connector/request.rb
253
245
  - projects/entities_plumbing/src/extensions/command_pattern_implementation/concerns/entities.rb
254
246
  - projects/entities_plumbing/src/extensions/command_pattern_implementation/concerns/entity_errors_type.rb
255
247
  - projects/entities_plumbing/src/extensions/command_pattern_implementation/concerns/entity_inputs.rb
256
248
  - projects/entities_plumbing/src/extensions/command_pattern_implementation/concerns/entity_reflection.rb
257
249
  - projects/entities_plumbing/src/extensions/command_pattern_implementation/concerns/runtime.rb
250
+ - projects/entities_plumbing/src/extensions/command_pattern_implementation/concerns/transactional_runtime.rb
258
251
  - projects/entities_plumbing/src/extensions/command_pattern_implementation/concerns/transactions.rb
252
+ - projects/entities_plumbing/src/extensions/command_registry/exposed_command_entities.rb
253
+ - projects/entities_plumbing/src/serializers/aggregate_serializer.rb
254
+ - projects/entities_plumbing/src/serializers/atomic_serializer.rb
255
+ - projects/entities_plumbing/src/serializers/entities_to_primary_keys_serializer.rb
256
+ - projects/entities_plumbing/src/serializers/record_store_serializer.rb
257
+ - projects/entities_plumbing/src/transformers/entity_to_primary_key_inputs_transformer.rb
258
+ - projects/entities_plumbing/src/transformers/load_aggregates_pre_commit_transformer.rb
259
+ - projects/entities_plumbing/src/transformers/load_aggregates_transformer.rb
260
+ - projects/entities_plumbing/src/transformers/load_atoms_pre_commit_transformer.rb
261
+ - projects/entities_plumbing/src/transformers/load_atoms_transformer.rb
262
+ - projects/entities_plumbing/src/transformers/load_delegated_attributes_entities_pre_commit_transformer.rb
259
263
  - projects/manifest/lib/foobara/manifest.rb
260
264
  - projects/manifest/src/array.rb
261
265
  - projects/manifest/src/attributes.rb