foobara 0.5.5 → 0.5.7

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: 6527e62790180b1aeb2f98e069655d8ac72750fbff834fc63e9b75a01c35cb4e
4
- data.tar.gz: a769dd2a642b71bd401dabe3c0917a1fa128069f2a7987ff79df633765ae93ad
3
+ metadata.gz: 0d1c5cb75a03670d17291e1d85de76a826b6fedfe4b0f099f235ca646253c165
4
+ data.tar.gz: 7f852654ca70620a4dd544792d4518cfb7a5cd64214802517bdd9a3e1f435b19
5
5
  SHA512:
6
- metadata.gz: '0359999dd32f56220e88e3e860ff7e415a4fd2b978bf83768868b1e10b0013c9e02597731890d1a2abb2fd11c1e288e1c1e8056b3bd6bf7a11bc9589af371ae3'
7
- data.tar.gz: 33cf7a4428854d3016c1ccda045820e6da47a268e34f5bb05505bcc878ecdeff909caf1c411505d97849f4ffd69cc6e9c1c51a046ee92f6ee7ac2afe1919b359
6
+ metadata.gz: 83077d31d4ac8f03a044568550f97a79a1772f6ec27f3b839501625a400d9b40550df500ba70e8e3241cf9ea001a2a52821b4c2c2c1a76241d5eb8265d36cf43
7
+ data.tar.gz: 9e41a5c335dab08647082b411e55ef4962ddf09a280cba9c8ee58b77533072349a0b271607a1f28ccd56eff82219182dd66e7e41177200abd979d855d9d53430
data/CHANGELOG.md CHANGED
@@ -1,3 +1,13 @@
1
+ # [0.5.7] - 2026-02-25
2
+
3
+ - Add a Manifest::Model.associations convenience method
4
+ - Add Manifest::Tuple and various missing predicate methods
5
+ - Add a query flag to the manifest
6
+
7
+ # [0.5.6] - 2026-02-20
8
+
9
+ - Introduce an official Query concept
10
+
1
11
  # [0.5.5] - 2026-02-19
2
12
 
3
13
  - Fix bug where WeakObjectSet#delete could fail after deactivation
@@ -1,7 +1,7 @@
1
1
  module Foobara
2
2
  module CommandPatternImplementation
3
3
  module Concerns
4
- module Description
4
+ module CommandData
5
5
  include Concern
6
6
 
7
7
  module ClassMethods
@@ -16,6 +16,20 @@ module Foobara
16
16
  # :nocov:
17
17
  end
18
18
  end
19
+
20
+ def is_query
21
+ @is_query = true
22
+ end
23
+
24
+ # rubocop:disable Naming/MemoizedInstanceVariableName
25
+ def query?
26
+ return @is_query if defined?(@is_query)
27
+
28
+ @is_query = if superclass.respond_to?(:query?)
29
+ superclass.query?
30
+ end
31
+ end
32
+ # rubocop:enable Naming/MemoizedInstanceVariableName
19
33
  end
20
34
  end
21
35
  end
@@ -68,6 +68,10 @@ module Foobara
68
68
  ).declaration_data
69
69
  ).merge(description:)
70
70
 
71
+ if query?
72
+ h[:is_query] = true
73
+ end
74
+
71
75
  if result_type
72
76
  # TODO: find a way to represent literal types like "nil"
73
77
  h[:result_type] = result_type.reference_or_declaration_data_for_manifest
@@ -15,7 +15,7 @@ module Foobara
15
15
 
16
16
  include TruncatedInspect
17
17
 
18
- include CommandPatternImplementation::Concerns::Description
18
+ include CommandPatternImplementation::Concerns::CommandData
19
19
  include CommandPatternImplementation::Concerns::Namespace
20
20
 
21
21
  include CommandPatternImplementation::Concerns::InputsType
@@ -0,0 +1,7 @@
1
+ module Foobara
2
+ # TODO: we should probably include CommandPatternImplementation instead of inheriting from Foobara::Command
3
+ # but don't want to hunt down plumbing problems that might arise if Query isn't a Command
4
+ class Query < Foobara::Command
5
+ is_query
6
+ end
7
+ end
@@ -251,13 +251,11 @@ module Foobara
251
251
  contains_associations?(element_type, false)
252
252
  end
