module Arlj::Base
Constants
- AGGREGATE_FUNCTIONS
- DIRECTIVE_PATTERN
Public Class Methods
memoize!()
click to toggle source
# File lib/arlj/base.rb, line 3 def self.memoize! require 'memoist' self.extend Memoist self.memoize :arlj_sql, :arlj_aggregate_sql end
Public Instance Methods
arlj(assoc)
click to toggle source
# File lib/arlj/base.rb, line 9 def arlj(assoc) # Example snippet: # LEFT JOIN [assoc] # ON [assoc].source_id = source.id joins(arlj_sql(assoc)) end
arlj_aggregate(assoc, *args)
click to toggle source
Example usage:
arlj_aggregate(other, 'count(*)', 'sum(col)' => target_name)
# File lib/arlj/base.rb, line 19 def arlj_aggregate(assoc, *args) # Example snippet: # LEFT JOIN(SELECT source_id, [func]([column]) AS [target_name] # FROM [assoc] # GROUP BY [assoc].source_id) arlj_aggregate_[assoc] # ON [assoc].source_id = source.id joins(arlj_aggregate_sql(assoc, *args)) end
arlj_aggregate_arel(assoc, *args)
click to toggle source
# File lib/arlj/base.rb, line 38 def arlj_aggregate_arel(assoc, *args) options = args.extract_options! refl = reflect_on_association(assoc) refl_arel = refl.klass.arel_table subq_ar = refl.klass.group(refl_arel[refl.foreign_key]) columns = [refl_arel[refl.foreign_key]] args.each do |arg| columns << parse_directive(refl, assoc, refl_arel, arg) end options.each do |key, value| if directive?(key) columns << parse_directive(refl, assoc, refl_arel, key, value) elsif key.to_s == 'where' subq_ar = subq_ar.send(key, value) else raise "'#{key.inspect} => #{value.inspect}' not recognized" end end subq_arel = subq_ar.arel subq_arel.projections.clear subq_arel = subq_arel.project(columns). as("arlj_aggregate_#{refl.table_name}") arlj_left_join_arel(subq_arel, refl.foreign_key) end
arlj_aggregate_sql(assoc, *args)
click to toggle source
# File lib/arlj/base.rb, line 68 def arlj_aggregate_sql(assoc, *args) arlj_aggregate_arel(assoc, *args).join_sources end
arlj_arel(assoc)
click to toggle source
# File lib/arlj/base.rb, line 29 def arlj_arel(assoc) refl = reflect_on_association(assoc) arlj_left_join_arel(refl.klass.arel_table, refl.foreign_key) end
arlj_sql(assoc)
click to toggle source
# File lib/arlj/base.rb, line 34 def arlj_sql(assoc) arlj_arel(assoc).join_sources end
Private Instance Methods
arel_node(value)
click to toggle source
# File lib/arlj/base.rb, line 110 def arel_node(value) Arel::Nodes::SqlLiteral.new(value) end
arlj_left_join_arel(arel, foreign_key)
click to toggle source
# File lib/arlj/base.rb, line 114 def arlj_left_join_arel(arel, foreign_key) arel_table.join(arel, Arel::Nodes::OuterJoin). on(arel[foreign_key].eq(arel_table[self.primary_key])) end
directive?(check)
click to toggle source
# File lib/arlj/base.rb, line 85 def directive?(check) DIRECTIVE_PATTERN =~ check end
parse_directive(refl, assoc, arel, directive, name=nil)
click to toggle source
# File lib/arlj/base.rb, line 89 def parse_directive(refl, assoc, arel, directive, name=nil) matchdata = DIRECTIVE_PATTERN.match(directive) if matchdata.nil? raise "'#{directive}' not parsable - must be of format 'func(column)'" end func = AGGREGATE_FUNCTIONS[matchdata[1].downcase] if func.nil? raise "'#{matchdata[1]}' not recognized - must be one of #{AGGREGATE_FUNCTIONS.keys}" end if matchdata[2] == '*' column = refl.active_record_primary_key name ||= "#{assoc}_#{func}" else column = matchdata[2] name ||= "#{assoc}_#{func}_#{column}" end arel[column].send(func).as(name) end