Class: Micdrop::StructureBuilder

Inherits:
Object
  • Object
show all
Defined in:
lib/micdrop/structure_builder.rb

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(raw_value, parent = nil, exists: true, push_parent: false, parent_key: nil) ⇒ StructureBuilder

Returns a new instance of StructureBuilder.



3
4
5
6
7
8
9
10
# File 'lib/micdrop/structure_builder.rb', line 3

def initialize(raw_value, parent = nil, exists: true, push_parent: false, parent_key: nil)
  @raw_value = raw_value
  @parent = parent
  @exists = exists
  @push_parent = push_parent
  @parent_key = parent_key
  @enforced_types = nil
end

Instance Attribute Details

#existsObject (readonly)

Returns the value of attribute exists.



16
17
18
# File 'lib/micdrop/structure_builder.rb', line 16

def exists
  @exists
end

#parentObject (readonly)

Returns the value of attribute parent.



16
17
18
# File 'lib/micdrop/structure_builder.rb', line 16

def parent
  @parent
end

#raw_valueObject (readonly)

Returns the value of attribute raw_value.



16
17
18
# File 'lib/micdrop/structure_builder.rb', line 16

def raw_value
  @raw_value
end

Class Method Details

.new_blankObject



12
13
14
# File 'lib/micdrop/structure_builder.rb', line 12

def self.new_blank
  StructureBuilder.new nil, nil, exists: false
end

Instance Method Details

#<<(value) ⇒ Object



76
77
78
79
80
81
# File 'lib/micdrop/structure_builder.rb', line 76

def <<(value)
  # x << :something
  enforce_array
  realize
  @raw_value.push value
end

#[](*args) ⇒ Object



18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
# File 'lib/micdrop/structure_builder.rb', line 18

def [](*args)
  if args.empty?
    # x[]
    enforce_array
    StructureBuilder.new nil, self, exists: false, push_parent: true
  elsif args.count == 1
    arg = args.first
    if args.first.is_a?(Integer)
      # x[1]
      enforce_array_or_hash
    else
      # x["thing"]
      enforce_hash
    end
    if @exists && @raw_value.is_a?(Array) && arg.is_a?(Integer) && arg < @raw_value.length && arg >= -@raw_value.length
      StructureBuilder.new @raw_value[arg], self, parent_key: arg
    elsif @exists && @raw_value.is_a?(Hash) && @raw_value.has_key?(arg)
      StructureBuilder.new @raw_value[arg], self, parent_key: arg
    else
      StructureBuilder.new nil, self, exists: false, parent_key: arg
    end
  elsif args.count == 2 && args[0].is_a?(Integer) && args[1].is_a?(Integer)
    # x[3, 7] = :something
    enforce_array
    context[*args] = value
  else
    raise IndexError
  end
end

#[]=(*args) ⇒ Object



48
49
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
# File 'lib/micdrop/structure_builder.rb', line 48

def []=(*args)
  value = args.pop
  if args.empty?
    # x[] = :something
    enforce_array
    realize
    @raw_value.push value
  elsif args.count == 1
    arg = args.first
    if arg.is_a?(Integer)
      # x[1] = :something
      enforce_array_or_hash
    else
      # x["thing"] = :something
      enforce_hash
    end
    realize
    @raw_value[arg] = value
  elsif args.count == 2 && args[0].is_a?(Integer) && args[1].is_a?(Integer)
    # x[3, 7] = :something
    enforce_array
    realize
    @raw_value[*args] = value
  else
    raise IndexError
  end
end

#bury(value, *keys) ⇒ Object

This is intended as an inverse to :dig, automatically assembling structure as needed



85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
# File 'lib/micdrop/structure_builder.rb', line 85

def bury(value, *keys)
  context = self
  last_key = keys.pop
  keys.each do |key|
    context = if key.nil?
                context[]
              else
                context[key]
              end
  end
  if last_key.nil?
    context[] = value
  else
    context[last_key] = value
  end
end

#enforce_arrayObject

Raises:

  • (StandardError)


102
103
104
105
106
107
108
109
110
# File 'lib/micdrop/structure_builder.rb', line 102

def enforce_array
  raise StandardError, "Value is not an array" if @exists && !@raw_value.is_a?(Array)

  @enforced_types = if @enforced_types.nil?
                      [:array]
                    else
                      [:array].intersection @enforced_types
                    end
end

#enforce_array_or_hashObject

Raises:

  • (StandardError)


122
123
124
125
126
127
128
129
130
# File 'lib/micdrop/structure_builder.rb', line 122

def enforce_array_or_hash
  raise StandardError, "Value is not a" if @exists && !(@raw_value.is_a?(Array) || @raw_value.is_a?(Hash))

  @enforced_types = if @enforced_types.nil?
                      %i[array hash]
                    else
                      %i[array hash].intersection @enforced_types
                    end
end

#enforce_hashObject

Raises:

  • (StandardError)


112
113
114
115
116
117
118
119
120
# File 'lib/micdrop/structure_builder.rb', line 112

def enforce_hash
  raise StandardError, "Value is not a" if @exists && !@raw_value.is_a?(Hash)

  @enforced_types = if @enforced_types.nil?
                      [:hash]
                    else
                      [:hash].intersection @enforced_types
                    end
end

#realizeObject



132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
# File 'lib/micdrop/structure_builder.rb', line 132

def realize
  return if @exists

  # First make sure the parent is real
  @parent.realize unless @parent.nil? || @parent.exists

  # Then make ourselves real
  if @enforced_types.nil?
    raise StandardError, "No specified type"
  elsif @enforced_types.empty?
    raise StandardError, "No allowed type"
  else
    case @enforced_types.first
    when :array
      @raw_value = []
    when :hash
      @raw_value = {}
    else
      raise StandardError, "Unknown type: #{@enforced_types.first}"
    end
  end

  unless @parent.nil?
    # Then add ourselves to the parent
    if !@parent_key.nil?
      @parent.raw_value[@parent_key] = @raw_value
    elsif @push_parent
      @parent_key = @parent.raw_value.length
      @parent.raw_value << @raw_value
    else
      raise StandardError, "Use either push_parent or parent_key for non-existing values"
    end
  end

  # And now we're done!
  @exists = true
end