quo 1.0.0.beta2 → 2.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.
Files changed (101) hide show
  1. checksums.yaml +4 -4
  2. data/.devcontainer/Dockerfile +17 -0
  3. data/.devcontainer/compose.yml +10 -0
  4. data/.devcontainer/devcontainer.json +12 -0
  5. data/Appraisals +4 -12
  6. data/CHANGELOG.md +112 -1
  7. data/CLAUDE.md +19 -0
  8. data/Gemfile +7 -1
  9. data/LICENSE.txt +1 -1
  10. data/README.md +496 -203
  11. data/Rakefile +66 -6
  12. data/UPGRADING.md +216 -0
  13. data/badges/coverage_badge_total.svg +35 -0
  14. data/badges/rubycritic_badge_score.svg +35 -0
  15. data/claude-skill/README.md +100 -0
  16. data/claude-skill/SKILL.md +442 -0
  17. data/claude-skill/references/API_REFERENCE.md +462 -0
  18. data/claude-skill/references/COMPOSITION.md +396 -0
  19. data/claude-skill/references/PAGINATION.md +396 -0
  20. data/claude-skill/references/QUERY_TYPES.md +297 -0
  21. data/claude-skill/references/TRANSFORMERS.md +282 -0
  22. data/context/01-core-architecture.md +247 -0
  23. data/context/02-query-types-implementation.md +355 -0
  24. data/context/03-composition-transformation.md +441 -0
  25. data/context/04-pagination-results.md +485 -0
  26. data/context/05-testing-configuration.md +491 -0
  27. data/context/06-advanced-patterns-examples.md +153 -0
  28. data/gemfiles/rails_8.0.gemfile +10 -5
  29. data/gemfiles/rails_8.1.gemfile +20 -0
  30. data/lib/generators/quo/install/USAGE +21 -0
  31. data/lib/generators/quo/install/install_generator.rb +63 -0
  32. data/lib/quo/collection_backed_query.rb +21 -15
  33. data/lib/quo/collection_results.rb +1 -0
  34. data/lib/quo/composed_collection_backed_query.rb +42 -0
  35. data/lib/quo/composed_instance.rb +144 -0
  36. data/lib/quo/composed_query.rb +43 -178
  37. data/lib/quo/composed_relation_backed_query.rb +42 -0
  38. data/lib/quo/composing/base_strategy.rb +22 -0
  39. data/lib/quo/composing/class_strategy.rb +86 -0
  40. data/lib/quo/composing/class_strategy_registry.rb +31 -0
  41. data/lib/quo/composing/query_classes_strategy.rb +38 -0
  42. data/lib/quo/composing.rb +81 -0
  43. data/lib/quo/engine.rb +1 -0
  44. data/lib/quo/minitest/helpers.rb +14 -24
  45. data/lib/quo/preloadable.rb +1 -0
  46. data/lib/quo/query.rb +22 -5
  47. data/lib/quo/relation_backed_query.rb +24 -18
  48. data/lib/quo/relation_backed_query_specification.rb +44 -25
  49. data/lib/quo/relation_results.rb +1 -0
  50. data/lib/quo/results.rb +31 -2
  51. data/lib/quo/rspec/helpers.rb +15 -26
  52. data/lib/quo/testing/collection_backed_fake.rb +1 -0
  53. data/lib/quo/testing/fake_helpers.rb +30 -0
  54. data/lib/quo/testing/relation_backed_fake.rb +1 -0
  55. data/lib/quo/version.rb +1 -1
  56. data/lib/quo/wrapped_collection_backed_query.rb +21 -0
  57. data/lib/quo/wrapped_relation_backed_query.rb +21 -0
  58. data/lib/quo.rb +8 -0
  59. data/quo.png +0 -0
  60. data/sig/generated/quo/collection_backed_query.rbs +10 -4
  61. data/sig/generated/quo/collection_results.rbs +1 -0
  62. data/sig/generated/quo/composed_collection_backed_query.rbs +25 -0
  63. data/sig/generated/quo/composed_instance.rbs +61 -0
  64. data/sig/generated/quo/composed_query.rbs +23 -56
  65. data/sig/generated/quo/composed_relation_backed_query.rbs +25 -0
  66. data/sig/generated/quo/composing/base_strategy.rbs +16 -0
  67. data/sig/generated/quo/composing/class_strategy.rbs +38 -0
  68. data/sig/generated/quo/composing/class_strategy_registry.rbs +16 -0
  69. data/sig/generated/quo/composing/query_classes_strategy.rbs +24 -0
  70. data/sig/generated/quo/composing.rbs +40 -0
  71. data/sig/generated/quo/engine.rbs +1 -0
  72. data/sig/generated/quo/minitest/helpers.rbs +12 -0
  73. data/sig/generated/quo/preloadable.rbs +1 -0
  74. data/sig/generated/quo/query.rbs +15 -4
  75. data/sig/generated/quo/relation_backed_query.rbs +15 -5
  76. data/sig/generated/quo/relation_backed_query_specification.rbs +47 -39
  77. data/sig/generated/quo/relation_results.rbs +1 -0
  78. data/sig/generated/quo/results.rbs +11 -0
  79. data/sig/generated/quo/rspec/helpers.rbs +12 -0
  80. data/sig/generated/quo/testing/collection_backed_fake.rbs +1 -0
  81. data/sig/generated/quo/testing/fake_helpers.rbs +14 -0
  82. data/sig/generated/quo/testing/relation_backed_fake.rbs +1 -0
  83. data/sig/generated/quo/wrapped_collection_backed_query.rbs +13 -0
  84. data/sig/generated/quo/wrapped_relation_backed_query.rbs +13 -0
  85. data/sig/generated/quo.rbs +1 -0
  86. data/website/.gitignore +6 -0
  87. data/website/.nojekyll +0 -0
  88. data/website/404.html +26 -0
  89. data/website/Gemfile +24 -0
  90. data/website/_config.yml +50 -0
  91. data/website/_data/navigation.yml +8 -0
  92. data/website/_data/sidebar.yml +2 -0
  93. data/website/_data/social_links.yml +3 -0
  94. data/website/_docs/api.md +261 -0
  95. data/website/_docs/get-started.md +289 -0
  96. data/website/assets/quo.png +0 -0
  97. data/website/index.md +141 -0
  98. metadata +70 -13
  99. data/gemfiles/rails_7.0.gemfile +0 -15
  100. data/gemfiles/rails_7.1.gemfile +0 -15
  101. data/gemfiles/rails_7.2.gemfile +0 -15
