Class: Usable::Config

Inherits:
Object
  • Object
show all
Includes:
ConfigMulti, ConfigRegister
Defined in:
lib/usable/config.rb

Overview

Store and manage configuration settings. Keep methods to a minimum since this class relies on method_missing to read and write to the underlying @spec object

Instance Method Summary collapse

Methods included from ConfigMulti

#+

Methods included from ConfigRegister

#add_module, #available_methods, #modules

Constructor Details

#initialize(attributes = {}) ⇒ Config Also known as: marshal_load

TODO:

Maybe keep a list of all attributes (lazy and regular)? e.g @attributes = Set.new attributes.keys.map(&:to_s)

Returns a new instance of Config.



12
13
14
15
# File 'lib/usable/config.rb', line 12

def initialize(attributes = {})
  @spec = OpenStruct.new(attributes)
  @lazy_loads = Set.new
end

Dynamic Method Handling

This class handles dynamic methods through the method_missing method

#method_missing(key, *args, &block) ⇒ Object



62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
# File 'lib/usable/config.rb', line 62

def method_missing(key, *args, &block)
  if block
    @lazy_loads << key
    @spec.define_singleton_method(key, &block)
  else
    # Needs to be a symbol so we can consistently access @lazy_loads
    key = key.to_s.tr('=', '').to_sym
    if args.empty?
      if @spec[key]
        # Cleanup, just in case we loaded it another way (e.g. combining with another usable config)
        @lazy_loads.delete key
      else
        @spec[key] = call_spec_method(key) unless frozen?
      end
      # Define method so we don't hit method missing again
      define_singleton_method(key) { @spec[key] } unless frozen?
      @spec[key]
    else
      @spec[key] = args.first
    end
  end
rescue NoMethodError
  super
end

Instance Method Details

#[](key) ⇒ Object



21
22
23
# File 'lib/usable/config.rb', line 21

def [](key)
  @spec[key]
end

#[]=(key, val) ⇒ Object



25
26
27
# File 'lib/usable/config.rb', line 25

def []=(key, val)
  @spec[key] = val
end

#each(&block) ⇒ Object



29
30
31
# File 'lib/usable/config.rb', line 29

def each(&block)
  @spec.to_h.each(&block)
end

#freezeObject



91
92
93
94
95
# File 'lib/usable/config.rb', line 91

def freeze
  to_h.each { |key, value| define_singleton_method(key) { value } }
  @spec.freeze
  super
end

#include?(key) ⇒ Boolean

Returns:

  • (Boolean)


58
59
60
# File 'lib/usable/config.rb', line 58

def include?(key)
  !!@spec[key] || @lazy_loads.include?(key.to_sym)
end

#inspectObject Also known as: to_s



97
98
99
100
101
102
103
104
# File 'lib/usable/config.rb', line 97

def inspect
  nested, locals = @spec.to_h.partition { |_, value| value.is_a?(Usable::Config) }
  nested.map! { |key, _| [key, '{...}'] }
  locals.concat nested
  locals.map! { |key, v| %(@#{key}=#{v.inspect}) }
  vars = locals.any? ? ' ' + locals.join(', ') : ''
  "<Usable::Config:0x00#{(object_id << 1).to_s(16)}#{vars}>"
end

#merge(other) ⇒ Object



46
47
48
# File 'lib/usable/config.rb', line 46

def merge(other)
  to_h.merge(other)
end

#merge!(other) ⇒ Object

Parameters:

  • other (Hash)

    to update ourselves with



51
52
53
54
55
56
# File 'lib/usable/config.rb', line 51

def merge!(other)
  other.each do |key, val|
    @spec[key] = val
  end
  self
end

#respond_to_missing?(method_name, _private = false) ⇒ Boolean

Returns:

  • (Boolean)


87
88
89
# File 'lib/usable/config.rb', line 87

def respond_to_missing?(method_name, _private = false)
  method_name.to_s.end_with?('=') || @spec.respond_to?(method_name)
end

#specObject



17
18
19
# File 'lib/usable/config.rb', line 17

def spec
  @spec
end

#to_hObject Also known as: to_hash, marshal_dump

Note:

The @spec could already be set in cases where the config was merged with another For example, a usable module defines a default with a block, and when mounting the module the same usable option is overridden as an options hash (usable mod, key: ‘val’)



36
37
38
39
40
# File 'lib/usable/config.rb', line 36

def to_h
  @lazy_loads.each { |key| @spec[key] ||= @spec.public_send(key) }
  @lazy_loads.clear
  @spec.to_h
end