Class: Blacklight::NestedOpenStructWithHashAccess

Inherits:
OpenStructWithHashAccess show all
Defined in:
lib/blacklight/nested_open_struct_with_hash_access.rb

Overview

An OpenStruct refinement that converts any hash-keys into additional instances of NestedOpenStructWithHashAccess

Instance Attribute Summary collapse

Instance Method Summary collapse

Methods inherited from OpenStructWithHashAccess

#deep_transform_values, #reverse_merge, #sort_by, #sort_by!, #to_h, #try

Constructor Details

#initialize(klass, hash = {}) ⇒ NestedOpenStructWithHashAccess

Returns a new instance of NestedOpenStructWithHashAccess.



13
14
15
16
17
18
19
20
21
22
23
24
25
# File 'lib/blacklight/nested_open_struct_with_hash_access.rb', line 13

def initialize(klass, hash = {})
  @nested_class = klass
  value = hash.each_with_object({}) do |(k, v), h|
    h[k] = if v.is_a? Hash
             nested_class.new({ key: k.to_sym }.merge(v))
           else
             v
           end
  end

  super value
  set_default_proc!
end

Dynamic Method Handling

This class handles dynamic methods through the method_missing method

#method_missing(mid, *args, **kwargs, &block) ⇒ Object

Override #method_missing from OpenStruct to ensure the default_proc logic gets triggered.



90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
# File 'lib/blacklight/nested_open_struct_with_hash_access.rb', line 90

def method_missing(mid, *args, **kwargs, &block)
  len = args.length

  res = if mid.to_s.end_with?('!')
          m = mid[0...-1].to_sym
          new_ostruct_member!(m)
          @table[m]
        elsif mid.to_s.end_with?('=')
          m = mid[0...-1].to_sym
          new_ostruct_member!(m)
          @table[m] = args.first
        elsif len.positive? || kwargs.any? || block
          new_ostruct_member!(mid)
          @table[mid] = nested_class.new(key: mid, **(args.first || {}), **kwargs)
        else
          @table[mid]
        end

  block&.call(res)

  res
end

Instance Attribute Details

#nested_classObject (readonly)

Returns the value of attribute nested_class.



9
10
11
# File 'lib/blacklight/nested_open_struct_with_hash_access.rb', line 9

def nested_class
  @nested_class
end

Instance Method Details

#<<(key) ⇒ Object

Add an new key to the object, with a default default



29
30
31
# File 'lib/blacklight/nested_open_struct_with_hash_access.rb', line 29

def << key
  @table[key]
end

#[]=(key, value) ⇒ Object

Add a new key/value to the object; if it’s a Hash, turn it into another NestedOpenStructWithHashAccess



36
37
38
39
40
41
42
# File 'lib/blacklight/nested_open_struct_with_hash_access.rb', line 36

def []=(key, value)
  if value.is_a? Hash
    send "#{key}=", nested_class.new({ key: key.to_sym }.merge(value))
  else
    super
  end
end

#deep_dupObject



63
64
65
# File 'lib/blacklight/nested_open_struct_with_hash_access.rb', line 63

def deep_dup
  self.class.new nested_class, @table.deep_dup
end

#marshal_dumpObject

Before serializing, we need to reset the default proc so it can be serialized appropriately



47
48
49
50
51
52
# File 'lib/blacklight/nested_open_struct_with_hash_access.rb', line 47

def marshal_dump
  h = to_h.dup
  h.default = nil

  [nested_class, h]
end

#marshal_load(x) ⇒ Object

After deserializing, we need to re-add the default proc to the internal hash



57
58
59
60
61
# File 'lib/blacklight/nested_open_struct_with_hash_access.rb', line 57

def marshal_load x
  @nested_class = x.first
  super x.last
  set_default_proc!
end

#merge(other_hash) ⇒ OpenStructWithHashAccess

Merge the values of this OpenStruct with another OpenStruct or Hash

Parameters:

  • other_hash (Hash, #to_h)

Returns:



75
76
77
# File 'lib/blacklight/nested_open_struct_with_hash_access.rb', line 75

def merge other_hash
  self.class.new nested_class, to_h.merge((other_hash if other_hash.is_a? Hash) || other_hash.to_h)
end

#merge!(other_hash) ⇒ OpenStructWithHashAccess

Merge the values of another OpenStruct or Hash into this object

Parameters:

  • other_hash (Hash, #to_h)

Returns:



83
84
85
# File 'lib/blacklight/nested_open_struct_with_hash_access.rb', line 83

def merge! other_hash
  @table.merge!(nested_class, (other_hash if other_hash.is_a? Hash) || other_hash.to_h)
end

#selectObject



67
68
69
# File 'lib/blacklight/nested_open_struct_with_hash_access.rb', line 67

def select(...)
  self.class.new nested_class, to_h.select(...)
end