data/lib/quo/results.rb CHANGED
@@ -3,6 +3,7 @@
3
3
  # rbs_inline: enabled
4
4
 
5
5
  module Quo
6
+ # Base results wrapper providing enumeration with optional transformation
6
7
  class Results
7
8
  def empty? #: bool
8
9
  !exists?
@@ -23,6 +24,23 @@ module Quo
23
24
  page_count
24
25
  end
25
26
 
27
+ FILTER_METHODS = %i[
28
+ select filter find_all reject
29
+ find detect
30
+ take_while drop_while
31
+ sort_by min_by max_by
32
+ uniq
33
+ ].to_set.freeze
34
+
35
+ PAIR_FILTER_METHODS = %i[partition minmax_by].to_set.freeze
36
+
37
+ PASSTHROUGH_METHODS = %i[
38
+ any? all? none? one? include? member?
39
+ count tally sum
40
+ each_with_object inject reduce
41
+ map collect flat_map collect_concat filter_map
42
+ ].to_set.freeze
43
+
26
44
  # @rbs &block: (untyped, *untyped) -> untyped
27
45
  # @rbs return: Hash[untyped, Array[untyped]]
28
46
  def group_by(&block)
@@ -45,16 +63,20 @@ module Quo
45
63
  return super unless respond_to_missing?(method)
46
64
 
47
65
  if block
48
- @configured_query.send(method, *args, **kwargs) do |*block_args|
66
+ raw = @configured_query.send(method, *args, **kwargs) do |*block_args|
49
67
  x = block_args.first
50
68
  transformed = transform? ? @transformer.call(x) : x
51
69
  other_args = block_args[1..] || []
52
70
  block.call(transformed, *other_args)
53
71
  end
72
+ return raw if PASSTHROUGH_METHODS.include?(method)
73
+ return transform_pair(raw) if PAIR_FILTER_METHODS.include?(method)
74
+ return transform_results(raw) if FILTER_METHODS.include?(method)
75
+ raw
54
76
  else
55
77
  raw = @configured_query.send(method, *args, **kwargs)
56
- # FIXME: consider how to handle applying a transformer to a Enumerator...
57
78
  return raw if raw.is_a?(Quo::RelationResults) || raw.is_a?(::Enumerator)
79
+ return raw if PASSTHROUGH_METHODS.include?(method)
58
80
  transform_results(raw)
59
81
  end
60
82
  end
@@ -85,5 +107,12 @@ module Quo
85
107
  @transformer.call(results)
86
108
  end
87
109
  end
110
+
111
+ # @rbs pair: untyped
112
+ # @rbs return: untyped
113
+ def transform_pair(pair)
114
+ return pair unless transform?
115
+ pair.map { |part| transform_results(part) }
116
+ end
88
117
  end
