foobara 0.1.8 → 0.1.10

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 497323362ef9b9bcf4a7d17cb9400b84701e73dc464f3ff318e6a52b6ee3bbf6
4
- data.tar.gz: ee7bc81ea47e850b90e569c4295bd914832c3604277790edd6db153e143515a6
3
+ metadata.gz: 71381dfd48bd1ce8c4dd9fd71a0353753a488fd14a61525e19e240bb6d99ad62
4
+ data.tar.gz: 9c0cb8f97cdee2d089ca751c6517b5af5aacd8a2e540ef974dfa23d726f17208
5
5
  SHA512:
6
- metadata.gz: acc9a5fed9bdfa6f7c19d74652b6c2bf770a24c17880968dc476289d2231ea51b906c538ee3d10dc65365c74d9d97f9f747ae3c97400789ce30e60babc9ca6b2
7
- data.tar.gz: 03225ae2b838efc6816fe072b0f94ea6193552bb1253159aaa749ec471c18d4ea821c399cba711f6f6246cf1c38686d398bb4cd5c6385daebf91014a3ab88436
6
+ metadata.gz: 4899aec1e7f9378c8ed2e568d1c1f99c851bc505e096f742af8592be7b96fe6695282c04ca7e4edc8a8aa320c378bf734e5ad12d62b3f4e67f5cbe865d6286be
7
+ data.tar.gz: d9562836258a051022093aee895099b2809e1effd77a4e0eb444c8012fb12f55e1cbd821b570069ee3bd8b7e9e8ee068195638d7df57b53308d9a057fab4f086
data/CHANGELOG.md CHANGED
@@ -1,4 +1,15 @@
1
- # [0.1.8] - 2025-08-25
1
+ # [0.1.10] - 2025-09-11
2
+
3
+ - Add NotFoundError when an entity input doesn't exist
4
+ - Make #add_input_error more flexible
5
+ - Fix an error path array bug
6
+ - Fix a bug that might prevent inherited possible errors
7
+
8
+ # [0.1.9] - 2025-09-08
9
+
10
+ - Support passing load_paths: to Entity.load to pre-load certain associations
11
+
12
+ # [0.1.8] - 2025-09-05
2
13
 
3
14
  - Memoize various parts of Type
4
15
  - Eliminate DoesNotNeedCastIf* processors
@@ -78,7 +78,7 @@ module Foobara
78
78
  elsif args.empty? || (args.size == 1 && args.first.is_a?(Hash))
79
79
  error_args = opts.merge(args.first || {})
80
80
  symbol = error_args[:symbol]
81
- path = Util.array(error_args[:input] || error_args[:path])
81
+ path = error_args[:input] || error_args[:path]
82
82
 
83
83
  error_args = error_args.except(:input)
84
84
 
@@ -100,8 +100,14 @@ module Foobara
100
100
  input, symbol, message = args
101
101
  context = opts
102
102
 
103
- error_class = self.class.lookup_input_error_class(symbol, input)
104
- error_class.new(path: Util.array(input), symbol:, context:, message:)
103
+ if symbol.is_a?(::Class) && symbol < Foobara::Error
104
+ error_class = symbol
105
+ symbol = error_class.symbol
106
+ else
107
+ error_class = self.class.lookup_input_error_class(symbol, input)
108
+ end
109
+
110
+ error_class.new(path: input, symbol:, context:, message:)
105
111
  else
106
112
  # :nocov:
107
113
  raise ArgumentError,
@@ -81,6 +81,11 @@ module Foobara
81
81
  symbol = error_class.symbol
82
82
 
83
83
  possible_error = PossibleError.new(error_class, symbol:, data:)
84
+
85
+ if path.is_a?(::String) || path.is_a?(::Symbol)
86
+ path = path.to_s.split(".")
87
+ end
88
+
84
89
  possible_error.prepend_path!(path)
85
90
 
86
91
  possible_error.manually_added = true
@@ -93,10 +98,24 @@ module Foobara
93
98
 
94
99
  # TODO: kill this method in favor of possible_errors
95
100
  def error_context_type_map
101
+ return @error_context_type_map if defined?(@error_context_type_map)
102
+
96
103
  process_error_constants
97
- @error_context_type_map ||= if superclass < Foobara::Command
98
- superclass.error_context_type_map.dup
99
- end || {}
104
+ map = if superclass < Foobara::Command
105
+ superclass.error_context_type_map.dup
106
+ end || {}
107
+
108
+ @error_context_type_map = if @error_context_type_map
109
+ map.merge(@error_context_type_map)
110
+ else
111
+ map
112
+ end
113
+
114
+ inputs_association_paths&.each do |data_path|
115
+ possible_input_error(data_path.to_sym, CommandPatternImplementation::NotFoundError)
116
+ end
117
+
118
+ @error_context_type_map
100
119
  end
101
120
 
102
121
  def register_possible_error_class(possible_error)
@@ -6,6 +6,26 @@ module Foobara
6
6
 
7
7
  include Concern
8
8
 
9
+ module ClassMethods
10
+ def inputs_association_paths
11
+ return @inputs_association_paths if defined?(@inputs_association_paths)
12
+
13
+ @inputs_association_paths = if inputs_type.nil?
14
+ nil
15
+ else
16
+ keys = Entity.construct_associations(inputs_type).keys
17
+
18
+ if keys.empty?
19
+ nil
20
+ else
21
+ keys.map do |key|
22
+ DataPath.new(key)
23
+ end
24
+ end
25
+ end
26
+ end
27
+ end
28
+
9
29
  attr_reader :inputs, :raw_inputs
