foobara 0.0.135 → 0.0.137

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 (43) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +16 -0
  3. data/projects/builtin_types/lib/foobara/builtin_types.rb +1 -0
  4. data/projects/callback/src/registry/chained_conditioned.rb +1 -3
  5. data/projects/callback/src/registry/joined_conditioned.rb +28 -0
  6. data/projects/command/lib/foobara/command.rb +1 -0
  7. data/projects/command/src/command_pattern_implementation/concerns/callbacks.rb +63 -46
  8. data/projects/command/src/command_pattern_implementation/concerns/reflection.rb +1 -0
  9. data/projects/command/src/command_pattern_implementation/concerns/state_machine.rb +10 -1
  10. data/projects/command_connectors/lib/foobara/command_connectors.rb +1 -0
  11. data/projects/command_connectors/src/serializers/errors_serializer.rb +1 -2
  12. data/projects/command_connectors/src/transformed_command.rb +0 -2
  13. data/projects/command_connectors/src/transformers/entity_to_primary_key_inputs_transformer.rb +7 -1
  14. data/projects/command_connectors/src/transformers/load_aggregates_pre_commit_transformer.rb +4 -21
  15. data/projects/command_connectors/src/transformers/load_aggregates_transformer.rb +30 -0
  16. data/projects/command_connectors/src/transformers/load_atoms_pre_commit_transformer.rb +4 -22
  17. data/projects/command_connectors/src/transformers/load_atoms_transformer.rb +31 -0
  18. data/projects/common/src/error.rb +4 -0
  19. data/projects/common/src/error_collection.rb +24 -22
  20. data/projects/common/src/error_key.rb +1 -1
  21. data/projects/common/src/outcome.rb +13 -7
  22. data/projects/detached_entity/lib/foobara/detached_entity.rb +1 -0
  23. data/projects/domain/src/domain_module_extension.rb +0 -1
  24. data/projects/domain/src/organization.rb +0 -1
  25. data/projects/entity/lib/foobara/entity.rb +2 -1
  26. data/projects/entity/src/association_depth.rb +7 -0
  27. data/projects/entity/src/concerns/callbacks.rb +1 -0
  28. data/projects/foobara/src/foobara.rb +9 -0
  29. data/projects/foobara/src/project.rb +1 -0
  30. data/projects/manifest/src/foobara/manifest/possible_error.rb +0 -2
  31. data/projects/model/lib/foobara/model.rb +1 -0
  32. data/projects/model/src/model.rb +1 -4
  33. data/projects/namespace/src/namespace.rb +0 -1
  34. data/projects/namespace/src/namespace_helpers.rb +4 -13
  35. data/projects/persistence/lib/foobara/persistence.rb +1 -0
  36. data/projects/persistence/src/entity_base/transaction/concerns/entity_callback_handling.rb +1 -0
  37. data/projects/persistence/src/entity_base/transaction/concerns/transaction_tracking.rb +1 -0
  38. data/projects/type_declarations/lib/foobara/type_declarations.rb +1 -0
  39. data/projects/type_declarations/src/attributes_transformers/from_yaml.rb +6 -0
  40. data/projects/type_declarations/src/attributes_transformers/only.rb +9 -1
  41. data/projects/type_declarations/src/attributes_transformers/reject.rb +11 -0
  42. data/projects/value/src/processor.rb +1 -1
  43. metadata +7 -3
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 0560b5378293e0abf5477c545b37e05646ffd31e90160e60dd9f9e107e5307f5
4
- data.tar.gz: 1b56363410e7a2af706f001559ee7a43c9ba27683b7a2de163747c8645054e5a
3
+ metadata.gz: 4c5acf1ac653d427d77720c273fa25651b6865482733f8b0a382a6cf5af9a2cd
4
+ data.tar.gz: ea8cf9b48ecc319a63d2d373339b729de4ee28763a85d30a31d8e1faf50faf08
5
5
  SHA512:
6
- metadata.gz: c3af812dd4decf50d37a5080d52299aa6eafe1643846ea92e73fa1acc6bc535f6772e8cb56356fad3065ec3b0dda1ed6be695f0fb826f9fd8cf9956014dd06af
7
- data.tar.gz: 8cafe756d10ed613cdb4da5e521a37f8e1c8cd8c40738744898224ff4cb5aadf244ac92c81f9aa608b1666debcd72a3c2ca6776262f2a4d649524dc2f8f2b4b9
6
+ metadata.gz: ab129e2a8bcaca2e72aa7c1208197586af9563c4540c3ba6b7925e0ae1fafb20a31fa9ea523b4906215b779aab265736b46f3c13ced24a74a63ff6466502ed0e
7
+ data.tar.gz: e2fcb02c9a104085488983a3e4755557696b83a5bd6353ffd35b562132e93a3f58871a175c2e8d126ba119ded2bc5eb36a4a0098fffc979632fc7bef84c08290
data/CHANGELOG.md CHANGED
@@ -1,3 +1,19 @@
1
+ # [0.0.137] - 2025-07-22
2
+
3
+ - Fix bug where update_children_with_new_parent processes a scoped with itself
4
+ - Don't double-create Reject inputs transformers
5
+ - Fix description bug when transforming an entity to its primary key type
6
+ - Add .raise_if_production method to all uses of reset_all(s)
7
+ - Move the start_with? method another repository
8
+ - Prevent attributes transformers without attributes
9
+
10
+ # [0.0.136] - 2025-07-06
11
+
12
+ - Do not allow calling Foobara.reset_alls in production
13
+ - Fix an error backtrace bug
14
+ - Separate Atom/Aggregate request versus object behavior in precommit transformers
15
+ - Fix busted command-class-level state machine callbacks
16
+
1
17
  # [0.0.135] - 2025-07-01
