class ActiveRecordExtended::QueryMethods::Select::SelectHelper

Constants

AGGREGATE_ONE_LINERS

Public Class Methods

new(scope) click to toggle source
# File lib/active_record_extended/query_methods/select.rb, line 12
def initialize(scope)
  @scope = scope
end

Public Instance Methods

build_foster_select(*args) click to toggle source
# File lib/active_record_extended/query_methods/select.rb, line 16
def build_foster_select(*args)
  flatten_safely(args).each do |select_arg|
    case select_arg
    when String, Symbol
      select!(select_arg)
    when Hash
      select_arg.each_pair do |alias_name, options_or_column|
        case options_or_column
        when Array
          process_array!(options_or_column, alias_name)
        when Hash
          process_hash!(options_or_column, alias_name)
        else
          select!(options_or_column, alias_name)
        end
      end
    end
  end
end

Private Instance Methods

hash_to_dot_notation(column) click to toggle source

Turn a hash chain into a query statement: Example: hash_to_dot_notation(table_name: :col_name) #=> “table_name.col_name”

# File lib/active_record_extended/query_methods/select.rb, line 65
def hash_to_dot_notation(column)
  case column
  when Hash, Array
    column.to_a.flat_map { |col| hash_to_dot_notation(col) }.join(".")
  when String, Symbol
    /^([[:alpha:]]+)$/.match?(column.to_s) ? double_quote(column) : column
  else
    column
  end
end
process_array!(array_of_options, alias_name) click to toggle source

Assumes that the first element in the array is the source/target column. Example process_array_options!(, :my_alias_name)

#=> SELECT ([:col_name:]) AS "my_alias_name", ...
# File lib/active_record_extended/query_methods/select.rb, line 42
def process_array!(array_of_options, alias_name)
  options = array_of_options.detect { |opts| opts.is_a?(Hash) }
  query   = { __select_statement: array_of_options.first }
  query.merge!(options) unless options.nil?
  process_hash!(query, alias_name)
end
process_hash!(hash_of_options, alias_name) click to toggle source

Processes options that come in as Hash elements Examples: process_hash_options!({ memberships: :price, cast_with: :agg_array_distinct }, :past_purchases)

#=> SELECT (ARRAY_AGG(DISTINCT members.price)) AS past_purchases, ...
# File lib/active_record_extended/query_methods/select.rb, line 53
def process_hash!(hash_of_options, alias_name)
  enforced_options = {
    cast_with: hash_of_options[:cast_with],
    order_by:  hash_of_options[:order_by],
    distinct:  !(!hash_of_options[:distinct])
  }
  query_statement = hash_to_dot_notation(hash_of_options[:__select_statement] || hash_of_options.first)
  select!(query_statement, alias_name, **enforced_options)
end
select!(query, alias_name = nil, **options) click to toggle source

Add's select statement values to the current relation, select statement lists

# File lib/active_record_extended/query_methods/select.rb, line 77
def select!(query, alias_name = nil, **options)
  pipe_cte_with!(query)
  @scope._select!(to_casted_query(query, alias_name, **options))
end
to_casted_query(query, alias_name, **options) click to toggle source

Wraps the query with the requested query method Example:

to_casted_query("memberships.cost", :total_revenue, :sum)
 #=> SELECT (SUM(memberships.cost)) AS total_revenue
# File lib/active_record_extended/query_methods/select.rb, line 86
def to_casted_query(query, alias_name, **options)
  cast_with  = options[:cast_with].to_s.downcase
  order_expr = order_by_expression(options[:order_by])
  distinct   = cast_with.chomp!("_distinct") || options[:distinct] # account for [:agg_name:]_distinct

  case cast_with
  when "array", "true"
    wrap_with_array(query, alias_name)
  when AGGREGATE_ONE_LINERS
    expr         = to_sql_array(query) { |value| group_when_needed(value) }
    casted_query = ::Arel::Nodes::AggregateFunctionName.new(cast_with, expr, distinct).order_by(order_expr)
    nested_alias_escape(casted_query, alias_name)
  else
    alias_name.presence ? nested_alias_escape(query, alias_name) : query
  end
end