class Card::Query::Join

object representation of Card::Query joins

Constants

JOIN_OPT_KEYS

Attributes

subjoins[RW]

These two manage hierarchy of nested joins

superjoin[RW]

These two manage hierarchy of nested joins

Public Class Methods

new(opts={}) click to toggle source

This example join clause:

cards c LEFT JOIN card_actions ca on c.id = ca.card_id and ca.draft is null

…would translate into the following instance variables on the Join object:

@side = "left"
@from_table = "cards"
@from_alias = "c"
@from_field = "id"
@to_table = "card_actions"
@to_alias = "ca"
@to_field = "card_id"
@conditions = "ca.draft is null"

all of the above can be set directly via opts using the keys with the same name.

Join.new side: "left", from_table: "cards"...

The from and to fields can also be set via :from and :to keys. (see interpret_from_and_to)

You can generally use Symbols in place of Strings where applicable.

# File lib/card/query/join.rb, line 37
def initialize opts={}
  interpret_from_and_to opts
  convert_opts_to_instance_variables opts

  @conditions = Array(@conditions).compact
  @subjoins = []
  register_superjoin
end

Public Instance Methods

left?() click to toggle source
# File lib/card/query/join.rb, line 54
def left?
  side == "LEFT"
end
side() click to toggle source
# File lib/card/query/join.rb, line 46
def side
  if !@side.nil?
    @side.to_s.upcase
  else
    @side = inside_or? ? "LEFT" : nil
  end
end

Private Instance Methods

convert_opts_to_instance_variables(opts) click to toggle source
# File lib/card/query/join.rb, line 112
def convert_opts_to_instance_variables opts
  opts.each do |key, value|
    send "#{key}=", value if value.present? && JOIN_OPT_KEYS.member?(key)
  end
end
dir_error(side, object) click to toggle source
# File lib/card/query/join.rb, line 108
def dir_error side, object
  raise Card::Error::BadQuery, "invalid #{side} option: #{object}"
end
dir_hash(table, table_alias, field=nil) click to toggle source
# File lib/card/query/join.rb, line 92
def dir_hash table, table_alias, field=nil
  hash = { table: table, alias: table_alias }
  hash[:field] = field || :id
  hash
end
dir_hash_for_join(side, object) click to toggle source
# File lib/card/query/join.rb, line 102
def dir_hash_for_join side, object
  raise "to: cannot be Join" if side == :to

  dir_hash object.to_table, object.to_alias
end
dir_hash_for_query(query) click to toggle source
# File lib/card/query/join.rb, line 98
def dir_hash_for_query query
  dir_hash query.table, query.table_alias
end
directional_hash_for_object(side, object) click to toggle source
# File lib/card/query/join.rb, line 81
def directional_hash_for_object side, object
  case object
  when nil              then nil
  when Hash             then object
  when Array            then dir_hash(*object)
  when AbstractQuery    then dir_hash_for_query object
  when Join             then dir_hash_for_join side, object
  else                       dir_error(side, object)
  end
end
inside_or?() click to toggle source
# File lib/card/query/join.rb, line 60
def inside_or?
  from.is_a?(Card::Query) && from.mods[:conj] == "or"
end
interpret_from_and_to(opts) click to toggle source

the options :to and :from can be translated into the full table/alias/field trio.

  • An Array is interpreted in that order (table, alias, field)

  • A Hash expects the keys :table, :alias, and (optionally) :field

  • A table and alias can be inferred from Card::Query or Card::Query::Reference objects.

  • They can also be inferred from a Join object, but only as a :from value

In all cases, if the field is not specified, it is assumed to be :id

# File lib/card/query/join.rb, line 73
def interpret_from_and_to opts
  %i[from to].each do |side|
    directional_hash_for_object(side, opts[side]).map do |key, value|
      opts[:"#{side}_#{key}"] ||= value
    end
  end
end
register_superjoin() click to toggle source
# File lib/card/query/join.rb, line 118
def register_superjoin
  return unless @from.is_a? Join

  @superjoin = @from
  @superjoin.subjoins << self
end