class Blacklight::NestedOpenStructWithHashAccess

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

Attributes

nested_class[R]

Public Class Methods

new(klass, hash = {}) click to toggle source
Calls superclass method
# 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

Public Instance Methods

<<(key) click to toggle source

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

# File lib/blacklight/nested_open_struct_with_hash_access.rb, line 29
def << key
  @table[key]
end
[]=(key, value) click to toggle source

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

Calls superclass method
# 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_dup() click to toggle source
# 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_dump() click to toggle source

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

# 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) click to toggle source

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

Calls superclass method
# 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) click to toggle source

Merge the values of this OpenStruct with another OpenStruct or Hash @param [Hash,#to_h] other_hash @return [OpenStructWithHashAccess] a new instance of an OpenStructWithHashAccess

# 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) click to toggle source

Merge the values of another OpenStruct or Hash into this object @param [Hash,#to_h] other_hash @return [OpenStructWithHashAccess] a new instance of an OpenStructWithHashAccess

# 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
method_missing(mid, *args, **kwargs, &block) click to toggle source

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

# 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
select(...) click to toggle source
# File lib/blacklight/nested_open_struct_with_hash_access.rb, line 67
def select(...)
  self.class.new nested_class, to_h.select(...)
end

Private Instance Methods

set_default_proc!() click to toggle source
# File lib/blacklight/nested_open_struct_with_hash_access.rb, line 115
def set_default_proc!
  self.default_proc = lambda do |hash, key|
    hash[key] = nested_class.new(key: key)
  end
end