Class: AppQuery::Result

Inherits:
ActiveRecord::Result
  • Object
show all
Defined in:
lib/app_query.rb

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(columns, rows, overrides = nil, cast: false) ⇒ Result

Returns a new instance of Result.



162
163
164
165
166
167
# File 'lib/app_query.rb', line 162

def initialize(columns, rows, overrides = nil, cast: false)
  super(columns, rows, overrides)
  @cast = cast
  # Rails v6.1: prevent mutate on frozen object on #first
  @hash_rows = [] if columns.empty?
end

Instance Attribute Details

#castObject Also known as: cast?

Returns the value of attribute cast.



159
160
161
# File 'lib/app_query.rb', line 159

def cast
  @cast
end

Class Method Details

.from_ar_result(r, cast = nil) ⇒ Object



246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
# File 'lib/app_query.rb', line 246

def self.from_ar_result(r, cast = nil)
  if r.empty?
    r.columns.empty? ? EMPTY : new(r.columns, [], r.column_types)
  else
    cast &&= case cast
    when Array
      r.columns.zip(cast).to_h
    when Hash
      cast.transform_keys(&:to_s).transform_values { |v| resolve_cast_type(v) }
    else
      {}
    end
    if !cast || (cast.empty? && r.column_types.empty?)
      # nothing to cast
      new(r.columns, r.rows, r.column_types)
    else
      overrides = (r.column_types || {}).merge(cast)
      rows = r.cast_values(overrides)
      # One column is special :( ;(
      # > ActiveRecord::Base.connection.select_all("select array[1,2]").rows
      # => [["{1,2}"]]
      # > ActiveRecord::Base.connection.select_all("select array[1,2]").cast_values
      # => [[1, 2]]
      rows = rows.zip if r.columns.one?
      new(r.columns, rows, overrides, cast: true)
    end
  end
end

.resolve_cast_type(value) ⇒ Object

Resolves a cast type value, converting symbols to ActiveRecord types.

Examples:

resolve_cast_type(:date)  #=> ActiveRecord::Type::Date instance
resolve_cast_type(ActiveRecord::Type::Json.new)  #=> returns as-is

Parameters:

  • value (Symbol, Object)

    the cast type (symbol shorthand or type instance)

Returns:

  • (Object)

    the resolved type instance



237
238
239
240
241
242
243
244
# File 'lib/app_query.rb', line 237

def self.resolve_cast_type(value)
  case value
  when Symbol
    ActiveRecord::Type.lookup(value)
  else
    value
  end
end

Instance Method Details

#column(name = nil, unique: false) ⇒ Array

Note:

If you only need a single column, prefer Q#column which selects only that column from the database, avoiding fetching all columns.

Returns an array of values for a single column.

Examples:

Get values by column name

result.column(:name)        # => ["Alice", "Bob"]
result.column("name")       # => ["Alice", "Bob"]

Get first column (no name)

result.column               # => [1, 2, 3]

Get unique values

result.column(:status, unique: true)  # => ["active", "pending"]

Parameters:

  • name (String, Symbol, nil) (defaults to: nil)

    the column name (nil returns first column)

  • unique (Boolean) (defaults to: false)

    whether to return only unique values

Returns:

  • (Array)

    the column values

Raises:

  • (ArgumentError)

    if the column doesn't exist

See Also:



190
191
192
193
194
195
196
197
198
# File 'lib/app_query.rb', line 190

def column(name = nil, unique: false)
  return [] if empty?
  name = name&.to_s
  unless name.nil? || includes_column?(name)
    raise ArgumentError, "Unknown column #{name.inspect}. Should be one of #{columns.inspect}."
  end
  ix = name.nil? ? 0 : columns.index(name)
  rows.map { _1[ix] }.then { unique ? _1.uniq! : _1 }
end

#sizeObject



200
201
202
# File 'lib/app_query.rb', line 200

def size
  count
end

#transform! {|Hash| ... } ⇒ self

Transforms each record in-place using the provided block.

Examples:

Add a computed field

result = AppQuery[:users].select_all
result.transform! { |r| r.merge("full_name" => "#{r['first']} #{r['last']}") }

Yields:

  • (Hash)

    each record as a hash with indifferent access

Yield Returns:

  • (Hash)

    the transformed record

Returns:

  • (self)

    the result object for chaining



224
225
226
227
# File 'lib/app_query.rb', line 224

def transform!
  @hash_rows = hash_rows.map { |r| yield(r) } unless empty?
  self
end