253
253
  elsif type.extends?(BuiltinTypes[:attributes])
254
-
255
254
  type.element_types&.values&.any? do |element_type|
256
255
  if !remove_sensitive || !element_type.sensitive?
257
256
  contains_associations?(element_type, false)
258
257
  end
259
258
  end
260
-
261
259
  elsif type.extends?(BuiltinTypes[:associative_array])
262
260
  element_types = type.element_types
263
261
 
@@ -0,0 +1,67 @@
1
+ # TODO: Get this out of here and into model project
2
+ RSpec.describe Foobara::Manifest::Model do
3
+ after { Foobara.reset_alls }
4
+
5
+ describe ".associations" do
6
+ context "when the type has associations" do
7
+ before do
8
+ stub_class "SomeInnerInnerEntity", Foobara::Entity do
9
+ attributes do
10
+ id :integer
11
+ bar :string, :required
12
+ end
13
+ primary_key :id
14
+ end
15
+
16
+ stub_class "SomeOuterModel", Foobara::Model do
17
+ attributes do
18
+ some_inner_inner_entities [:SomeInnerInnerEntity, :SomeInnerInnerEntity]
19
+ end
20
+ end
21
+
22
+ stub_class("SomeInnerEntity", Foobara::Entity) do
23
+ attributes do
24
+ id :integer
25
+ foo :string, :required
26
+ end
27
+
28
+ primary_key :id
29
+ end
30
+
31
+ stub_class("SomeOuterEntity", Foobara::Entity) do
32
+ attributes do
33
+ id :integer
34
+ some_inner_entity :SomeInnerEntity
35
+ end
36
+
37
+ primary_key :id
38
+ end
39
+
40
+ Foobara::GlobalDomain.foobara_register_type(:some_type) do
41
+ some_array [SomeOuterEntity]
42
+ some_inner_model :SomeOuterModel
43
+ end
44
+ end
45
+
46
+ it "can reproduce association info from the underlying associations in the types" do
47
+ raw_manifest = Foobara.manifest
48
+
49
+ root_manifest = Foobara::Manifest::RootManifest.new(raw_manifest)
50
+
51
+ manifest_type = root_manifest.type_by_name(:some_type)
52
+
53
+ expect(manifest_type).to be_a(Foobara::Manifest::Type)
54
+
55
+ associations = described_class.associations(manifest_type)
56
+
57
+ expect(associations.keys).to contain_exactly(
58
+ "some_array.#",
59
+ "some_inner_model.some_inner_inner_entities.0",
60
+ "some_inner_model.some_inner_inner_entities.1"
61
+ )
62
+
63
+ expect(associations.values).to all be_a(Foobara::Manifest::Entity)
64
+ end
65
+ end
66
+ end
67
+ end
@@ -71,7 +71,7 @@ RSpec.describe Foobara::Manifest do
71
71
  primary_key :id
72
72
  end
73
73
 
74
- stub_class "SomeOrg::SomeDomain::QueryUser", Foobara::Command
74
+ stub_class "SomeOrg::SomeDomain::QueryUser", Foobara::Query
75
75
  stub_class "SomeOrg::SomeDomain::QueryUser::SomethingWentWrongError", Foobara::RuntimeError do
76
76
  class << self
77
77
  def context_type_declaration
@@ -259,8 +259,11 @@ RSpec.describe Foobara::Manifest do
259
259
  expect(attributes.sensitive).to be_falsey
260
260
  expect(attributes.sensitive_exposed).to be_falsey
261
261
 
262
+ expect(manifest.queries.map(&:command_name)).to contain_exactly("QueryUser")
263
+
262
264
  command = manifest.command_by_name("SomeOrg::SomeDomain::QueryUser")
263
265
 
266
+ expect(command).to be_query
264
267
  expect(command).to be_a(Foobara::Manifest::Command)
265
268
  expect(command.scoped_category).to eq(:command)
266
269
  expect(command.parent_category).to eq(:domain)
