Class: Praxis::FieldExpander

Inherits:
Object
  • Object
show all
Defined in:
lib/praxis-blueprints/field_expander.rb

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initializeFieldExpander

Returns a new instance of FieldExpander.



11
12
13
14
15
16
17
18
# File 'lib/praxis-blueprints/field_expander.rb', line 11

def initialize
  @stack = Hash.new do |hash, key|
    hash[key] = Set.new
  end
  @history = Hash.new do |hash, key|
    hash[key] = {}
  end
end

Instance Attribute Details

#historyObject (readonly)

Returns the value of attribute history.



9
10
11
# File 'lib/praxis-blueprints/field_expander.rb', line 9

def history
  @history
end

#stackObject (readonly)

Returns the value of attribute stack.



8
9
10
# File 'lib/praxis-blueprints/field_expander.rb', line 8

def stack
  @stack
end

Class Method Details

.expand(object, fields = true) ⇒ Object



4
5
6
# File 'lib/praxis-blueprints/field_expander.rb', line 4

def self.expand(object, fields = true)
  new.expand(object, fields)
end

Instance Method Details

#expand(object, fields = true) ⇒ Object



20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
# File 'lib/praxis-blueprints/field_expander.rb', line 20

def expand(object, fields = true)
  if stack[object].include? fields
    return history[object][fields] if history[object].include? fields
    # We should probably never get here, since we should have a record
    # of the history of an expansion if we're trying to redo it,
    # but we should also be conservative and raise here just in case.
    raise "Circular expansion detected for object #{object.inspect} with fields #{fields.inspect}"
  else
    stack[object] << fields
  end

  result = if object.is_a?(Praxis::View)
             expand_view(object, fields)
           elsif object.is_a? Attributor::Attribute
             expand_type(object.type, fields)
           else
             expand_type(object, fields)
           end

  result
ensure
  stack[object].delete fields
end

#expand_fields(attributes, fields) ⇒ Object

Raises:

  • (ArgumentError)


44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
# File 'lib/praxis-blueprints/field_expander.rb', line 44

def expand_fields(attributes, fields)
  raise ArgumentError, 'expand_fields must be given a block' unless block_given?

  unless fields == true
    attributes = attributes.select do |k, _v|
      fields.key?(k)
    end
  end

  attributes.each_with_object({}) do |(name, dumpable), hash|
    sub_fields = case fields
                 when true
                   true
                 when Hash
                   fields[name] || true
                 end
    hash[name] = yield(dumpable, sub_fields)
  end
end

#expand_type(object, fields = true) ⇒ Object



83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
# File 'lib/praxis-blueprints/field_expander.rb', line 83

def expand_type(object, fields = true)
  unless object.respond_to?(:attributes)
    if object.respond_to?(:member_attribute)
      return expand_with_member_attribute(object, fields)
    else
      return true
    end
  end

  # just include the full thing if it has no attributes
  return true if object.attributes.empty?

  return history[object][fields] if history[object].include? fields

  history[object][fields] = {}
  result = expand_fields(object.attributes, fields) do |dumpable, sub_fields|
    expand(dumpable.type, sub_fields)
  end
  history[object][fields].merge!(result)
end

#expand_view(object, fields = true) ⇒ Object



64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
# File 'lib/praxis-blueprints/field_expander.rb', line 64

def expand_view(object, fields = true)
  history[object][fields] = if object.is_a?(Praxis::CollectionView)
                              []
                            else
                              {}
                            end

  result = expand_fields(object.contents, fields) do |dumpable, sub_fields|
    expand(dumpable, sub_fields)
  end

  if object.is_a?(Praxis::CollectionView)
    history[object][fields] << result
  else
    history[object][fields].merge!(result)
  end
  history[object][fields]
end

#expand_with_member_attribute(object, fields = true) ⇒ Object



104
105
106
107
108
109
110
111
112
113
114
# File 'lib/praxis-blueprints/field_expander.rb', line 104

def expand_with_member_attribute(object, fields = true)
  return history[object][fields] if history[object].include? fields
  history[object][fields] = []

  new_fields = fields.is_a?(Array) ? fields[0] : fields

  result = [expand(object.member_attribute.type, new_fields)]
  history[object][fields].concat(result)

  result
end