89
118
  end
@@ -1,40 +1,29 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ # rbs_inline: enabled
4
+
3
5
  require_relative "../testing/collection_backed_fake"
4
6
  require_relative "../testing/relation_backed_fake"
7
+ require_relative "../testing/fake_helpers"
5
8
 
6
9
  module Quo
7
10
  module Rspec
11
+ # Test helpers for stubbing query objects in RSpec
8
12
  module Helpers
9
- def fake_query(query_class, with: nil, results: [], total_count: nil, page_count: nil, &block)
10
- # make it so that results of instances of this class return a fake Result object
11
- # of the right type which returns the results passed in
12
- if query_class < Quo::CollectionBackedQuery
13
- klass = Class.new(Quo::Testing::CollectionBackedFake) do
14
- if query_class < Quo::Preloadable
15
- include Quo::Preloadable
13
+ include Quo::Testing::FakeHelpers
16
14
 
17
- def query
18
- collection
19
- end
20
- end
21
- end
22
- fake = ->(*kwargs) {
23
- klass.new(results: results, total_count: total_count, page_count: page_count)
24
- }
25
- expectation = allow(query_class).to receive(:new)
26
- expectation = expectation.with(with) if with
27
- expectation.and_invoke(fake)
28
- elsif query_class < Quo::RelationBackedQuery
29
- fake = ->(*kwargs) {
30
- Quo::Testing::RelationBackedFake.new(results: results, total_count: total_count, page_count: page_count)
31
- }
32
- expectation = allow(query_class).to receive(:new)
33
- expectation = expectation.with(with) if with
34
- expectation.and_invoke(fake)
35
- else
15
+ def fake_query(query_class, with: nil, results: [], total_count: nil, page_count: nil, &block)
16
+ unless query_class < Quo::Query
36
17
  raise ArgumentError, "Not a Query class: #{query_class}"
37
18
  end
19
+
20
+ klass = build_fake_class(query_class)
21
+ fake = ->(*kwargs) {
22
+ klass.new(results: results, total_count: total_count, page_count: page_count)
23
+ }
24
+ expectation = allow(query_class).to receive(:new)
25
+ expectation = expectation.with(with) if with
26
+ expectation.and_invoke(fake)
38
27
  end
39
28
  end
40
29
  end
@@ -4,6 +4,7 @@
4
4
 
5
5
  module Quo
6
6
  module Testing
7
+ # Test helper for creating fake collection-backed queries with predefined results
7
8
  class CollectionBackedFake < Quo.collection_backed_query_base_class
8
9
  prop :results, _Any, reader: false
9
10
  prop :page_count, _Nilable(Integer), reader: false
@@ -0,0 +1,30 @@
1
+ # frozen_string_literal: true
2
+
3
+ # rbs_inline: enabled
4
+
5
+ module Quo
6
+ module Testing
7
+ # Shared helpers for creating fake query objects in tests
8
+ module FakeHelpers
9
+ private
10
+
11
+ # @rbs query_class: Class
12
+ # @rbs return: Class
13
+ def build_fake_class(query_class)
14
+ if query_class < Quo::CollectionBackedQuery
15
+ Class.new(Quo::Testing::CollectionBackedFake) do
16
+ if query_class < Quo::Preloadable
17
+ include Quo::Preloadable
18
+
19
+ def query
20
+ collection
21
+ end
22
+ end
23
+ end
24
+ else
25
+ Quo::Testing::RelationBackedFake
26
+ end
27
+ end
28
+ end
29
+ end
30
+ end
@@ -4,6 +4,7 @@
4
4
 
5
5
  module Quo
6
6
  module Testing
7
+ # Test helper for creating fake relation-backed queries with predefined results
7
8
  class RelationBackedFake < Quo.relation_backed_query_base_class
8
9
  prop :results, _Any, reader: false
9
10
  prop :page_count, _Nilable(Integer), reader: false
data/lib/quo/version.rb CHANGED
@@ -3,5 +3,5 @@
3
3
  # rbs_inline: enabled
4
4
 
5
5
  module Quo
6
- VERSION = "1.0.0.beta2"
6
+ VERSION = "2.0.0"
7
7
  end