2
18
 
3
19
  - Eliminate Monorepo project
@@ -64,6 +64,7 @@ module Foobara
64
64
  end
65
65
 
66
66
  def reset_all
67
+ Foobara.raise_if_production!("reset_all")
67
68
  builtin_types.each do |builtin_type|
68
69
  builtin_type.foobara_each do |scoped|
69
70
  if scoped.scoped_namespace == builtin_type
@@ -1,4 +1,4 @@
1
- Foobara.require_project_file("callback", "registry/conditioned")
1
+ require_relative "joined_conditioned"
2
2
 
3
3
  module Foobara
4
4
  module Callback
@@ -6,8 +6,6 @@ module Foobara
6
6
  class ChainedConditioned < Conditioned
7
7
  attr_accessor :other_conditions_registry
8
8
 
9
- class InvalidConditions < StandardError; end
10
-
11
9
  foobara_delegate :possible_conditions, :possible_condition_keys, to: :other_conditions_registry
12
10
 
13
11
  def initialize(other_conditions_registry)
@@ -0,0 +1,28 @@
1
+ require_relative "conditioned"
2
+
3
+ module Foobara
4
+ module Callback
5
+ module Registry
6
+ class JoinedConditioned < Conditioned
7
+ attr_accessor :first, :second
8
+
9
+ foobara_delegate :possible_conditions, :possible_condition_keys, to: :first
10
+
11
+ def initialize(first, second)
12
+ self.first = first
13
+ self.second = second
14
+
15
+ super(possible_conditions)
16
+ end
17
+
18
+ def unioned_callback_set_for(...)
19
+ super.union(
20
+ first.unioned_callback_set_for(...).union(
21
+ second.unioned_callback_set_for(...)
22
+ )
23
+ )
24
+ end
25
+ end
26
+ end
27
+ end
28
+ end
@@ -9,6 +9,7 @@ module Foobara
9
9
  end
10
10
 
11
11
  def reset_all
12
+ Foobara.raise_if_production!("reset_all")
12
13
  to_delete = []
13
14
 
14
15
  all.each do |command_class|
@@ -1,3 +1,5 @@
1
+ require_relative "../../state_machine"
2
+
1
3
  module Foobara
2
4
  module CommandPatternImplementation
3
5
  module Concerns
@@ -17,75 +19,90 @@ module Foobara
17
19
  subclass_defined_callbacks.register_callback(:after, &)
18
20
  end
19
21
 
20
- def callback_state_machine_target
21
- Foobara::Command::StateMachine
22
+ def state_machine_callback_registry
23
+ return @state_machine_callback_registry if defined?(@state_machine_callback_registry)
24
+
25
+ @state_machine_callback_registry = if superclass.respond_to?(:state_machine_callback_registry)
26
+ Callback::Registry::ChainedConditioned.new(
27
+ superclass.state_machine_callback_registry
28
+ )
29
+ else
30
+ Callback::Registry::Conditioned.new(
31
+ from: Foobara::Command::StateMachine.states,
32
+ transition: Foobara::Command::StateMachine.transitions,
33
+ to: Foobara::Command::StateMachine.states
34
+ )
35
+ end
22
36
  end
23
37
 
24
- foobara_delegate :remove_all_callbacks, to: :callback_state_machine_target
38
+ def remove_all_callbacks
39
+ Foobara::Command::StateMachine.remove_all_callbacks
40
+ if defined?(@state_machine_callback_registry)
41
+ remove_instance_variable(:@state_machine_callback_registry)
42
+ end
43
+ end
25
44
  end
26
45
 
