class Settings::Cursor
Cursors handle navigating the settings hierarchy built by our Builder
class, allowing getting and setting entry values and inspecting the hierarchy itself.
Public Class Methods
Start up our cursor bound to a given group in the settings hierarchy, with the value store holding the values for the current context.
# File lib/iron/settings/cursor.rb, line 9 def initialize(group, values, context = nil) @group = group @values = values @context = context end
Public Instance Methods
Array-like access to the entry value at the specified key
# File lib/iron/settings/cursor.rb, line 69 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
Array-like setter for entry values using the specified key
# File lib/iron/settings/cursor.rb, line 82 def []=(key, val) item = find_item(key) if item @values.set_value(item.key, Settings.parse(val, item.type)) end val end
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.
# 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
Returns a hash of all entry keys to their values 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.
# File lib/iron/settings/cursor.rb, line 35 def entry_values(include_all = true) keys = entry_keys(include_all) keys.convert_to_hash {|k| item_value(find_item(k)) } end
Return Settings::Entry
items for entries at this cursor level and optionally below it
# File lib/iron/settings/cursor.rb, line 64 def find_entries(include_all = true) @group.entries(include_all) end
Finds the item (group or entry) in the hierarchy matching the provided relative key. Raises a RuntimeError on unknown keys.
# File lib/iron/settings/cursor.rb, line 51 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
Returns all group keys
# File lib/iron/settings/cursor.rb, line 41 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
Calculates the default value for an entry, handling callable defaults.
# File lib/iron/settings/cursor.rb, line 163 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
When true, has non-default value set for the given entry
# File lib/iron/settings/cursor.rb, line 149 def item_has_value?(item) return false if item.group? @values.has_value?(item.key) end
Calculates the value of the given entry item given the current value store and item default value.
# File lib/iron/settings/cursor.rb, line 156 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
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.
# File lib/iron/settings/cursor.rb, line 94 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. if query # Querying for existence of key is fine if it's missing return false else # Setting or getting, GTFO raise RuntimeError.new("Unknown settings group or entry '#{method}' for settings path #{@group.key}") end 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
Counterpart to method_missing
# File lib/iron/settings/cursor.rb, line 142 def respond_to_missing?(method, include_private = false) method = method.to_s.gsub(/[=\?]+/,'') item = @group.find_item(method) return !item.nil? end
Provides access to the root of the hierarchy, generally not useful during operations… :-)
# File lib/iron/settings/cursor.rb, line 17 def root @group.root end