@@ -0,0 +1,21 @@
1
+ # frozen_string_literal: true
2
+
3
+ # rbs_inline: enabled
4
+
5
+ module Quo
6
+ class WrappedCollectionBackedQuery < Quo.collection_backed_query_base_class
7
+ # @rbs!
8
+ # @wrapped: Enumerable[untyped]
9
+ prop :wrapped, Enumerable, writer: false
10
+
11
+ # @rbs override
12
+ def collection
13
+ wrapped
14
+ end
15
+
16
+ # @rbs override
17
+ def inspect
18
+ "#{self.class.name}[#{wrapped.class.name}]"
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,21 @@
1
+ # frozen_string_literal: true
2
+
3
+ # rbs_inline: enabled
4
+
5
+ module Quo
6
+ class WrappedRelationBackedQuery < Quo.relation_backed_query_base_class
7
+ # @rbs!
8
+ # @wrapped: ActiveRecord::Relation
9
+ prop :wrapped, ::ActiveRecord::Relation, writer: false
10
+
11
+ # @rbs override
12
+ def query
13
+ wrapped
14
+ end
15
+
16
+ # @rbs override
17
+ def inspect
18
+ "#{self.class.name}[#{wrapped.klass.name}]"
19
+ end
20
+ end
21
+ end
data/lib/quo.rb CHANGED
@@ -4,7 +4,9 @@
4
4
 
5
5
  require_relative "quo/version"
6
6
  require "quo/engine"
7
+ require "literal"
7
8
 
9
+ # Query object library for ActiveRecord with composable queries and pagination
8
10
  module Quo
9
11
  extend ActiveSupport::Autoload
10
12
 
@@ -16,7 +18,13 @@ module Quo
16
18
  autoload :RelationResults
17
19
  autoload :CollectionResults
18
20
  autoload :ComposedQuery
21
+ autoload :ComposedInstance
22
+ autoload :ComposedRelationBackedQuery
23
+ autoload :ComposedCollectionBackedQuery
24
+ autoload :WrappedRelationBackedQuery
25
+ autoload :WrappedCollectionBackedQuery
19
26
  autoload :CollectionBackedQuery
27
+ autoload :Composing
20
28
 
21
29
  mattr_accessor :relation_backed_query_base_class, default: "Quo::RelationBackedQuery"
22
30
  mattr_accessor :collection_backed_query_base_class, default: "Quo::CollectionBackedQuery"
data/quo.png ADDED
Binary file
@@ -1,11 +1,17 @@
1
1
  # Generated from lib/quo/collection_backed_query.rb with RBS::Inline
2
2
 
3
3
  module Quo
4
+ # Query object backed by in-memory collections
4
5
  class CollectionBackedQuery < Query
5
- # Wrap an enumerable collection or a block that returns an enumerable collection
6
- # @rbs data: untyped, props: Symbol => untyped, block: () -> untyped
6
+ # @rbs data: Enumerable[untyped] | Quo::CollectionBackedQuery
7
+ # @rbs props: Hash[Symbol, untyped]
8
+ # @rbs &block: ? () -> Enumerable[untyped]
7
9
  # @rbs return: Quo::CollectionBackedQuery
8
- def self.wrap: (?untyped data, ?props: untyped) ?{ (?) -> untyped } -> Quo::CollectionBackedQuery
10
+ def self.wrap: (?Enumerable[untyped] | Quo::CollectionBackedQuery data, ?props: Hash[Symbol, untyped]) ?{ () -> Enumerable[untyped] } -> Quo::CollectionBackedQuery
11
+
12
+ # @rbs enumerable: Enumerable[untyped]
13
+ # @rbs return: Quo::WrappedCollectionBackedQuery
14
+ def self.from: (Enumerable[untyped] enumerable) -> Quo::WrappedCollectionBackedQuery
9
15
 
10
16
  # @rbs return: Object & Enumerable[untyped]
11
17
  def collection: () -> (Object & Enumerable[untyped])
@@ -15,7 +21,7 @@ module Quo
15
21
  # @rbs return: Object & Enumerable[untyped]
16
22
  def query: () -> (Object & Enumerable[untyped])
17
23
 
18
- def results: () -> untyped
24
+ def results: () -> Quo::Results
19
25
 
20
26
  # @rbs override
21
27
  def relation?: ...
@@ -1,6 +1,7 @@
1
1
  # Generated from lib/quo/collection_results.rb with RBS::Inline
2
2
 
3
3
  module Quo
4
+ # Results wrapper for collection-backed queries providing pagination and counting
4
5
  class CollectionResults < Results
5
6
  # @rbs override
6
7
  def initialize: ...
