Class: Praxis::Mapper::SelectorGenerator

Inherits:
Object
  • Object
show all
Defined in:
lib/praxis-mapper/selector_generator.rb

Overview

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

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initializeSelectorGenerator

Returns a new instance of SelectorGenerator.



7
8
9
10
11
12
13
14
# 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

Instance Attribute Details

#selectorsObject (readonly)

Returns the value of attribute selectors.



5
6
7
# File 'lib/praxis-mapper/selector_generator.rb', line 5

def selectors
  @selectors
end

Instance Method Details

#add(resource, fields) ⇒ Object



16
17
18
19
20
21
22
23
# 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) ⇒ Object



50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
# 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) ⇒ Object



90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
# 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) ⇒ Object



39
40
41
42
43
44
# 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) ⇒ Object



46
47
48
# File 'lib/praxis-mapper/selector_generator.rb', line 46

def add_track(resource, name)
  selectors[resource.model][:track] << name
end

#apply_dependency(resource, dependency) ⇒ Object



113
114
115
116
117
118
119
120
121
122
123
# 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) ⇒ Object



29
30
31
32
33
34
35
36
37
# 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) ⇒ Object



25
26
27
# File 'lib/praxis-mapper/selector_generator.rb', line 25

def select_all(resource)
  selectors[resource.model][:select] = true
end