class Object

Public Class Methods

new(tables) click to toggle source
# File lib/rails_select_on_includes.rb, line 6
def initialize(tables)
  @tables = tables
  @alias_cache = tables.each_with_object({}) { |table,h|
    h[table.node] = table.columns.each_with_object({}) { |column,i|
      i[column.name] = column.alias
    }
  }
  @columns_cache = tables.each_with_object({}) { |table, h|
    h[table.node] = table.columns
    @base_class_node_aliases ||= h[table.node] if table.node.is_a?(ActiveRecord::Associations::JoinDependency::JoinBase)
  }
  @virtual_attributes_names = []
end

Public Instance Methods

add_virtual_attribute(selected_column) click to toggle source
# File lib/rails_select_on_includes.rb, line 60
def add_virtual_attribute(selected_column)
  @base_class_node_aliases << ActiveRecord::Associations::JoinDependency::Aliases::Column.new(selected_column, selected_column)
  @virtual_attributes_names << selected_column
end
exec_queries(&block) click to toggle source
# File lib/rails_select_on_includes.rb, line 116
def exec_queries(&block)
  skip_query_cache_if_necessary do
    @records =
        if eager_loading?
          apply_join_dependency do |relation, join_dependency|
            if ActiveRecord::NullRelation === relation
              []
            else
              relation = join_dependency.apply_column_aliases(relation)
              rows = connection.select_all(relation.arel, "SQL")
              #1 DISTINCTION IS HERE:
              # now we gently mokey-patching existing column aliases with select values
              join_dependency.send(:aliases).update_aliases_to_select_values(values[:select]) unless values[:select].blank?

              join_dependency.instantiate(rows, &block)
            end.freeze
          end
        else
          klass.find_by_sql(arel, &block).freeze
        end

    preload = preload_values
    preload += includes_values unless eager_loading?
    preloader = nil
    preload.each do |associations|
      preloader ||= build_preloader
      preloader.preload @records, associations
    end

    @records.each(&:readonly!) if readonly_value

    @loaded = true
    @records
  end
end
flatten_hash_values( some_hash ) click to toggle source
# File lib/rails_select_on_includes.rb, line 56
def flatten_hash_values( some_hash )
  some_hash.values.map{ |value| value.is_a?(Hash) ? flatten_hash_values( value ) : value }.flatten
end
instantiate(row, aliases, column_types = {}, &block) click to toggle source
# File lib/rails_select_on_includes.rb, line 68
def instantiate(row, aliases, column_types = {}, &block)
  base_klass.instantiate(extract_record(row, aliases), column_types, &block)
end
slice_selected_attr_types( column_types ) click to toggle source
# File lib/rails_select_on_includes.rb, line 51
def slice_selected_attr_types( column_types )
  column_types.slice( *@virtual_attributes_names )
end
update_aliases_to_select_values( select_values ) click to toggle source

valid formats are: 'table_name.column' or 'table_name.column as column_1' will be parsed! distinct on can be used also '(subquery with AS) AS column_1 ' Select with aliased arel function: .select(Comment.arel_table.count.as('comments_count')) Select with aliased arel attirubte: .select(Comment.arel_table.as('column_alias'))

# File lib/rails_select_on_includes.rb, line 24
def update_aliases_to_select_values( select_values )
  return if select_values.blank?
  select_values.each do |sv|

    # if sv is symbol that we assume that its a base table column and it will be aliased and added as usual
    # all we need is some specials joins+select from related tables
    case sv
     when String
        sv.split(/,[\s$]*/).each do |sub_sv|
          if sub_sv[/.+ as .+/i]
            add_virtual_attribute(sub_sv.rpartition(/ as /i).last.strip)
          elsif sub_sv[/.+\s+.+/i]
              add_virtual_attribute(sub_sv.rpartition(/\s+/i).last.strip)
          elsif sub_sv[/.+\.[^\*]+/]
            add_virtual_attribute(sub_sv[/\..+/][1..-1].strip)
          end
        end
      when Arel::Nodes::As
        add_virtual_attribute(sv.right)
      when Arel::Nodes::TableAlias
        add_virtual_attribute(sv.right)
      when Arel::Nodes::Function
        add_virtual_attribute(sv.alias) if sv.alias.present?
    end
  end
end