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