10
30
 
11
31
  def initialize(inputs = {})
@@ -12,6 +12,10 @@ module Foobara
12
12
  unregister_possible_error_if_registered(possible_error)
13
13
  end
14
14
 
15
+ if defined?(@inputs_association_paths)
16
+ remove_instance_variable(:@inputs_association_paths)
17
+ end
18
+
15
19
  type = type_for_declaration(...)
16
20
 
17
21
  if type.extends?(BuiltinTypes[:model]) && !type.extends?(BuiltinTypes[:entity])
@@ -7,6 +7,13 @@ module Foobara
7
7
  class CannotHaltWithoutAddingErrors < StandardError; end
8
8
  class Halt < StandardError; end
9
9
 
10
+ class NotFoundError < Foobara::DataError
11
+ context do
12
+ entity_class :string, :required
13
+ criteria :duck
14
+ end
15
+ end
16
+
10
17
  module ClassMethods
11
18
  def run(...)
12
19
  new(...).run
@@ -81,7 +88,41 @@ module Foobara
81
88
  end
82
89
 
83
90
  def validate_records
84
- # noop
91
+ self.class.inputs_association_paths&.each do |data_path|
92
+ if data_path.last == :"#"
93
+ records = data_path.values_at(@inputs)
94
+
95
+ records.each.with_index do |record, index|
96
+ if record&.persisted? && !record.loaded?
97
+ begin
98
+ record.class.load(record)
99
+ rescue Foobara::Entity::NotFoundError => e
100
+ add_input_error(
101
+ [*data_path.path[..-2], index],
102
+ CommandPatternImplementation::NotFoundError,
103
+ criteria: e.criteria,
104
+ entity_class: record.class.model_type.scoped_full_name
105
+ )
106
+ end
107
+ end
108
+ end
109
+ else
110
+ record = data_path.value_at(@inputs)
111
+
112
+ if record&.persisted? && !record.loaded?
113
+ begin
114
+ record.class.load(record)
115
+ rescue Foobara::Entity::NotFoundError => e
116
+ add_input_error(
117
+ data_path.to_s,
118
+ CommandPatternImplementation::NotFoundError,
119
+ criteria: e.criteria,
120
+ entity_class: record.class.model_type.scoped_full_name
121
+ )
122
+ end
123
+ end
124
+ end
125
+ end
85
126
  end
86
127
 
87
128
  def validate
@@ -31,6 +31,7 @@ module Foobara
31
31
  key.to_s_type
32
32
  end
33
33
 
34
+ # TODO: flip these arguments?
34
35
  def values_at(data_path, object)
35
36
  unless data_path.is_a?(DataPath)
36
37
  data_path = new(data_path)
@@ -215,6 +215,11 @@ module Foobara
215
215
  self.message = message
216
216
  self.context = context
217
217
  self.category = category
218
+
219
+ if path.is_a?(::String) || path.is_a?(::Symbol)
220
+ path = path.to_s.split(".").map(&:to_sym)
221
+ end
222
+
218
223
  self.path = path
219
224
  self.runtime_path = runtime_path
220
225
  self.is_fatal = is_fatal
@@ -44,16 +44,40 @@ module Foobara
44
44
  current_transaction_table.find_many_by(attributes)
45
45
  end
46
46
 
47
- def load(record)
48
- if record.is_a?(Foobara::Entity)
49
- if record.loaded?
50
- record
47
+ def load(record, load_paths: nil)
48
+ record = if record.is_a?(Foobara::Entity)
49
+ if record.loaded?
50
+ record
51
+ else
52
+ current_transaction_table.load(record)
53
+ end
54
+ else
55
+ current_transaction_table.load(record)
56
+ end
57
+
58
+ if load_paths
59
+ if load_paths.is_a?(::Array)
60
+ first = load_paths.first
61
+
62
+ if first.is_a?(::Symbol) || (first.is_a?(::String) && !first.include?("."))
63
+ load_paths = [load_paths]
64
+ end
51
65
  else
52
- current_transaction_table.load(record)
66
+ load_paths = [load_paths]
67
+ end
68
+
69
+ load_paths.each do |data_path|
70
+ DataPath.values_at(data_path, record).each do |value|
71
+ if value.is_a?(Foobara::Entity)
72
+ value.class.load(value)
73
+ elsif value.is_a?(::Array)
74
+ value.each { |r| r.class.load(r) }
75
+ end
76
+ end
53
77
  end
54
- else
55
- current_transaction_table.load(record)
56
78
  end
79
+
80
+ record
57
81
  rescue ::Foobara::Persistence::EntityAttributesCrudDriver::Table::CannotFindError
58
82
  primary_key = if record.is_a?(Foobara::Entity)
59
83
  record.primary_key
data/version.rb CHANGED
@@ -1,6 +1,6 @@
1
1
  module Foobara
2
2
  module Version
3
- VERSION = "0.1.8".freeze
3
+ VERSION = "0.1.10".freeze
4
4
  MINIMUM_RUBY_VERSION = ">= 3.4.0".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.1.8
4
+ version: 0.1.10
5
5
  platform: ruby
6
6
  authors:
7
7
  - Miles Georgi