@@ -0,0 +1,30 @@
1
+ RSpec.describe Foobara::Manifest::Type do
2
+ after { Foobara.reset_alls }
3
+
4
+ context "when it's an associative array" do
5
+ before do
6
+ Foobara::GlobalDomain.foobara_register_type(:some_type,
7
+ type: :associative_array,
8
+ value_type_declaration: :string,
9
+ key_type_declaration: :integer)
10
+ end
11
+
12
+ describe "#associative_array?" do
13
+ it "is true" do
14
+ root_manifest = Foobara::Manifest::RootManifest.new(Foobara.manifest)
15
+ expect(root_manifest.type_by_name(:some_type)).to be_associative_array
16
+ end
17
+ end
18
+
19
+ describe "#to_type_declaration_from_declaration_data" do
20
+ it "gives an associative_array declaration" do
21
+ root_manifest = Foobara::Manifest::RootManifest.new(Foobara.manifest)
22
+ type = root_manifest.type_by_name(:some_type)
23
+ declaration = type.to_type_declaration_from_declaration_data
24
+
25
+ expect(declaration).to be_a(Foobara::Manifest::TypeDeclaration)
26
+ expect(declaration).to be_associative_array
27
+ end
28
+ end
29
+ end
30
+ end
@@ -69,8 +69,6 @@ module Foobara
69
69
  end
70
70
 
71
71
  def domain
72
- domain_reference = self[:domain]
73
-
74
72
  Domain.new(root_manifest, [:domain, domain_reference])
75
73
  end
76
74
 
@@ -21,6 +21,10 @@ module Foobara
21
21
  scoped_full_name
22
22
  end
23
23
 
24
+ def query?
25
+ self[:is_query]
26
+ end
27
+
24
28
  def inputs_type
25
29
  Attributes.new(root_manifest, [*manifest_path, :inputs_type])
26
30
  end
@@ -3,6 +3,44 @@ require_relative "type"
3
3
  module Foobara
4
4
  module Manifest
5
5
  class Model < Type
6
+ class << self
7
+ def associations(type, path = DataPath.new, result = {}, initial: true)
8
+ if type.detached_entity? && !initial
9
+ type = type.to_type if type.is_a?(TypeDeclaration)
10
+ result[path.to_s] = type
11
+ elsif type.model?
12
+ type = type.to_type if type.is_a?(TypeDeclaration)
13
+ associations(type.attributes_type, path, result, initial: false)
14
+ elsif type.tuple?
15
+ type = type.to_type_declaration_from_declaration_data if type.is_a?(Type)
16
+ type.element_types&.each&.with_index do |element_type, index|
17
+ associations(element_type, path.append(index), result, initial: false)
18
+ end
19
+ elsif type.array?
20
+ type = type.to_type_declaration_from_declaration_data if type.is_a?(Type)
21
+ element_type = type.element_type
22
+
23
+ if element_type
24
+ associations(element_type, path.append(:"#"), result, initial: false)
25
+ end
26
+ elsif type.attributes?
27
+ type = type.to_type_declaration_from_declaration_data if type.is_a?(Type)
28
+ type.attribute_declarations.each_pair do |attribute_name, element_type|
29
+ associations(element_type, path.append(attribute_name), result, initial: false)
30
+ end
31
+ # :nocov:
32
+ elsif type.associative_array?
33
+ if contains_associations?(type)
34
+ raise "Associative array types with associations in them are not currently supported. " \
35
+ "Use attributes type if you can or set the key_type and/or value_type to duck type"
36
+ end
37
+ end
38
+ # :nocov:
39
+
40
+ result
41
+ end
42
+ end
43
+
6
44
  self.category_symbol = :type
7
45
 
8
46
  optional_keys :delegates
@@ -25,6 +25,10 @@ module Foobara
25
25
  organizations.map(&:commands).flatten
26
26
  end
27
27
 
28
+ def queries
29
+ commands.select(&:query?)
30
+ end
31
+
28
32
  def types
29
33
  @types ||= DataPath.value_at(:type, root_manifest).keys.map do |reference|
30
34
  Type.new(root_manifest, [:type, reference])
@@ -0,0 +1,15 @@
1
+ require_relative "type_declaration"
2
+
3
+ module Foobara
4
+ module Manifest
5
+ class Tuple < TypeDeclaration
6
+ alias tuple_manifest relevant_manifest
7
+
8
+ def element_types
9
+ @element_types ||= (0...element_type_declarations.size).map do |index|
10
+ TypeDeclaration.new(root_manifest, [*manifest_path, :element_type_declarations, index])
11
+ end
12
+ end
13
+ end
14
+ end
15
+ end
@@ -38,6 +38,22 @@ module Foobara
38
38
  !builtin? && extends_symbol?(:model)
