class SelfishAssociations::AssociationTraverser

Public Class Methods

new(klass) click to toggle source
# File lib/selfish_associations/utils/association_traverser.rb, line 38
def initialize(klass)
  klass.is_a?(::Class) or ::Kernel.raise ::ArgumentError, "Input must be a Class"
  @original = klass
  @associations = []
  reset!
end

Public Instance Methods

associations!(merge: true) click to toggle source

Return associations traversed Default behavior is to return an array of each path (Array of associations) Use argument merge = true to return a Hash where duplicate keys are merged

# File lib/selfish_associations/utils/association_traverser.rb, line 53
def associations!(merge: true)
  merge ? PathMerger.new(@associations).merge : @associations
end
method_missing(method, *args) click to toggle source

Method Missing pattern (reluctantly). Really we could initialize a new at each node and pre-define all methods But this actually seems more lightweight.

# File lib/selfish_associations/utils/association_traverser.rb, line 85
def method_missing(method, *args)
  send(method, *args)
end
reset!() click to toggle source
# File lib/selfish_associations/utils/association_traverser.rb, line 45
def reset!
  @path = []
  @klass = @original
end
send(method, *args) click to toggle source

Check if method is an association or a column If Association, store current node and iterate to the association. If it is a column, return an Arel::Node representing that value Else, raise NoMethodError

# File lib/selfish_associations/utils/association_traverser.rb, line 61
def send(method, *args)
  if @klass.column_names.include?(method.to_s)
    @associations << @path if @path.present?
    node = @klass.arel_table[method]
    reset!
    return node
  elsif @klass.reflect_on_association(method)
    @path << method
    @klass = @klass.reflect_on_association(method).klass
    return self
  elsif @klass.selfish_associations[method].present?
    @path << method
    @klass = @klass.selfish_associations[method].foreign_class
    return self
  else
    message = "No association or field named #{method} found for class #{@klass}"
    reset!
    ::Kernel.raise ::NoMethodError, message
  end
end