@@ -0,0 +1,25 @@
1
+ # Generated from lib/quo/composed_collection_backed_query.rb with RBS::Inline
2
+
3
+ module Quo
4
+ class ComposedCollectionBackedQuery
5
+ include ComposedInstance
6
+
7
+ @left: Quo::Query | Enumerable[untyped]
8
+
9
+ @right: Quo::Query | Enumerable[untyped]
10
+
11
+ @merge_joins: Symbol | Hash[untyped, untyped] | Array[untyped] | nil
12
+
13
+ # @rbs override
14
+ def collection: ...
15
+
16
+ # @rbs override
17
+ def inspect: ...
18
+
19
+ private
20
+
21
+ # @rbs operand: untyped
22
+ # @rbs return: String
23
+ def operand_desc: (untyped operand) -> String
24
+ end
25
+ end
@@ -0,0 +1,61 @@
1
+ # Generated from lib/quo/composed_instance.rb with RBS::Inline
2
+
3
+ module Quo
4
+ module ComposedInstance
5
+ # @rbs **overrides: untyped
6
+ # @rbs return: Quo::Query
7
+ def copy: (**untyped overrides) -> Quo::Query
8
+
9
+ private
10
+
11
+ # @rbs prop_name: Symbol
12
+ # @rbs value: untyped
13
+ # @rbs return: Quo::Query
14
+ def fan_override: (Symbol prop_name, untyped value) -> Quo::Query
15
+
16
+ # @rbs return: Array[Symbol]
17
+ def own_property_names: () -> Array[Symbol]
18
+
19
+ # @rbs operand: untyped
20
+ # @rbs prop_name: Symbol
21
+ # @rbs return: bool
22
+ def operand_accepts?: (untyped operand, Symbol prop_name) -> bool
23
+
24
+ # @rbs operand: untyped
25
+ # @rbs prop_name: Symbol
26
+ # @rbs value: untyped
27
+ # @rbs return: untyped
28
+ def apply_to_operand: (untyped operand, Symbol prop_name, untyped value) -> untyped
29
+
30
+ # @rbs return: ActiveRecord::Relation | Enumerable[untyped]
31
+ def merge_left_and_right: () -> (ActiveRecord::Relation | Enumerable[untyped])
32
+
33
+ # @rbs operand: untyped
34
+ # @rbs return: ActiveRecord::Relation | Enumerable[untyped]
35
+ def unwrap_operand: (untyped operand) -> (ActiveRecord::Relation | Enumerable[untyped])
36
+
37
+ # @rbs left_rel: ActiveRecord::Relation
38
+ # @rbs right_rel: ActiveRecord::Relation
39
+ # @rbs return: ActiveRecord::Relation
40
+ def merge_active_record_relations: (ActiveRecord::Relation left_rel, ActiveRecord::Relation right_rel) -> ActiveRecord::Relation
41
+
42
+ # @rbs rel: untyped
43
+ # @rbs return: bool
44
+ def is_relation?: (untyped rel) -> bool
45
+
46
+ # @rbs lr: untyped
47
+ # @rbs rr: untyped
48
+ # @rbs return: bool
49
+ def both_relations?: (untyped lr, untyped rr) -> bool
50
+
51
+ # @rbs lr: untyped
52
+ # @rbs rr: untyped
53
+ # @rbs return: bool
54
+ def left_relation_right_enumerable?: (untyped lr, untyped rr) -> bool
55
+
56
+ # @rbs lr: untyped
57
+ # @rbs rr: untyped
58
+ # @rbs return: bool
59
+ def left_enumerable_right_relation?: (untyped lr, untyped rr) -> bool
60
+ end
61
+ end
@@ -1,68 +1,39 @@
1
1
  # Generated from lib/quo/composed_query.rb with RBS::Inline
2
2
 
3
3
  module Quo
4
+ # Mixin for queries composed of two child queries
4
5
  module ComposedQuery
5
- # Combine two Query classes into a new composed query class
6
- # Combine two query-like or composeable entities:
7
- # These can be Quo::Query, Quo::ComposedQuery, Quo::CollectionBackedQuery and ActiveRecord::Relations.
8
- # See the `README.md` docs for more details.
9
- # @rbs chosen_superclass: singleton(Quo::RelationBackedQuery | Quo::CollectionBackedQuery)
10
- # @rbs left_query_class: singleton(Quo::Query | ::ActiveRecord::Relation)
11
- # @rbs right_query_class: singleton(Quo::Query | ::ActiveRecord::Relation)
12
- # @rbs joins: untyped
13
- # @rbs return: singleton(Quo::ComposedQuery)
14
- def self?.composer: (untyped chosen_superclass, untyped left_query_class, untyped right_query_class, ?joins: untyped) -> singleton(Quo::ComposedQuery)
15
-
16
- # We can also merge instance of prepared queries
17
- # @rbs left_instance: Quo::Query | ::ActiveRecord::Relation
18
- # @rbs right_instance: Quo::Query | ::ActiveRecord::Relation
19
- # @rbs joins: untyped
20
- # @rbs return: Quo::ComposedQuery
21
- def self?.merge_instances: (Quo::Query | ::ActiveRecord::Relation left_instance, Quo::Query | ::ActiveRecord::Relation right_instance, ?joins: untyped) -> Quo::ComposedQuery
6
+ # Class-level methods shared by every composed query class. Defined once
7
+ # here and extended onto each anon class via the `included` hook below
8
+ # rather than being re-defined on every Class.new in the composer.
9
+ module ClassMethods
10
+ attr_reader _composing_joins: untyped
22
11
 