27
- on_include do
28
- self.subclass_defined_callbacks ||= Foobara::Callback::Registry::SingleAction.new
29
-
30
- [self, singleton_class].each do |target|
31
- [:before, :after].each do |type|
32
- target.define_method "#{type}_any_transition" do |&block|
33
- callback_state_machine_target.register_transition_callback(type) do |state_machine:, **args|
34
- block.call(command: state_machine.owner, **args)
35
- end
46
+ [self, ClassMethods].each do |target|
47
+ [:before, :after].each do |type|
48
+ target.define_method "#{type}_any_transition" do |&block|
49
+ state_machine_callback_registry.register_callback(type) do |state_machine:, **args|
50
+ block.call(command: state_machine.owner, **args)
36
51
  end
37
52
  end
53
+ end
38
54
 
39
- target.define_method "around_any_transition" do |&block|
40
- callback_state_machine_target.register_transition_callback(
41
- :around
42
- ) do |state_machine:, **args, &do_transition_block|
43
- block.call(command: state_machine.owner, **args, &do_transition_block)
44
- end
55
+ target.define_method "around_any_transition" do |&block|
56
+ state_machine_callback_registry.register_callback(
57
+ :around
58
+ ) do |state_machine:, **args, &do_transition_block|
59
+ block.call(command: state_machine.owner, **args, &do_transition_block)
45
60
  end
61
+ end
46
62
 
47
- target.define_method :error_any_transition do |&block|
48
- callback_state_machine_target.register_transition_callback(:error) do |error|
49
- callback_data = error.callback_data
63
+ target.define_method :error_any_transition do |&block|
64
+ state_machine_callback_registry.register_callback(:error) do |error|
65
+ callback_data = error.callback_data
50
66
 
51
- state_machine = callback_data[:state_machine]
52
- command = state_machine.owner
53
- from = callback_data[:from]
54
- transition = callback_data[:transition]
55
- to = callback_data[:to]
67
+ state_machine = callback_data[:state_machine]
68
+ command = state_machine.owner
69
+ from = callback_data[:from]
70
+ transition = callback_data[:transition]
71
+ to = callback_data[:to]
56
72
 
57
- block.call(error:, command:, state_machine:, from:, to:, transition:)
58
- end
73
+ block.call(error:, command:, state_machine:, from:, to:, transition:)
59
74
  end
60
75
  end
76
+ end
61
77
 
62
- Foobara::Command::StateMachine.transitions.each do |transition|
63
- [self, singleton_class].each do |target|
64
- [:before, :after].each do |type|
65
- target.define_method "#{type}_#{transition}" do |&block|
66
- callback_state_machine_target.register_transition_callback(
67
- type, transition:
68
- ) do |state_machine:, **args|
69
- block.call(command: state_machine.owner, **args)
70
- end
78
+ Foobara::Command::StateMachine.transitions.each do |transition|
79
+ [self, ClassMethods].each do |target|
80
+ [:before, :after].each do |type|
81
+ target.define_method "#{type}_#{transition}" do |&block|
82
+ state_machine_callback_registry.register_callback(
83
+ type, transition:
84
+ ) do |state_machine:, **args|
85
+ block.call(command: state_machine.owner, **args)
71
86
  end
72
87
  end
88
+ end
73
89
 
74
- target.define_method "around_#{transition}" do |&block|
75
- callback_state_machine_target.register_transition_callback(
76
- :around, transition:
77
- ) do |state_machine:, **args, &do_transition_block|
78
- block.call(command: state_machine.owner, **args, &do_transition_block)
79
- end
90
+ target.define_method "around_#{transition}" do |&block|
91
+ state_machine_callback_registry.register_callback(
92
+ :around, transition:
93
+ ) do |state_machine:, **args, &do_transition_block|
94
+ block.call(command: state_machine.owner, **args, &do_transition_block)
80
95
  end
81
96
  end
82
97
  end
83
98
  end
84
99
 
85
- private
100
+ def state_machine_callback_registry
101
+ state_machine.callback_registry
102
+ end
86
103
 
87
- def callback_state_machine_target
88
- state_machine
104
+ on_include do
105
+ self.subclass_defined_callbacks ||= Foobara::Callback::Registry::SingleAction.new
89
106
  end
90
107
  end
91
108
  end
@@ -16,6 +16,7 @@ module Foobara
16
16
  end
17
17
 
18
18
  def reset_all
19
+ Foobara.raise_if_production!("reset_all")
19
20
  remove_instance_variable("@all") if instance_variable_defined?("@all")
20
21
  end
21
22
 
@@ -3,8 +3,17 @@ module Foobara
3
3
  module Concerns
4
4
  module StateMachine
5
5
  def state_machine
6
+ return @state_machine if defined?(@state_machine)
7
+
6
8
  # It makes me nervous to pass self around. Seems like a design smell.
7
- @state_machine ||= Foobara::Command::StateMachine.new(owner: self)
9
+ @state_machine = Foobara::Command::StateMachine.new(owner: self)
10
+
11
+ @state_machine.callback_registry = Callback::Registry::JoinedConditioned.new(
12
+ @state_machine.callback_registry,
13
+ self.class.state_machine_callback_registry
14
+ )
15
+
16
+ @state_machine
8
17
  end
