Class: Quo::RelationBackedQuery
- Inherits:
-
Query
- Object
- Literal::Struct
- Query
- Quo::RelationBackedQuery
- Defined in:
- lib/quo/relation_backed_query.rb,
sig/generated/quo/relation_backed_query.rbs
Overview
Query object backed by ActiveRecord relations
Constant Summary
Constants inherited from Query
Class Method Summary collapse
- .from(relation) ⇒ Quo::WrappedRelationBackedQuery
- .sanitize_sql_for_conditions(conditions) ⇒ String
- .sanitize_sql_parameter(value) ⇒ String
- .sanitize_sql_string(string) ⇒ String
- .wrap(query = nil, props: {}, &block) ⇒ void
Instance Method Summary collapse
-
#configured_query ⇒ ActiveRecord::Relation
The configured query is the underlying query with paging.
- #klass ⇒ untyped?
-
#method_missing(method_name, *args, **kwargs, &block) ⇒ void
Implements a fluent API for query methods This allows methods to be chained like query.where(...).order(...).limit(...).
- #model ⇒ untyped?
- #respond_to_missing?(method_name, include_private = false) ⇒ Boolean
-
#results ⇒ Quo::Results
: Quo::Results.
- #to_collection(total_count: nil) ⇒ Quo::CollectionBackedQuery
-
#to_sql ⇒ String?
Return the SQL string for this query if its a relation type query object.
-
#underlying_query ⇒ ActiveRecord::Relation
The underlying query is essentially the configured query with optional extras setup.
- #validated_query ⇒ Object
-
#with(options = {}) ⇒ Quo::Query
Apply query options using the specification.
-
#with_specification(specification) ⇒ Quo::Query
Apply a query specification to this query.
Methods inherited from Query
#collection?, compose, #copy, define_props_on_class, #inspect, inspect, #is_collection?, #merge, #next_page_query, #offset, #paged?, #previous_page_query, #query, #quo_unwrap_unpaginated_query, #relation?, #sanitised_page_size, #test_relation, #to_s, to_s, #transform, #transform?, #transformer, #unwrap, #unwrap_unpaginated
Dynamic Method Handling
This class handles dynamic methods through the method_missing method
#method_missing(method_name, *args, **kwargs, &block) ⇒ void
This method returns an undefined value.
Implements a fluent API for query methods This allows methods to be chained like query.where(...).order(...).limit(...)
105 106 107 108 109 110 111 112 113 114 115 116 117 |
# File 'lib/quo/relation_backed_query.rb', line 105 def method_missing(method_name, *args, **kwargs, &block) spec = @_specification || RelationBackedQuerySpecification.blank # Check if the method exists in RelationBackedQuerySpecification if spec.respond_to?(method_name) # Call the method on the specification and return a new query with the updated specification updated_spec = spec.method(method_name).call(*args, **kwargs, &block) return with_specification(updated_spec) end # Forward to underlying query if method not found in RelationBackedQuerySpecification super end |
Class Method Details
.from(relation) ⇒ Quo::WrappedRelationBackedQuery
33 34 35 |
# File 'lib/quo/relation_backed_query.rb', line 33 def self.from(relation) Quo::WrappedRelationBackedQuery.new(wrapped: relation) end |
.sanitize_sql_for_conditions(conditions) ⇒ String
39 40 41 |
# File 'lib/quo/relation_backed_query.rb', line 39 def self.sanitize_sql_for_conditions(conditions) ActiveRecord::Base.sanitize_sql_for_conditions(conditions) end |
.sanitize_sql_parameter(value) ⇒ String
51 52 53 |
# File 'lib/quo/relation_backed_query.rb', line 51 def self.sanitize_sql_parameter(value) sanitize_sql_for_conditions(["?", value]) end |
.sanitize_sql_string(string) ⇒ String
45 46 47 |
# File 'lib/quo/relation_backed_query.rb', line 45 def self.sanitize_sql_string(string) sanitize_sql_for_conditions(["'%s'", string]) end |
.wrap(query = nil, props: {}, &block) ⇒ void
This method returns an undefined value.
12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 |
# File 'lib/quo/relation_backed_query.rb', line 12 def self.wrap(query = nil, props: {}, &block) raise ArgumentError, "either a query or a block must be provided" unless query || block if query && !(query.is_a?(::ActiveRecord::Relation) || query.is_a?(Quo::RelationBackedQuery)) raise ArgumentError, "Quo::RelationBackedQuery.wrap requires an ActiveRecord::Relation or a Quo::RelationBackedQuery instance; got #{query.class}. " \ "Use Quo::CollectionBackedQuery.wrap or Quo::CollectionBackedQuery.from for in-memory collections." end klass = Class.new(self) define_props_on_class(klass, props) if block klass.define_method(:query, &block) else klass.define_method(:query) { query } end klass end |
Instance Method Details
#configured_query ⇒ ActiveRecord::Relation
The configured query is the underlying query with paging
149 150 151 152 153 154 |
# File 'lib/quo/relation_backed_query.rb', line 149 def configured_query #: ActiveRecord::Relation q = return q unless paged? q.offset(offset).limit(sanitised_page_size) end |
#klass ⇒ untyped?
42 |
# File 'sig/generated/quo/relation_backed_query.rbs', line 42
def klass: () -> (untyped | nil)
|
#model ⇒ untyped?
40 |
# File 'sig/generated/quo/relation_backed_query.rbs', line 40
def model: () -> (untyped | nil)
|
#respond_to_missing?(method_name, include_private = false) ⇒ Boolean
122 123 124 125 126 |
# File 'lib/quo/relation_backed_query.rb', line 122 def respond_to_missing?(method_name, include_private = false) # Reuse the memoized blank specification rather than allocating a fresh # instance per probe — ActiveRecord's delegation hits respond_to? heavily. RelationBackedQuerySpecification.blank.respond_to?(method_name, include_private) || super end |
#results ⇒ Quo::Results
: Quo::Results
89 90 91 |
# File 'lib/quo/relation_backed_query.rb', line 89 def results #: Quo::Results Quo::RelationResults.new(self, transformer: transformer) end |
#to_collection(total_count: nil) ⇒ Quo::CollectionBackedQuery
85 86 87 |
# File 'lib/quo/relation_backed_query.rb', line 85 def to_collection(total_count: nil) Quo.collection_backed_query_base_class.wrap(results.to_a).new(total_count:) end |
#to_sql ⇒ String?
Return the SQL string for this query if its a relation type query object
94 95 96 |
# File 'lib/quo/relation_backed_query.rb', line 94 def to_sql #: String? configured_query.to_sql if relation? end |
#underlying_query ⇒ ActiveRecord::Relation
The underlying query is essentially the configured query with optional extras setup
137 138 139 140 141 142 143 144 145 146 |
# File 'lib/quo/relation_backed_query.rb', line 137 def #: ActiveRecord::Relation rel = quo_unwrap_unpaginated_query(validated_query) # Apply specification if it exists if @_specification @_specification.apply_to(rel) else rel end end |
#validated_query ⇒ Object
130 131 132 133 134 |
# File 'lib/quo/relation_backed_query.rb', line 130 def validated_query query.tap do |q| raise ArgumentError, "#query must return an ActiveRecord Relation or a Quo::Query instance" unless query.nil? || q.is_a?(::ActiveRecord::Relation) || q.is_a?(Quo::Query) end end |
#with(options = {}) ⇒ Quo::Query
Apply query options using the specification
72 73 74 75 |
# File 'lib/quo/relation_backed_query.rb', line 72 def with( = {}) spec = @_specification || RelationBackedQuerySpecification.blank with_specification(spec.merge()) end |
#with_specification(specification) ⇒ Quo::Query
Apply a query specification to this query
65 66 67 |
# File 'lib/quo/relation_backed_query.rb', line 65 def with_specification(specification) copy(_specification: specification) end |