Class: Settings::Cursor

Inherits:
DslBuilder
  • Object
show all
Defined in:
lib/iron/settings/cursor.rb

Overview

Cursors handle navigating the settings hierarchy built by our Builder class, allowing getting and setting entry values and inspecting the hierarchy itself.

Instance Method Summary collapse

Constructor Details

#initialize(group, values, context = nil) ⇒ Cursor

Start up our cursor bound to a given group in the settings hierarchy, with the value store holding the values for the current context.



9
10
11
12
13
# File 'lib/iron/settings/cursor.rb', line 9

def initialize(group, values, context = nil)
  @group = group
  @values = values
  @context = context
end

Dynamic Method Handling

This class handles dynamic methods through the method_missing method

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

Look for the next item from our current group pointer, returning a new cursor if the item is a sub-group, or the value of the requested entry if the item is a leaf in the hierarchy tree.



86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
# File 'lib/iron/settings/cursor.rb', line 86

def method_missing(method, *args, &block)
  method = method.to_s
  query = method.ends_with?('?')
  assignment = method.ends_with?('=')
  method.gsub!(/[=\?]+/,'')
  
  # Look up the item
  item = @group.find_item(method)
  if item.nil?
    # Unknown item name, whoops.
    raise RuntimeError.new("Unknown settings group or entry '#{method}' for settings path #{@group.key}")
    
  elsif item.group?
    if query
      # Yes, this group exists
      return true
    else
      # Got asked for another group, so create a new cursor and do the right thing(tm)
      cursor = Settings::Cursor.new(item, @values)
      DslProxy::exec(cursor, &block) if block
      return cursor
    end
    
  elsif item.entry?
    if query
      # Return true if the given item has a non-nil value
      return !item_value(item).nil?
    else
      if args.empty?
        # No args means return the current value (or default if none)
        return item_value(item)
      else
        # With args, we set the current value of the item (if it parses correctly)
        val = Settings.parse(args.first, item.type)
        @values.set_value(item.key, val)
        return args.first
      end
    end
  end
end

Instance Method Details

#[](key, &block) ⇒ Object

Array-like access to the entry value at the specified key



61
62
63
64
65
66
67
68
69
70
71
# File 'lib/iron/settings/cursor.rb', line 61

def [](key, &block)
  item = find_item(key)
  if item.group?
    # Got asked for another group, so create a new cursor and do the right thing(tm)
    cursor = Settings::Cursor.new(item, @values)
    DslProxy::exec(cursor, &block) if block
    cursor
  else
    item_value(item)
  end
end

#[]=(key, val) ⇒ Object

Array-like setter for entry values using the specified key



74
75
76
77
78
79
80
# File 'lib/iron/settings/cursor.rb', line 74

def []=(key, val)
  item = find_item(key)
  if item
    @values.set_value(item.key, Settings.parse(val, item.type))
  end
  val
end

#entry_keys(include_all = true) ⇒ Object

Returns all entry keys at the cursor’s current position, and optionally including all child keys. If the cursor is at a sub-group node, keys will be relative to that node.



24
25
26
27
28
29
30
# File 'lib/iron/settings/cursor.rb', line 24

def entry_keys(include_all = true)
  keys = @group.entries(include_all).collect {|e| e.key }
  unless @group.key.blank?
    keys.collect! {|k| k.gsub(@group.key + '.', '') }
  end
  keys
end

#eval_in_context(text) ⇒ Object

:nodoc:



162
163
164
165
166
# File 'lib/iron/settings/cursor.rb', line 162

def eval_in_context(text) # :nodoc:
  proc = Proc.new {}
  binding = proc.binding
  eval(text, binding)
end

#find_entries(include_all = true) ⇒ Object

Return Settings::Entry items for entries at this cursor level and optionally below it



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

def find_entries(include_all = true)
  @group.entries(include_all)
end

#find_item(key) ⇒ Object

Finds the item (group or entry) in the hierarchy matching the provided relative key. Raises a RuntimeError on unknown keys.



43
44
45
46
47
48
49
50
51
52
53
# File 'lib/iron/settings/cursor.rb', line 43

def find_item(key)
  item = @group
  key = key.to_s
  parts = key.split(/\./)
  until parts.empty?
    item_key = parts.shift
    item = item.find_item(item_key)
    raise RuntimeError.new("Unknown settings group or entry '#{item_key}' in settings path #{[@group.key,key].list_join('.')}") if item.nil?
  end
  item
end

#group_keys(include_all = false) ⇒ Object

Returns all group keys



33
34
35
36
37
38
39
# File 'lib/iron/settings/cursor.rb', line 33

def group_keys(include_all = false)
  keys = @group.entries(include_all).collect {|e| e.key }
  unless @group.key.blank?
    keys.collect! {|k| k.gsub(@group.key + '.', '') }
  end
  keys
end

#item_default_value(item) ⇒ Object

Calculates the default value for an entry, handling callable defaults.



149
150
151
152
153
154
155
156
157
158
159
160
# File 'lib/iron/settings/cursor.rb', line 149

def item_default_value(item)
  return nil if item.group? || item.default.nil?
  if item.default.respond_to?(:call)
    # Callable default, call in context of a root cursor, yielding our context (generally a
    # model instance) to the block.
    val = DslProxy.exec(Cursor.new(root, @values), @context, &(item.default))
    val = Settings.parse(val, item.type)
  else
    val = item.default
  end
  Settings.restore(val, item.type)
end

#item_has_value?(item) ⇒ Boolean

When true, has non-default value set for the given entry

Returns:

  • (Boolean)


135
136
137
138
# File 'lib/iron/settings/cursor.rb', line 135

def item_has_value?(item)
  return false if item.group?
  @values.has_value?(item.key)
end

#item_value(item) ⇒ Object

Calculates the value of the given entry item given the current value store and item default value.



142
143
144
145
146
# File 'lib/iron/settings/cursor.rb', line 142

def item_value(item)
  return item_default_value(item) unless item_has_value?(item)
  val = @values.get_value(item.key)
  Settings.restore(val, item.type)
end

#respond_to_missing?(method, include_private = false) ⇒ Boolean

Counterpart to #method_missing

Returns:

  • (Boolean)


128
129
130
131
132
# File 'lib/iron/settings/cursor.rb', line 128

def respond_to_missing?(method, include_private = false)
  method = method.to_s.gsub(/[=\?]+/,'')
  item = @group.find_item(method)
  return !item.nil?
end

#rootObject

Provides access to the root of the hierarchy, generally not useful during operations… :-)



17
18
19
# File 'lib/iron/settings/cursor.rb', line 17

def root
  @group.root
end