Class: Quo::Query

Inherits:
Literal::Struct show all
Includes:
Literal::Types
Defined in:
lib/quo/query.rb,
sig/generated/quo/query.rbs

Overview

Base class for query objects with pagination and composition support

Direct Known Subclasses

CollectionBackedQuery, RelationBackedQuery

Constant Summary collapse

COERCE_TO_INT =

: (untyped value) -> Integer?

Returns:

  • (Object)
->(value) do #: (untyped value) -> Integer?
  return if value.equal?(Literal::Undefined)
  value&.to_i
end

Class Method Summary collapse

Instance Method Summary collapse

Class Method Details

.compose(right, joins: nil) ⇒ Quo::Query & Quo::ComposedQuery

TODO: put this in a module with the composer and merge_instances methods Compose is aliased as +. Can optionally take joins parameters to add joins on merged relation.

Parameters:

  • right (Quo::Query, ActiveRecord::Relation, Object & Enumerable[untyped])
  • joins: (Symbol, Hash[Symbol, untyped], Array[Symbol | Hash[Symbol, untyped]]) (defaults to: nil)

Returns:



35
36
37
38
39
40
41
42
# File 'lib/quo/query.rb', line 35

def self.compose(right, joins: nil)
  super_class = if self < Quo::CollectionBackedQuery || right < Quo::CollectionBackedQuery
    Quo.collection_backed_query_base_class
  else
    Quo.relation_backed_query_base_class
  end
  Composing.composer(super_class, self, right, joins: joins)
end

.define_props_on_class(klass, props) ⇒ void

This method returns an undefined value.

Helper method to define properties on a dynamically created class

Parameters:

  • klass (Class)
  • props (Hash[Symbol, untyped])


49
50
51
52
53
54
55
56
57
# File 'lib/quo/query.rb', line 49

def self.define_props_on_class(klass, props)
  props.each do |name, property|
    if property.is_a?(Literal::Property)
      klass.prop name, property.type, property.kind, reader: property.reader, writer: property.writer, default: property.default
    else
      klass.prop name, property
    end
  end
end

.inspectvoid

This method returns an undefined value.



11
12
13
# File 'lib/quo/query.rb', line 11

def self.inspect
  "#{name || "(anonymous)"}<#{superclass}>"
end

.to_svoid

This method returns an undefined value.



16
17
18
# File 'lib/quo/query.rb', line 16

def self.to_s
  inspect
end

Instance Method Details

#collection?Boolean

Is this query object loaded data/collection under the hood? (ie not a AR relation)

Returns:

  • (Boolean)


127
128
129
# File 'lib/quo/query.rb', line 127

def collection? #: bool
  is_collection?(configured_query)
end

#configured_queryvoid

This method returns an undefined value.

The configured query is the underlying query with paging



167
168
169
# File 'lib/quo/query.rb', line 167

def configured_query #: void
  raise NoMethodError, "Query objects must define a 'configured_query' method"
end

#copy(**overrides) ⇒ Quo::Query

Parameters:

  • overrides (Object)

Returns:



96
97
98
99
100
# File 'lib/quo/query.rb', line 96

def copy(**overrides)
  self.class.new(**to_h.merge(overrides)).tap do |q|
    q.instance_variable_set(:@__transformer, transformer)
  end
end

#inspectvoid

This method returns an undefined value.



21
22
23
# File 'lib/quo/query.rb', line 21

def inspect
  "#{self.class.name || "(anonymous)"}<#{self.class.superclass} #{paged? ? "" : "not "}paginated>#{super}"
end

#is_collection?(rel) ⇒ Boolean

Parameters:

  • rel (Object)

Returns:

  • (Boolean)


187
188
189
# File 'lib/quo/query.rb', line 187

def is_collection?(rel)
  rel.is_a?(Quo::CollectionBackedQuery) || (rel.is_a?(Enumerable) && !test_relation(rel))
end

#merge(right, joins: nil) ⇒ Quo::ComposedQuery Also known as: +

Compose is aliased as +. Can optionally take joins parameters to add joins on merged relation.

Parameters:

  • right (Quo::Query, ::ActiveRecord::Relation)
  • joins: (Object) (defaults to: nil)

Returns:



106
107
108
# File 'lib/quo/query.rb', line 106

def merge(right, joins: nil)
  Composing.merge_instances(self, right, joins: joins)
end

