Class: ModCons::Configuration

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

Constant Summary collapse

REQUIRED_METHODS =
["[]", "==", "class", "config_changed", "configure", "declare", 
"initialize", "inspect", "instance_eval", "method_missing", 
"methods", "to_hash", "to_s"]

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(namespace) ⇒ Configuration

Returns a new instance of Configuration.



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

def initialize(namespace)
  @config_changed = []
  @namespace = namespace
  @mode = :access
  @mode_stack = []
  @table = {}
end

Dynamic Method Handling

This class handles dynamic methods through the method_missing method

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



80
81
82
83
84
85
86
87
88
89
# File 'lib/mod_cons.rb', line 80

def method_missing(sym, *args, &block)
  case @mode
  when :declare
    _dispatch_declare(sym, *args, &block)
  when :config
    _dispatch_config(sym, *args, &block)
  else
    _dispatch_access(sym)
  end
end

Class Method Details

.declare(namespace = nil, &block) ⇒ Object



11
12
13
14
15
# File 'lib/mod_cons.rb', line 11

def declare(namespace = nil, &block)
  result = self.new(namespace)
  result.declare(&block)
  return result
end

Instance Method Details

#[](key) ⇒ Object



160
161
162
163
164
165
166
167
# File 'lib/mod_cons.rb', line 160

def [](key)
  result = @table[key.to_sym]
  if result.is_a?(self.class)
    result.to_hash
  else
    result
  end
end

#_dispatch_access(sym) ⇒ Object



72
73
74
75
76
77
78
# File 'lib/mod_cons.rb', line 72

def _dispatch_access(sym)
  if @table.has_key?(sym)
    @table[sym]
  else
    raise NameError, "Unknown configuration option: #{sym}"
  end
end

#_dispatch_config(sym, *args, &block) ⇒ Object



56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
# File 'lib/mod_cons.rb', line 56

def _dispatch_config(sym, *args, &block)
  if @table.has_key?(sym)
    if @table[sym].is_a?(self.class) and (args.length > 0 or block_given?)
      @table[sym].configure(*args, &block)
    elsif args.length == 1
      @table[sym] = args.first
    elsif args.length == 0
      @table[sym]
    else
      raise ArgumentError, "wrong number of arguments (#{args.length} for 1)"
    end
  else
    raise NameError, "Unknown configuration option: #{sym}"
  end
end

#_dispatch_declare(sym, *args, &block) ⇒ Object



41
42
43
44
45
46
47
48
49
50
51
52
53
54
# File 'lib/mod_cons.rb', line 41

def _dispatch_declare(sym, *args, &block)
  unless sym.to_s =~ /^[A-Za-z][A-Za-z0-9_]+$/
    raise NameError, "Invalid configuration option name: #{sym}"
  end
  if @table[sym]
    warn "WARNING: Redeclaring configuration option #{sym}"
  end
  if block_given?
    self.declare(sym, &block)
  else
    @table[sym] = args.first
  end
  return self
end

#_keysObject



169
170
171
# File 'lib/mod_cons.rb', line 169

def _keys
  @table.keys
end

#config_changed(&block) ⇒ Object



120
121
122
123
# File 'lib/mod_cons.rb', line 120

def config_changed(&block)
  @config_changed << block
  return self
end

#configure(hash = nil, &block) ⇒ Object



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

def configure(hash = nil, &block)
  config_signature = self.to_hash
  self._push_mode(:config) do
    if hash
      hash.each_pair do |k,v|
        key = k.to_sym
        unless @table.has_key?(key)
          raise NameError, "Unknown configuration option: #{key}"
        end
  
        if @table[key].is_a?(self.class)
          @table[key].configure(v)
        else
          @table[key] = v
        end
      end
    end
    self.instance_eval(&block) if block_given?
  end
  post_config unless self.to_hash == config_signature
  return self
end

#declare(namespace = nil, &block) ⇒ Object



26
27
28
29
30
31
32
33
34
35
36
37
38
39
# File 'lib/mod_cons.rb', line 26

def declare(namespace = nil, &block)
  result = self
  unless (namespace.nil?)
    ns = namespace.to_sym
    if @table[ns]
      warn "WARNING: Redeclaring configuration namespace #{namespace}"
    end
    result = (@table[ns] ||= self.class.new(ns))
  end
  if block_given?
    result._push_mode(:declare, &block)
  end
  return(result)
end

#inspectObject



182
183
184
185
# File 'lib/mod_cons.rb', line 182

def inspect
  (initial,rest) = @namespace.to_s.split(//,2)
  "#<#{initial.to_s.upcase}#{rest}: {#{_keys.join(', ')}}>"
end

#methodsObject



187
188
189
# File 'lib/mod_cons.rb', line 187

def methods
  super + _keys.collect { |k| k.to_s }
end

#post_configObject



114
115
116
117
118
# File 'lib/mod_cons.rb', line 114

def post_config
  @config_changed.each do |listener|
    listener.call(self)
  end
end

#template(indent = '') ⇒ Object



125
126
127
128
129
130
131
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
# File 'lib/mod_cons.rb', line 125

def template(indent = '')
  result = "#{indent}#{@namespace.to_s}"
  if indent.length == 0
    result << ".configure"
  end
  result << " do\n"
  _keys.sort { |a,b| a.to_s <=> b.to_s }.each do |key|
    value = @table[key]
    display_value = nil
    if value.is_a?(self.class)
      if value._keys.length == 1 and not value[value._keys.first].is_a?(Hash)
        child_key = value._keys.first
        display_value = value[child_key].inspect
        result << "#{indent}  #{key.to_s}.#{child_key}"
      else
        result << value.template("#{indent}  ")
      end
    else
      result << "#{indent}  #{key.to_s}"
      display_value = value.inspect
    end
    
    unless display_value.nil?
      if display_value[0,1] == '{'
        display_value = "(#{display_value})"
      else
        display_value = " #{display_value}"
      end
      result << "#{display_value}\n"
    end
  end
  result << "#{indent}end\n"
  return(result)
end

#to_hashObject



173
174
175
176
177
178
179
180
# File 'lib/mod_cons.rb', line 173

def to_hash
  result = @table.dup
  result.each_pair do |k,v|
    if v.is_a?(self.class)
      result[k] = v.to_hash
    end
  end
end