9
18
  end
10
19
  end
@@ -24,6 +24,7 @@ module Foobara
24
24
  end
25
25
 
26
26
  def reset_all
27
+ Foobara.raise_if_production!("reset_all")
27
28
  remove_instance_variable("@desugarizer") if defined?(@desugarizer)
28
29
  remove_instance_variable("@desugarizers") if defined?(@desugarizers)
29
30
  end
@@ -11,8 +11,7 @@ module Foobara
11
11
  end
12
12
 
13
13
  def serialize(error_collection)
14
- errors = error_collection.errors
15
- errors.map(&:to_h)
14
+ error_collection.map(&:to_h)
16
15
  end
17
16
  end
18
17
  end
@@ -1,6 +1,5 @@
1
1
  module Foobara
2
2
  # TODO: feels so strange that this doesn't inherit from command
3
- # TODO: move this to command connectors project
4
3
  class TransformedCommand
5
4
  class << self
6
5
  # TODO: handle errors_transformers!
@@ -752,7 +751,6 @@ module Foobara
752
751
  self.outcome = outcome if outcome
753
752
  rescue => e
754
753
  if capture_unknown_error
755
- # TODO: move to superclass?
756
754
  self.outcome = Outcome.error(CommandConnector::UnknownError.for(e))
757
755
  else
758
756
  # :nocov:
@@ -52,13 +52,19 @@ module Foobara
52
52
 
53
53
  unless to_type.extends_directly?(Foobara::BuiltinTypes[:detached_entity]) ||
54
54
  to_type.extends_directly?(Foobara::BuiltinTypes[:entity])
55
+
55
56
  description = [
56
57
  description,
57
- to_type.description
58
+ *to_type.description
58
59
  ].join(" : ")
59
60
  end
61
+
60
62
  declaration[:description] = description
61
63
 
64
+ if to_type.declaration_data.key?(:allow_nil)
65
+ declaration[:allow_nil] = to_type.declaration_data[:allow_nil]
66
+ end
67
+
62
68
  declaration
63
69
  elsif to_type.extends?(Foobara::BuiltinTypes[:model])
64
70
  attributes_type = to_type.target_class.attributes_type
@@ -1,35 +1,18 @@
1
+ require_relative "load_aggregates_transformer"
2
+
1
3
  module Foobara
2
4
  module CommandConnectors
3
5
  module Transformers
4
- class LoadAggregatesPreCommitTransformer < Value::Transformer
6
+ class LoadAggregatesPreCommitTransformer < LoadAggregatesTransformer
5
7
  def applicable?(request)
6
8
  request.command.outcome.success?
7
9
  end
8
10
 
9
11
  def transform(request)
10
- load_aggregates(request.command.outcome.result)
12
+ super(request.command.outcome.result)
11
13
 
12
14
  request
13
15
  end
14
-
15
- def load_aggregates(object)
16
- case object
17
- when Entity
18
- object.class.load_aggregate(object)
19
- when Array
20
- object.each do |element|
21
- load_aggregates(element)
22
- end
23
- when Hash
24
- object.each_key do |key|
25
- load_aggregates(key)
26
- end
27
-
28
- object.each_value do |value|
29
- load_aggregates(value)
30
- end
31
- end
32
- end
33
16
  end
34
17
  end
35
18
  end
@@ -0,0 +1,30 @@
1
+ module Foobara
2
+ module CommandConnectors
3
+ module Transformers
4
+ class LoadAggregatesTransformer < Value::Transformer
5
+ def transform(object)
6
+ load_aggregates(object)
7
+ end
8
+
9
+ def load_aggregates(object)
10
+ case object
11
+ when Entity
12
+ object.class.load_aggregate(object)
13
+ when Array
14
+ object.each do |element|
15
+ load_aggregates(element)
16
+ end
17
+ when Hash
18
+ object.each_key do |key|
19
+ load_aggregates(key)
20
+ end
21
+
22
+ object.each_value do |value|
23
+ load_aggregates(value)
24
+ end
25
+ end
26
+ end
27
+ end
28
+ end
29
+ end
30
+ end
@@ -1,36 +1,18 @@
1
+ require_relative "load_atoms_transformer"
2
+
1
3
  module Foobara
2
4
  module CommandConnectors
3
5
  module Transformers
4
- class LoadAtomsPreCommitTransformer < Value::Transformer
6
+ class LoadAtomsPreCommitTransformer < LoadAtomsTransformer
5
7
  def applicable?(request)
6
8
  request.command.outcome.success?
7
9
  end
8
10
 
9
11
  def transform(request)
10
- load_atoms(request.command.outcome.result)
12
+ super(request.command.outcome.result)
11
13
 
12
14
  request
13
15
  end