39
39
  end
40
40
 
41
+ def array?
42
+ !builtin? && extends_symbol?(:array)
43
+ end
44
+
45
+ def attributes?
46
+ !builtin? && extends_symbol?(:attributes)
47
+ end
48
+
49
+ def associative_array?
50
+ !builtin? && extends_symbol?(:associative_array)
51
+ end
52
+
53
+ def tuple?
54
+ !builtin? && extends_symbol?(:tuple)
55
+ end
56
+
41
57
  def base_type
42
58
  base_type_symbol = self[:base_type]
43
59
 
@@ -15,6 +15,8 @@ module Foobara
15
15
  Attributes.new(type_declaration.root_manifest, type_declaration.manifest_path)
16
16
  when :array
17
17
  Array.new(type_declaration.root_manifest, type_declaration.manifest_path)
18
+ when :tuple
19
+ Tuple.new(type_declaration.root_manifest, type_declaration.manifest_path)
18
20
  else
19
21
  type_declaration
20
22
  end
@@ -82,6 +84,14 @@ module Foobara
82
84
  type.to_sym == :array
83
85
  end
84
86
 
87
+ def tuple?
88
+ type.to_sym == :tuple
89
+ end
90
+
91
+ def associative_array?
92
+ type.to_sym == :associative_array
93
+ end
94
+
85
95
  def model?
86
96
  return @model if defined?(@model)
87
97
 
data/version.rb CHANGED
@@ -1,6 +1,6 @@
1
1
  module Foobara
2
2
  module Version
3
- VERSION = "0.5.5".freeze
3
+ VERSION = "0.5.7".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.5.5
4
+ version: 0.5.7
5
5
  platform: ruby
6
6
  authors:
7
7
  - Miles Georgi
@@ -84,7 +84,7 @@ files:
84
84
  - projects/command/src/command.rb
85
85
  - projects/command/src/command_pattern_implementation.rb
86
86
  - projects/command/src/command_pattern_implementation/concerns/callbacks.rb
87
- - projects/command/src/command_pattern_implementation/concerns/description.rb
87
+ - projects/command/src/command_pattern_implementation/concerns/command_data.rb
88
88
  - projects/command/src/command_pattern_implementation/concerns/domain_mappers.rb
89
89
  - projects/command/src/command_pattern_implementation/concerns/entities.rb
90
90
  - projects/command/src/command_pattern_implementation/concerns/errors.rb
@@ -102,6 +102,7 @@ files:
102
102
  - projects/command/src/extensions/domain/domain_module_extension.rb
103
103
  - projects/command/src/extensions/domain/domain_module_extension_extension.rb
104
104
  - projects/command/src/extensions/foobara.rb
105
+ - projects/command/src/query.rb
105
106
  - projects/command/src/state_machine.rb
106
107
  - projects/command_connectors/Guardfile
107
108
  - projects/command_connectors/lib/foobara/command_connectors.rb
@@ -339,10 +340,12 @@ files:
339
340
  - projects/entities_plumbing/src/extensions/authenticator.rb
340
341
  - projects/manifest/Guardfile
341
342
  - projects/manifest/lib/foobara/manifest.rb
343
+ - projects/manifest/spec/associations_spec.rb
342
344
  - projects/manifest/spec/manifest_spec.rb
343
345
  - projects/manifest/spec/model_spec.rb
344
346
  - projects/manifest/spec/spec_helper.rb
345
347
  - projects/manifest/spec/type_declaration_spec.rb
348
+ - projects/manifest/spec/type_spec.rb
346
349
  - projects/manifest/src/array.rb
347
350
  - projects/manifest/src/attributes.rb
348
351
  - projects/manifest/src/base_manifest.rb
@@ -357,6 +360,7 @@ files:
357
360
  - projects/manifest/src/processor.rb
358
361
  - projects/manifest/src/processor_class.rb
359
362
  - projects/manifest/src/root_manifest.rb
363
+ - projects/manifest/src/tuple.rb
360
364
  - projects/manifest/src/type.rb
361
365
  - projects/manifest/src/type_declaration.rb
362
366
  - projects/model_plumbing/lib/foobara/model_plumbing.rb