23
- # @rbs override
24
- def query: ...
12
+ attr_reader _left_specification: untyped
25
13
 
26
- # @rbs override
27
- def inspect: ...
14
+ attr_reader _right_specification: untyped
28
15
 
29
- # @rbs left_query_class: singleton(Quo::Query | ::ActiveRecord::Relation)
30
- # @rbs right_query_class: singleton(Quo::Query | ::ActiveRecord::Relation)
31
- private def self.validate_query_classes: (untyped left_query_class, untyped right_query_class) -> untyped
16
+ attr_reader _left_query: untyped
32
17
 
33
- # @rbs left_query_class: singleton(Quo::Query | ::ActiveRecord::Relation)
34
- # @rbs right_query_class: singleton(Quo::Query | ::ActiveRecord::Relation)
35
- private def self.collect_properties: (untyped left_query_class, untyped right_query_class) -> untyped
18
+ attr_reader _right_query: untyped
36
19
 
37
- private def self.create_composed_class: (untyped chosen_superclass, untyped props) -> untyped
20
+ # @rbs return: String
21
+ def inspect: () -> String
38
22
 
39
- # @rbs klass: Class
40
- # @rbs left_query_class: singleton(Quo::Query | ::ActiveRecord::Relation)
41
- # @rbs right_query_class: singleton(Quo::Query | ::ActiveRecord::Relation)
42
- # @rbs joins: untyped
43
- private def self.assign_query_metadata: (Class klass, untyped left_query_class, untyped right_query_class, untyped joins) -> untyped
23
+ # @rbs operand: Class
24
+ # @rbs return: String
25
+ def quo_operand_desc: (Class operand) -> String
26
+ end
44
27
 
45
- # @rbs left_instance: Quo::Query | ::ActiveRecord::Relation
46
- # @rbs right_instance: Quo::Query | ::ActiveRecord::Relation
47
- private def self.validate_instances: (Quo::Query | ::ActiveRecord::Relation left_instance, Quo::Query | ::ActiveRecord::Relation right_instance) -> untyped
28
+ # @rbs base: Class
29
+ # @rbs return: void
30
+ def self.included: (Class base) -> void
48
31
 
49
- # @rbs relation: ::ActiveRecord::Relation
50
- # @rbs query: Quo::Query
51
- # @rbs joins: untyped
52
- private def self.merge_query_and_relation: (Quo::Query query, ::ActiveRecord::Relation relation, untyped joins) -> untyped
53
-
54
- # @rbs relation: ::ActiveRecord::Relation
55
- # @rbs query: Quo::Query
56
- # @rbs joins: untyped
57
- private def self.merge_relation_and_query: (::ActiveRecord::Relation relation, Quo::Query query, untyped joins) -> untyped
58
-
59
- # @rbs left_query: Quo::Query | ::ActiveRecord::Relation
60
- # @rbs right_query: Quo::Query | ::ActiveRecord::Relation
61
- private def self.merge_query_instances: (Quo::Query | ::ActiveRecord::Relation left_query, Quo::Query | ::ActiveRecord::Relation right_query, untyped joins) -> untyped
32
+ # @rbs override
33
+ def query: ...
62
34
 
63
- # @rbs left_query: Quo::Query | ::ActiveRecord::Relation
64
- # @rbs right_query: Quo::Query | ::ActiveRecord::Relation
65
- private def self.determine_base_class_for_queries: (Quo::Query | ::ActiveRecord::Relation left_query, Quo::Query | ::ActiveRecord::Relation right_query) -> untyped
35
+ # @rbs override
36
+ def inspect: ...
66
37
 
67
38
  private
68
39
 
@@ -86,10 +57,6 @@ module Quo
86
57
  # @rbs return: ActiveRecord::Relation
87
58
  def merge_active_record_relations: (ActiveRecord::Relation left_rel, ActiveRecord::Relation right_rel) -> ActiveRecord::Relation
88
59
 