14
-
15
- def load_atoms(object)
16
- case object
17
- when Entity
18
- if object.persisted? && !object.loaded?
19
- object.class.load(object)
20
- end
21
- when Model
22
- load_atoms(object.attributes)
23
- when Array
24
- object.each do |element|
25
- load_atoms(element)
26
- end
27
- when Hash
28
- object.each_pair do |key, value|
29
- load_atoms(key)
30
- load_atoms(value)
31
- end
32
- end
33
- end
34
16
  end
35
17
  end
36
18
  end
@@ -0,0 +1,31 @@
1
+ module Foobara
2
+ module CommandConnectors
3
+ module Transformers
4
+ class LoadAtomsTransformer < Value::Transformer
5
+ def transform(object)
6
+ load_atoms(object)
7
+ end
8
+
9
+ def load_atoms(object)
10
+ case object
11
+ when Entity
12
+ if object.persisted? && !object.loaded?
13
+ object.class.load(object)
14
+ end
15
+ when Model
16
+ load_atoms(object.attributes)
17
+ when Array
18
+ object.each do |element|
19
+ load_atoms(element)
20
+ end
21
+ when Hash
22
+ object.each_pair do |key, value|
23
+ load_atoms(key)
24
+ load_atoms(value)
25
+ end
26
+ end
27
+ end
28
+ end
29
+ end
30
+ end
31
+ end
@@ -231,6 +231,10 @@ module Foobara
231
231
  has_build_error = false
232
232
 
233
233
  1.upto(10) do |i|
234
+ backtrace_line = backtrace_when_initialized[i]
235
+
236
+ break unless backtrace_line
237
+
234
238
  if backtrace_when_initialized[i].end_with?("#build_error'")
235
239
  index = i + 1
236
240
  has_build_error = true
@@ -1,22 +1,15 @@
1
1
  module Foobara
2
- # TODO: inherit array instead of delegating
3
- class ErrorCollection
2
+ class ErrorCollection < Array
4
3
  class ErrorAlreadySetError < StandardError; end
5
4
 
6
5
  class << self
7
6
  def to_h(errors)
8
7
  new.tap do |collection|
9
8
  collection.add_errors(errors)
10
- end.to_h
9
+ end.errors_hash
11
10
  end
12
11
  end
13
12
 
14
- attr_reader :error_array
15
-
16
- def initialize
17
- @error_array = []
18
- end
19
-
20
13
  def success?
21
14
  empty?
22
15
  end
@@ -25,14 +18,18 @@ module Foobara
25
18
  !empty?
26
19
  end
27
20
 
28
- foobara_delegate :empty?, :partition, :size, :clear, to: :error_array
29
-
30
21
  def errors
31
- error_array
22
+ # :nocov:
23
+ warn "DEPRECATED: Do not call ErrorCollection#errors instead just use the collection directly."
24
+ self
25
+ # :nocov:
32
26
  end
33
27
 
34
28
  def each_error(&)
35
- error_array.each(&)
29
+ # :nocov:
30
+ warn "DEPRECATED: This method will be deprecated in the coming version"
31
+ each(&)
32
+ # :nocov:
36
33
  end
37
34
 
38
35
  def has_error?(error)
@@ -42,15 +39,13 @@ module Foobara
42
39
  # :nocov:
43
40
  end
44
41
 
45
- error_array.include?(error)
42
+ include?(error)
46
43
  end
47
44
 
48
45
  def add_error(error_or_collection_or_error_hash)
49
46
  error = case error_or_collection_or_error_hash
50
47
  when Error
51
48
  error_or_collection_or_error_hash
52
- when ErrorCollection
53
- return add_errors(error_or_collection_or_error_hash.errors)
54
49
  when Hash
55
50
  if error_or_collection_or_error_hash.key?(:symbol) &&
56
51
  error_or_collection_or_error_hash.key?(:message)
@@ -73,25 +68,32 @@ module Foobara
73
68
  raise ErrorAlreadySetError, "cannot set #{error} more than once"
74
69
  end
75
70
 
76
- error_array << error
71
+ self << error
77
72
  end
78
73
 
79
74
  def add_errors(errors)
80
75
  Util.array(errors).each { |error| add_error(error) }
81
76
  end
82
77
 
83
- def to_h
84
- error_array.to_h do |error|
85
- [error.key, error.to_h]
78
+ def errors_hash
79
+ each_with_object({}) do |error, hash|
80
+ hash[error.key] = error.to_h
86
81
  end
87
82
  end
88
83
 
89
84
  def to_sentence
90
- Util.to_sentence(error_array.map(&:message))
85
+ Util.to_sentence(map(&:message))
91
86
  end
92
87
 
93
88
  def keys
94
- error_array.map(&:key)
89
+ map(&:key)
90
+ end
91
+
92
+ def to_h
93
+ # :nocov:
94
+ warn "DEPRECATED: Use #errors_hash instead"
95
+ errors_hash
96
+ # :nocov:
95
97
  end