#next_page_queryQuo::Query

: Quo::Query

Returns:



71
72
73
# File 'lib/quo/query.rb', line 71

def next_page_query #: Quo::Query
  copy(page: page + 1)
end

#offsetInteger

: Integer

Returns:

  • (Integer)


79
80
81
82
83
84
85
86
87
# File 'lib/quo/query.rb', line 79

def offset #: Integer
  per_page = sanitised_page_size
  page_with_default = if page&.positive?
    page
  else
    1
  end
  per_page * (page_with_default - 1)
end

#paged?Boolean

Is this query object paged? (ie is paging enabled)

Returns:

  • (Boolean)


132
133
134
# File 'lib/quo/query.rb', line 132

def paged? #: bool
  page.present?
end

#previous_page_queryQuo::Query

: Quo::Query

Returns:



75
76
77
# File 'lib/quo/query.rb', line 75

def previous_page_query #: Quo::Query
  copy(page: [page - 1, 1].max)
end

#queryQuo::Query, ::ActiveRecord::Relation

Returns a active record query, or a Quo::Query instance

Returns:



90
91
92
# File 'lib/quo/query.rb', line 90

def query #: Quo::Query | ::ActiveRecord::Relation
  raise NotImplementedError, "Query objects must define a 'query' method"
end

#quo_unwrap_unpaginated_query(q) ⇒ Object

Parameters:

  • q (Object)

Returns:

  • (Object)


197
198
199
# File 'lib/quo/query.rb', line 197

def quo_unwrap_unpaginated_query(q)
  q.is_a?(Quo::Query) ? q.unwrap_unpaginated : q
end

#relation?Boolean

Is this query object a ActiveRecord relation under the hood?

Returns:

  • (Boolean)


122
123
124
# File 'lib/quo/query.rb', line 122

def relation? #: bool
  test_relation(configured_query)
end

#sanitised_page_sizeInteger

: Integer

Returns:

  • (Integer)


171
172
173
174
175
176
177
178
179
180
181
182
183
# File 'lib/quo/query.rb', line 171

def sanitised_page_size #: Integer
  if page_size&.positive?
    given_size = page_size.to_i
    max_page_size = Quo.max_page_size || 200
    if given_size > max_page_size
      max_page_size
    else
      given_size
    end
  else
    Quo.default_page_size || 20
  end
end

#test_relation(rel) ⇒ Boolean

Parameters:

  • rel (Object)

Returns:

  • (Boolean)


193
194
195
# File 'lib/quo/query.rb', line 193

def test_relation(rel)
  rel.is_a?(ActiveRecord::Relation)
end

#to_svoid

This method returns an undefined value.



26
27
28
# File 'lib/quo/query.rb', line 26

def to_s
  inspect
end

#transform(&block) ⇒ void

This method returns an undefined value.

Set a block used to transform data after query fetching



116
117
118
119
# File 'lib/quo/query.rb', line 116

def transform(&block)
  @__transformer = block
  self
end

#transform?Boolean

Is this query object transforming results?

Returns:

  • (Boolean)


137
138
139
# File 'lib/quo/query.rb', line 137

def transform? #: bool
  transformer.present?
end

#transformerObject

Returns:

  • (Object)


153
154
155
# File 'lib/quo/query.rb', line 153

def transformer
  @__transformer
end

#underlying_queryvoid

This method returns an undefined value.

The underlying query is essentially the configured query with optional extras setup



162
163
164
# File 'lib/quo/query.rb', line 162

def underlying_query #: void
  raise NoMethodError, "Query objects must define a 'underlying_query' method"
end

#unwrapActiveRecord::Relation

Unwrap the paginated query

Returns:

  • (ActiveRecord::Relation)


142
143
144
# File 'lib/quo/query.rb', line 142

def unwrap #: ActiveRecord::Relation
  configured_query
end

#unwrap_unpaginatedActiveRecord::Relation

Unwrap the un-paginated query

Returns:

  • (ActiveRecord::Relation)


147
148
149
# File 'lib/quo/query.rb', line 147

def unwrap_unpaginated #: ActiveRecord::Relation
  underlying_query
end

#validated_queryObject

Returns:

  • (Object)

Raises:

  • (NoMethodError)


157
158
159
# File 'lib/quo/query.rb', line 157

def validated_query
  raise NoMethodError, "Query objects must define a 'validated_query' method"
end