class Praxis::Mapper::SelectorGenerator

Generates a set of selectors given a resource and list of resource attributes.

Attributes

selectors[R]

Public Class Methods

new() click to toggle source
# File lib/praxis-mapper/selector_generator.rb, line 7
def initialize
  @selectors = Hash.new do |hash, key|
    hash[key] = {select: Set.new, track: Set.new}
  end
  @seen = Hash.new do |hash, resource|
    hash[resource] = Set.new
  end
end

Public Instance Methods

add(resource, fields) click to toggle source
# File lib/praxis-mapper/selector_generator.rb, line 16
def add(resource, fields)
  return if @seen[resource].include? fields
  @seen[resource] << fields

  fields.each do |name, field|
    map_property(resource, name, field)
  end
end
add_association(resource, name, fields) click to toggle source
# File lib/praxis-mapper/selector_generator.rb, line 50
def add_association(resource, name, fields)
  association = resource.model.associations.fetch(name) do
    raise "missing association for #{resource} with name #{name}"
  end
  associated_resource = resource.model_map[association[:model]]

  case association[:type]
  when :many_to_one
    add_track(resource, name)
    Array(association[:key]).each do |akey|
      add_select(resource, akey)
    end
  when :one_to_many
    add_track(resource, name)
    Array(association[:key]).each do |akey|
      add_select(associated_resource, akey)
    end
  when :many_to_many
    # If we haven't explicitly added the "through" option in the association
    # then we'll assume the underlying ORM is able to fill in the gap. We will
    # simply add the fields for the associated resource below
    if association.key? :through
      head, *tail = association[:through]
      new_fields = tail.reverse.inject(fields) do |thing, step|
        {step => thing}
      end
      return add_association(resource, head, new_fields)
    else
      add_track(resource, name)
    end
  else
    raise "no select applicable for #{association[:type].inspect}"
  end

  unless fields == true
    # recurse into the field
    add(associated_resource,fields)
  end
end
add_property(resource, name, fields) click to toggle source
# File lib/praxis-mapper/selector_generator.rb, line 90
def add_property(resource, name, fields)
  dependencies = resource.properties[name][:dependencies]
  if dependencies
    dependencies.each do |dependency|
      # if dependency includes the name, then map it directly as the field
      if dependency == name
        add_select(resource, name)
      else
        apply_dependency(resource, dependency)
      end
    end
  end

  head, *tail = resource.properties[name][:through]
  return if head.nil?

  new_fields = tail.reverse.inject(fields) do |thing, step|
    {step => thing}
  end

  add_association(resource, head, new_fields)
end
add_select(resource, name) click to toggle source
# File lib/praxis-mapper/selector_generator.rb, line 39
def add_select(resource, name)
  return select_all(resource) if name == :*
  return if selectors[resource.model][:select] == true

  selectors[resource.model][:select] << name
end
add_track(resource, name) click to toggle source
# File lib/praxis-mapper/selector_generator.rb, line 46
def add_track(resource, name)
  selectors[resource.model][:track] << name
end
apply_dependency(resource, dependency) click to toggle source
# File lib/praxis-mapper/selector_generator.rb, line 113
def apply_dependency(resource, dependency)
  case dependency
  when Symbol
    map_property(resource, dependency, {})
  when String
    head, tail = dependency.split('.').collect(&:to_sym)
    raise "String dependencies can not be singular" if tail.nil?

    add_association(resource, head, {tail => true})
  end
end
map_property(resource, name, fields) click to toggle source
# File lib/praxis-mapper/selector_generator.rb, line 29
def map_property(resource, name, fields)
  if resource.properties.key?(name)
    add_property(resource, name, fields)
  elsif resource.model.associations.key?(name)
    add_association(resource, name, fields)
  else
    add_select(resource, name)
  end
end
select_all(resource) click to toggle source
# File lib/praxis-mapper/selector_generator.rb, line 25
def select_all(resource)
  selectors[resource.model][:select] = true
end