Class: Settings

Inherits:
OpenStruct
  • Object
show all
Defined in:
lib/settings.rb

Overview

Settings container, supporting nested settings.

Class Method Summary collapse

Instance Method Summary collapse

Dynamic Method Handling

This class handles dynamic methods through the method_missing method

#method_missing(mth, *args) ⇒ Object



48
49
50
51
52
# File 'lib/settings.rb', line 48

def method_missing(mth, *args)
  # property assignments convert Hashes to Settings
  args = Settings[args] if mth.to_s[-1,1]=='='
  super mth, *args
end

Class Method Details

.[](settings = {}) ⇒ Object

Settings constructor. A hash is passed to define properties

s = Settings[:x=>100, :y=>200]


18
19
20
21
22
23
# File 'lib/settings.rb', line 18

def [](settings={})
  ModalSupport.recursive_map(settings){|v|
    # We keep hashes with keys other than strings/symbols as hashe
    (v.kind_of?(Hash) && !v.keys.detect{|k| !k.respond_to?(:to_sym)}) ? Settings.new(v) : v
  }
end

.load(settings_filename, merge_key = nil) ⇒ Object

Build a Settings from a YAML file defining a properties Hash. The YAML can include ERB macros. An optional second argument defines the name of an attribute to be merge into the top level.



27
28
29
30
31
32
33
34
35
# File 'lib/settings.rb', line 27

def load(settings_filename, merge_key=nil)
  properties = File.exists?(settings_filename) ? YAML.load(ERB.new(File.read(settings_filename)).result(binding)) : {}
  s = Settings[properties]
  if merge_key
    merge_settings = s[merge_key]
    s.merge! merge_settings if merge_settings && merge_settings.kind_of?(Settings)
  end
  s
end

Instance Method Details

#[](k) ⇒ Object

Read a property with Hash syntax (with either a String or Symbol property name)



39
40
41
# File 'lib/settings.rb', line 39

def [](k)
  @table[k.to_sym]
end

#[]=(k, v) ⇒ Object

Write a property with Hash syntax (with either a String or Symbol property name)



44
45
46
# File 'lib/settings.rb', line 44

def []=(k,v)
  @table[k.to_sym] = Settings[v]
end

#collisions(recursive = false) ⇒ Object

Keys that need [] syntax for access (because of collision with defined methods)



97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
# File 'lib/settings.rb', line 97

def collisions(recursive=false)
  unless defined?(@@predefined_keys)
    empty = Settings.new
    # note that private & protected methods do not collide
    @@predefined_keys = (empty.methods).map{|k| k.to_sym}
  end
  keys = @table.keys & @@predefined_keys
  if recursive
    @table.each_pair do |key, value|
      if value.kind_of?(Settings)
        keys += value.collisions(recursive).map{|k| k.kind_of?(Array) ? [key]+k : [key, k]}
      end
    end
  end
  keys
end

#dupObject

Deep copy (in relation to nested Settings; other non-inmediate values (e.g. arrays) are to cloned)



88
89
90
91
92
93
94
# File 'lib/settings.rb', line 88

def dup
  copy = super
  copy.each do |k, v|
    copy[k] = v.dup if v.kind_of?(Settings)
  end
  copy
end

#each(&blk) ⇒ Object

Iterator of key-value pairs.



66
67
68
# File 'lib/settings.rb', line 66

def each(&blk)
  @table.each(&blk)
end

#merge(other) ⇒ Object

Merge with another Settings or Hash object (deeply).



71
72
73
# File 'lib/settings.rb', line 71

def merge(other)
  dup.merge!(other)
end

#merge!(other) ⇒ Object

Merge with another Settings or Hash object mutator (deeply).



76
77
78
79
80
81
82
83
84
85
# File 'lib/settings.rb', line 76

def merge!(other)
  other.each do |k,v|
    if self[k].kind_of?(Settings) && (v.kind_of?(Settings) || v.kind_of?(Hash))
      self[k].merge! v
    else
      self[k] = v
    end
  end
  self
end

#to_hObject

Convert to a hash of properties indexed by symbolic property names. Nested Settings objects are also converted to hash.



56
57
58
# File 'lib/settings.rb', line 56

def to_h
  ModalSupport.recursive_map(self){|s| s.kind_of?(Settings) ? s.instance_variable_get(:@table) : s}
end

#to_yamlObject

A Settings object converts to YAML as a Hash.



61
62
63
# File 'lib/settings.rb', line 61

def to_yaml
  to_h.to_yaml
end