96
98
  end
97
99
  end
@@ -1,5 +1,5 @@
1
1
  module Foobara
2
- # TODO: path's have use outside of errors. Make this more general.
2
+ # TODO: paths have use outside of errors. Make this more general.
3
3
  class ErrorKey
4
4
  # TODO: use this wherever it makes sense
5
5
  EMPTY_PATH = [].freeze
@@ -56,29 +56,35 @@ module Foobara
56
56
  end
57
57
 
58
58
  foobara_delegate :has_errors?,
59
- :errors,
60
- :each_error,
61
59
  :has_error?,
62
60
  :add_error,
63
61
  :add_errors,
64
62
  to: :error_collection
65
63
 
64
+ def errors
65
+ error_collection
66
+ end
67
+
68
+ def each_error(&)
69
+ error_collection.each(&)
70
+ end
71
+
66
72
  def success?
67
73
  !has_errors?
68
74
  end
69
75
 
70
76
  def fatal?
71
- errors.any?(&:fatal?)
77
+ error_collection.any?(&:fatal?)
72
78
  end
73
79
 
74
80
  def raise!
75
81
  return if success?
76
82
 
77
- error = errors.first
83
+ error = error_collection.first
78
84
  original_backtrace = error.backtrace_when_initialized
79
85
 
80
- if errors.size > 1
81
- error = UnsuccessfulOutcomeError.new(errors)
86
+ if error_collection.size > 1
87
+ error = UnsuccessfulOutcomeError.new(error_collection)
82
88
  end
83
89
 
84
90
  error.set_backtrace(original_backtrace)
@@ -93,7 +99,7 @@ module Foobara
93
99
  end
94
100
 
95
101
  def errors_hash
96
- error_collection.to_h
102
+ error_collection.errors_hash
97
103
  end
98
104
 
99
105
  def errors_sentence
@@ -16,6 +16,7 @@ module Foobara
16
16
  end
17
17
 
18
18
  def reset_all
19
+ Foobara.raise_if_production!("reset_all")
19
20
  install!
20
21
  end
21
22
  end
@@ -430,7 +430,6 @@ module Foobara
430
430
  end
431
431
  end
432
432
 
433
- # TODO: can we kill this skip concept?
434
433
  def foobara_manifest
435
434
  to_include = TypeDeclarations.foobara_manifest_context_to_include
436
435
 
@@ -4,7 +4,6 @@ module Foobara
4
4
  class NoSuchOrganization < StandardError; end
5
5
 
6
6
  class << self
7
- # TODO: move this to organization.rb
8
7
  def to_organization(object)
9
8
  case object
10
9
  when nil
@@ -1,5 +1,5 @@
1
1
  module Foobara
2
- # TODO: I think we should have a configuration that indicates if created records can have primary keys past to them
2
+ # TODO: I think we should have a configuration that indicates if created records can have primary keys passed to them
3
3
  # or not. That is, do primary keys get issued by the database upon insertion? Or are they generated externally
4
4
  # and passed in? Would be nice to have programmatic clarification via explicit configuration.
5
5
  class Entity < DetachedEntity
@@ -21,6 +21,7 @@ module Foobara
21
21
  end
22
22
 
23
23
  def reset_all
24
+ Foobara.raise_if_production!("reset_all")
24
25
  Entity::Concerns::Callbacks.reset_all
25
26
 
26
27
  install!
@@ -0,0 +1,7 @@
1
+ module Foobara
2
+ module AssociationDepth
3
+ ATOM = :atom
4
+ AGGREGATE = :aggregate
5
+ PRIMARY_KEY_ONLY = :primary_key_only
6
+ end
7
+ end
@@ -6,6 +6,7 @@ module Foobara
6
6
 
7
7
  class << self
8
8
  def reset_all
9
+ Foobara.raise_if_production!("reset_all")
9
10
  Entity.instance_variable_set("@class_callback_registry", nil)
10
11
  end
11
12
  end
@@ -1,6 +1,8 @@
1
1
  require_relative "project"
2
2
 
3
3
  module Foobara
4
+ class MethodCantBeCalledInProductionError < StandardError; end
5
+
4
6
  class << self
5
7
  def require_project_file(project, path)
6
8
  require_relative("../../#{project}/src/#{path}")
@@ -47,7 +49,14 @@ module Foobara
47
49
  end
48
50
 
49
51
  def reset_alls
52
+ raise_if_production!("reset_alls")
50
53
  all_projects.each_value(&:reset_all)
51
54
  end
55
+
56
+ def raise_if_production!(*)
57
+ if ENV["FOOBARA_ENV"].nil? || ENV["FOOBARA_ENV"] == "production"
58
+ raise MethodCantBeCalledInProductionError
59
+ end
60
+ end
52
61
  end
53
62
  end