89
- # @rbs left_rel: ActiveRecord::Relation
90
- # @rbs return: ActiveRecord::Relation
91
- def apply_joins: (ActiveRecord::Relation left_rel) -> ActiveRecord::Relation
92
-
93
60
  # @rbs rel: untyped
94
61
  # @rbs return: bool
95
62
  def is_relation?: (untyped rel) -> bool
@@ -0,0 +1,25 @@
1
+ # Generated from lib/quo/composed_relation_backed_query.rb with RBS::Inline
2
+
3
+ module Quo
4
+ class ComposedRelationBackedQuery
5
+ include ComposedInstance
6
+
7
+ @left: Quo::Query | ActiveRecord::Relation | Enumerable[untyped]
8
+
9
+ @right: Quo::Query | ActiveRecord::Relation | Enumerable[untyped]
10
+
11
+ @merge_joins: Symbol | Hash[untyped, untyped] | Array[untyped] | nil
12
+
13
+ # @rbs override
14
+ def query: ...
15
+
16
+ # @rbs override
17
+ def inspect: ...
18
+
19
+ private
20
+
21
+ # @rbs operand: untyped
22
+ # @rbs return: String
23
+ def operand_desc: (untyped operand) -> String
24
+ end
25
+ end
@@ -0,0 +1,16 @@
1
+ # Generated from lib/quo/composing/base_strategy.rb with RBS::Inline
2
+
3
+ module Quo
4
+ module Composing
5
+ # Base class for all composition strategies
6
+ class BaseStrategy
7
+ # @rbs left: untyped
8
+ # @rbs right: untyped
9
+ # @rbs return: bool
10
+ def applicable?: (untyped left, untyped right) -> bool
11
+
12
+ # @rbs return: untyped
13
+ def compose: () -> untyped
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,38 @@
1
+ # Generated from lib/quo/composing/class_strategy.rb with RBS::Inline
2
+
3
+ module Quo
4
+ module Composing
5
+ # Base class for class composition strategies
6
+ class ClassStrategy < BaseStrategy
7
+ # @rbs left_query_class: Class
8
+ # @rbs right_query_class: Class
9
+ # @rbs return: void
10
+ def validate_query_classes: (Class left_query_class, Class right_query_class) -> void
11
+
12
+ # Collect properties that need to be (re)defined on the composed class.
13
+ # Properties already declared on `chosen_superclass` are inherited via the
14
+ # normal Ruby/Literal class hierarchy and do not need to be re-registered;
15
+ # skipping them avoids the per-prop Literal::Property allocation, schema
16
+ # dup, and `module_eval` of reader/writer source on every Class.new.
17
+ # @rbs chosen_superclass: Class
18
+ # @rbs left_query_class: Class
19
+ # @rbs right_query_class: Class
20
+ # @rbs return: Hash[Symbol, Literal::Property]
21
+ def collect_properties: (Class chosen_superclass, Class left_query_class, Class right_query_class) -> Hash[Symbol, Literal::Property]
22
+
23
+ # @rbs chosen_superclass: Class
24
+ # @rbs props: Hash[Symbol, Literal::Property]
25
+ # @rbs return: Class & Quo::ComposedQuery
26
+ def create_composed_class: (Class chosen_superclass, Hash[Symbol, Literal::Property] props) -> (Class & Quo::ComposedQuery)
27
+
28
+ # @rbs klass: Class
29
+ # @rbs left_query_class: Class
30
+ # @rbs right_query_class: Class
31
+ # @rbs joins: Symbol | Hash[Symbol, untyped] | Array[Symbol | Hash[Symbol, untyped]]?
32
+ # @rbs left_spec: Quo::RelationBackedQuerySpecification?
33
+ # @rbs right_spec: Quo::RelationBackedQuerySpecification?
34
+ # @rbs return: void
35
+ def assign_query_metadata: (Class klass, Class left_query_class, Class right_query_class, Symbol | Hash[Symbol, untyped] | Array[Symbol | Hash[Symbol, untyped]]? joins, Quo::RelationBackedQuerySpecification? left_spec, Quo::RelationBackedQuerySpecification? right_spec) -> void
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,16 @@
1
+ # Generated from lib/quo/composing/class_strategy_registry.rb with RBS::Inline
2
+
3
+ module Quo
4
+ module Composing
5
+ # Registry for class composition strategies
6
+ class ClassStrategyRegistry
7
+ # @rbs return: Array[Quo::Composing::BaseStrategy]
8
+ def strategies: () -> Array[Quo::Composing::BaseStrategy]
9
+
10
+ # @rbs left: Class
11
+ # @rbs right: Class
12
+ # @rbs return: Quo::Composing::BaseStrategy
13
+ def find_strategy: (Class left, Class right) -> Quo::Composing::BaseStrategy
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,24 @@
1
+ # Generated from lib/quo/composing/query_classes_strategy.rb with RBS::Inline
2
+
3
+ module Quo
4
+ module Composing
5
+ # Strategy for composing two Query classes
6
+ class QueryClassesStrategy < ClassStrategy
7
+ # @rbs override
8
+ # @rbs left: Class
9
+ # @rbs right: Class
10
+ # @rbs return: bool
11
+ def applicable?: ...
12
+
13
+ # @rbs override
14
+ # @rbs chosen_superclass: Class
15
+ # @rbs left_query_class: Class
16
+ # @rbs right_query_class: Class
17
+ # @rbs joins: Symbol | Hash[Symbol, untyped] | Array[Symbol | Hash[Symbol, untyped]]?
18
+ # @rbs left_spec: Quo::RelationBackedQuerySpecification?
19
+ # @rbs right_spec: Quo::RelationBackedQuerySpecification?
20
+ # @rbs return: Class & Quo::ComposedQuery
21
+ def compose: ...
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,40 @@
1
+ # Generated from lib/quo/composing.rb with RBS::Inline
2
+
3
+ module Quo
4
+ module Composing
5
+ CLASS_STRATEGY_REGISTRY: untyped
6
+
7
+ # @rbs chosen_superclass: Class
8
+ # @rbs left_query_class: Class
9
+ # @rbs right_query_class: Class
10
+ # @rbs joins: Symbol | Hash[Symbol, untyped] | Array[Symbol | Hash[Symbol, untyped]]?
11
+ # @rbs left_spec: Quo::RelationBackedQuerySpecification?
12
+ # @rbs right_spec: Quo::RelationBackedQuerySpecification?
13
+ # @rbs return: Class & Quo::ComposedQuery
14
+ def self.composer: (Class chosen_superclass, Class left_query_class, Class right_query_class, ?joins: Symbol | Hash[Symbol, untyped] | Array[Symbol | Hash[Symbol, untyped]]?, ?left_spec: Quo::RelationBackedQuerySpecification?, ?right_spec: Quo::RelationBackedQuerySpecification?) -> (Class & Quo::ComposedQuery)
15
+
16
+ # @rbs left_instance: Quo::Query
17
+ # @rbs right_instance: Quo::Query | ActiveRecord::Relation | Object & Enumerable[untyped]
18
+ # @rbs joins: Symbol | Hash[Symbol, untyped] | Array[Symbol | Hash[Symbol, untyped]]?
19
+ # @rbs return: Quo::Query
20
+ def self.merge_instances: (Quo::Query left_instance, Quo::Query | ActiveRecord::Relation | Object & Enumerable[untyped] right_instance, ?joins: Symbol | Hash[Symbol, untyped] | Array[Symbol | Hash[Symbol, untyped]]?) -> Quo::Query
21
+
22
+ # @rbs operand: untyped
23
+ # @rbs return: bool
24
+ private def self.relation_backed?: (untyped operand) -> bool
25
+
26
+ # @rbs left: untyped
27
+ # @rbs right: untyped
28
+ # @rbs return: Array[Integer?]
29
+ private def self.inherited_pagination: (untyped left, untyped right) -> Array[Integer?]
30
+
31
+ # @rbs operand: untyped
32
+ # @rbs return: untyped
33
+ private def self.pagination_source: (untyped operand) -> untyped
34
+
35
+ # @rbs left: untyped
36
+ # @rbs right: untyped
37
+ # @rbs return: Proc?
38
+ private def self.inherited_transformer: (untyped left, untyped right) -> Proc?
39
+ end
40
+ end
@@ -1,6 +1,7 @@
1
1
  # Generated from lib/quo/engine.rb with RBS::Inline
2
2
 
3
3
  module Quo
4
+ # Rails engine for integrating Quo with Rails applications
4
5
  class Engine < ::Rails::Engine
5
6
  end
6
7
  end
@@ -0,0 +1,12 @@
1
+ # Generated from lib/quo/minitest/helpers.rb with RBS::Inline
2
+
3
+ module Quo
4
+ module Minitest
5
+ # Test helpers for stubbing query objects in Minitest
6
+ module Helpers
7
+ include Quo::Testing::FakeHelpers
8
+
9
+ def fake_query: (untyped query_class, ?results: untyped, ?total_count: untyped, ?page_count: untyped) ?{ (?) -> untyped } -> untyped
10
+ end
11
+ end
12
+ end