@@ -34,6 +34,7 @@ module Foobara
34
34
  end
35
35
 
36
36
  def reset_all
37
+ Foobara.raise_if_production!("reset_all")
37
38
  if self.module.respond_to?(:reset_all)
38
39
  self.module.reset_all
39
40
  end
@@ -19,8 +19,6 @@ module Foobara
19
19
  self[:manually_added]
20
20
  end
21
21
 
22
- # TODO: this has to die
23
-
24
22
  # oops, shadowed the convenience method
25
23
  def _path
26
24
  method_missing(:path)
@@ -28,6 +28,7 @@ module Foobara
28
28
  end
29
29
 
30
30
  def reset_all
31
+ Foobara.raise_if_production!("reset_all")
31
32
  install!
32
33
  end
33
34
  end
@@ -1,9 +1,6 @@
1
1
  require "inheritable_thread_vars"
2
2
 
3
3
  module Foobara
4
- # TODO: either make this an abstract base class of ValueModel and Entity or rename it to ValueModel
5
- # and have Entity inherit from it...
6
- # TODO: also, why is this at the root level instead of in a project??
7
4
  class Model
8
5
  class NoSuchAttributeError < StandardError; end
9
6
  class AttributeIsImmutableError < StandardError; end
@@ -312,7 +309,7 @@ module Foobara
312
309
  end
313
310
 
314
311
  def validation_errors
315
- attributes_type.process_value(attributes).errors
312
+ attributes_type.process_value(attributes).error_collection
316
313
  end
317
314
 
318
315
  def validate!
@@ -11,7 +11,6 @@ module Foobara
11
11
  Thread.current[:foobara_current_namespace] || global
12
12
  end
13
13
 
14
- # TODO: eliminate deprecated_namespace and yield instead
15
14
  def use(namespace)
16
15
  unless namespace.is_a?(Namespace::IsNamespace)
17
16
  # :nocov:
@@ -248,10 +248,12 @@ module Foobara
248
248
  next if parent == mod
249
249
 
250
250
  if parent && !parent.scoped_full_path.empty?
251
- next if _start_with?(parent.scoped_full_path, mod.scoped_full_path)
251
+ next if Foobara::Util.start_with?(parent.scoped_full_path, mod.scoped_full_path)
252
252
  end
253
253
 
254
- if _start_with?(scoped.scoped_full_path, mod.scoped_full_path)
254
+ next if scoped.scoped_full_path == mod.scoped_full_path
255
+
256
+ if Foobara::Util.start_with?(scoped.scoped_full_path, mod.scoped_full_path)
255
257
  scoped.scoped_path = scoped.scoped_full_path[mod.scoped_full_path.size..]
256
258
 
257
259
  if parent
@@ -268,17 +270,6 @@ module Foobara
268
270
  end
269
271
  end
270
272
  end
271
-
272
- # TODO: move to util
273
- def _start_with?(large_array, small_array)
274
- return false unless large_array.size > small_array.size
275
-
276
- small_array.each.with_index do |item, index|
277
- return false unless large_array[index] == item
278
- end
279
-
280
- true
281
- end
282
273
  end
283
274
 
284
275
  def foobara_namespace!(scoped_path: nil, ignore_modules: nil)
@@ -2,6 +2,7 @@ module Foobara
2
2
  module Persistence
3
3
  class << self
4
4
  def reset_all
5
+ Foobara.raise_if_production!("reset_all")
5
6
  @tables_for_entity_class_name = @bases = @default_crud_driver = @default_base = nil
6
7
  EntityBase::Transaction::Concerns::EntityCallbackHandling.reset_all
7
8
  EntityBase::Transaction.reset_all
@@ -10,6 +10,7 @@ module Foobara
10
10
  module EntityCallbackHandling
11
11
  class << self
12
12
  def reset_all
13
+ Foobara.raise_if_production!("reset_all")
13
14
  install!
14
15
  end
15
16
 
@@ -21,6 +21,7 @@ module Foobara
21
21
  end
22
22
 
23
23
  def reset_all
24
+ Foobara.raise_if_production!("reset_all")
24
25
  @open_transactions = nil
25
26
  end
26
27
 
@@ -2,6 +2,7 @@ module Foobara
2
2
  module TypeDeclarations
3
3
  class << self
4
4
  def reset_all
5
+ Foobara.raise_if_production!("reset_all")
5
6
  # TODO: this doesn't really belong here. I think we need to maybe call reset in reverse order?
6
7
  Foobara::Domain::DomainModuleExtension.all.each do |domain|
7
8
  var = "@foobara_type_builder"
@@ -3,6 +3,12 @@ module Foobara
3
3
  class << self
4
4
  # TODO: dry this up with a .subclass method in AttributesTransformers?
5
5
  def from_yaml(*attribute_names)
6
+ if attribute_names.empty?
7
+ # :nocov:
8
+ raise ArgumentError, "You must specify at least one attribute name"
9
+ # :nocov:
10
+ end
11
+
6
12
  symbol = symbol_for_attribute_names(attribute_names)
7
13
  existing = FromYaml.foobara_lookup(symbol, mode: Namespace::LookupMode::DIRECT)
8
14
 
@@ -2,10 +2,18 @@ module Foobara
2
2
  class AttributesTransformers < TypeDeclarations::TypedTransformer
3
3
  class << self
4
4
  def only(*attribute_names)
5
+ if attribute_names.empty?
6
+ # :nocov:
7
+ raise ArgumentError, "You must specify at least one attribute name"
8
+ # :nocov:
9
+ end
10
+
5
11
  symbol = symbol_for_attribute_names(attribute_names)
6
12
  existing = Only.foobara_lookup(symbol, mode: Namespace::LookupMode::DIRECT)
7
13
 
8
- return existing if existing
14
+ if existing
15
+ return existing
16
+ end
9
17
 
10
18
  transformer_class = Class.new(Only)
11
19
  transformer_class.only_attributes = attribute_names
@@ -2,6 +2,17 @@ module Foobara
2
2
  class AttributesTransformers < TypeDeclarations::TypedTransformer
3
3
  class << self
4
4
  def reject(*attribute_names)
5
+ if attribute_names.empty?
6
+ # :nocov:
7
+ raise ArgumentError, "You must specify at least one attribute name"
8
+ # :nocov:
9
+ end
10
+
11
+ symbol = symbol_for_attribute_names(attribute_names)
12
+ existing = Reject.foobara_lookup(symbol, mode: Namespace::LookupMode::DIRECT)
13
+
14
+ return existing if existing
15
+
5
16
  transformer_class = Class.new(Reject)
6
17
  transformer_class.reject_attributes = attribute_names
7
18
 
@@ -235,7 +235,7 @@ module Foobara
235
235
  return old_outcome unless applicable?(value)
236
236
 
237
237
  process_value(value).tap do |outcome|
238
- outcome.add_errors(old_outcome.errors)
238
+ outcome.add_errors(old_outcome.error_collection)
239
239
  end
240
240
  end
241
241
 
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: foobara
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.135
4
+ version: 0.0.137
5
5
  platform: ruby
6
6
  authors:
7
7
  - Miles Georgi
8
8
  bindir: bin
9
9
  cert_chain: []
10
- date: 1980-01-02 00:00:00.000000000 Z
10
+ date: 2025-07-22 00:00:00.000000000 Z
11
11
  dependencies:
12
12
  - !ruby/object:Gem::Dependency
13
13
  name: bigdecimal
@@ -155,6 +155,7 @@ files:
155
155
  - projects/callback/src/registry/chained_conditioned.rb
156
156
  - projects/callback/src/registry/chained_multiple_action.rb
157
157
  - projects/callback/src/registry/conditioned.rb
158
+ - projects/callback/src/registry/joined_conditioned.rb
158
159
  - projects/callback/src/registry/multiple_action.rb
159
160
  - projects/callback/src/registry/single_action.rb
160
161
  - projects/callback/src/runner.rb
@@ -231,7 +232,9 @@ files:
231
232
  - projects/command_connectors/src/transformers/auth_errors_transformer.rb
232
233
  - projects/command_connectors/src/transformers/entity_to_primary_key_inputs_transformer.rb
233
234
  - projects/command_connectors/src/transformers/load_aggregates_pre_commit_transformer.rb
235
+ - projects/command_connectors/src/transformers/load_aggregates_transformer.rb
234
236
  - projects/command_connectors/src/transformers/load_atoms_pre_commit_transformer.rb
237
+ - projects/command_connectors/src/transformers/load_atoms_transformer.rb
235
238
  - projects/command_connectors/src/transformers/load_delegated_attributes_entities_pre_commit_transformer.rb
236
239
  - projects/common/lib/foobara/common.rb
237
240
  - projects/common/src/data_path.rb
@@ -288,6 +291,7 @@ files:
288
291
  - projects/domain_mapper/src/domain_mapper.rb
289
292
  - projects/domain_mapper/src/domain_mapper_lookups.rb
290
293
  - projects/entity/lib/foobara/entity.rb
294
+ - projects/entity/src/association_depth.rb
291
295
  - projects/entity/src/concerns/attributes.rb
292
296
  - projects/entity/src/concerns/callbacks.rb
293
297
  - projects/entity/src/concerns/initialization.rb
@@ -531,7 +535,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
531
535
  - !ruby/object:Gem::Version
532
536
  version: '0'
533
537
  requirements: []
534
- rubygems_version: 3.6.9
538
+ rubygems_version: 3.6.2
535
539
  specification_version: 4
536
540
  summary: A command-centric and discoverable software framework with a focus on domain
537
541
  concepts and abstracting away integration code