Class: Ruber::YamlSettingsBackend

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

Overview

Backend for SettingsContainer which writes the options to a YAML file, as a nested hash, where the outer hash contains the groups and each inner hash, which represents a group, contains the options. Here’s an example of the YAML file produced by this class.

:group1: :opt1: value1 :opt2: value2 :opt3: value3 :group2: :opt1: value4 :opt4: value5 :group3: :opt5: value6

Direct Known Subclasses

DocumentProject::Backend

Defined Under Namespace

Classes: InvalidSettingsFile

Instance Method Summary (collapse)

Constructor Details

- (YamlSettingsBackend) initialize(file)

Creates a new YamlSettingsBackend corresponding to the YAML file with name file. If the file exists, it’s parsed and the content is stored internally in a hash. If it doesn’t exist, the object is initialized with a new hash.

If the file exists but isn’t a valid YAML file, or if it doesn’t contain a toplevel hash, InvalidSettingsFile is raised. In this case, however, the object will be fully initialized (with an empty hash) before the exception is raised. This means that a class deriving from YamlSettingsBackend which wants to ignore errors due to an invalid project file can simply do the following:

class CustomSettingsBackend < Ruber::Yaml::SettingsBackend

def initialize file begin super rescue Ruber::YamlSettingsBackend::InvalidSettingsFile end end

end

This way

CustomSettingsBackend.new(‘/path/to/invalid_file’)

will return an option backend fully initialized. (This happens because of how Class.new works: the object is first allocated, then its initialize method is called and the object is returned. If an exception raised by initialize is rescued within the initialize method, Class.new will never notice something went wrong and still return the allocated object)



80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
# File 'lib/ruber/yaml_option_backend.rb', line 80

def initialize file
  @filename = file
  if File.exist? file
    @data = begin YAML.load(File.read(file))
    rescue ArgumentError => e
      @data = {}
      raise InvalidSettingsFile, e.message
    end
    unless @data.is_a? Hash
      @data = {}
      raise InvalidSettingsFile, "The file #{file} isn\'t a valid option file"
    end
  else @data = {}
  end
end

Instance Method Details

- (Object) [](opt)

Returns the option corresponding to opt. opt is an option object with the characteristics specified in SettingsContainer#add_option. If an option with the same name and value of opt isn’t included in the internal hash, the option default value will be returned



110
111
112
113
# File 'lib/ruber/yaml_option_backend.rb', line 110

def [] opt
  grp = @data.fetch(opt.group){return opt.default.deep_copy}
  grp.fetch(opt.name, opt.default)
end

- (Object) compute_data(options) (private)

Creates a hash with the options to be written to file. See write for a more detailed description of how this happens



139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
# File 'lib/ruber/yaml_option_backend.rb', line 139

def compute_data options
  new_data = Hash.new{|h, k| h[k] = {}}
  removed = []
  options.each_pair do |k, v|
    if v != k.default then new_data[k.group][k.name] = v
    else removed << [k.group, k.name]
    end
  end
  @data.each_pair do |grp, data|
    data.each_pair do |opt, val|
      unless removed.include?([grp, opt])
        new_data[grp][opt] ||= val
      end
    end
  end
  new_data
end

- (Object) file

The name of the file associated with the backend. Note that there’s no warranty the file actually exists.



100
101
102
# File 'lib/ruber/yaml_option_backend.rb', line 100

def file
  @filename
end

- (Object) write(options)

Writes the options back to the YAML file (creating it if needed). options is a hash with option objects as keys and the corresponding values as entries. There are two issues to be aware of:

  • if one of the options in options has a value which is equal to its default value, it won’t be written to file
  • options is interpreted as only containing the options which might have changed: any option contained in the internal hash but not in options is written back to the file unchanged.

After having written the new options back to file, the internal hash is updated



127
128
129
130
131
# File 'lib/ruber/yaml_option_backend.rb', line 127

def write options
  new_data = compute_data options
  File.open(@filename, 'w'){|f| f.write YAML.dump(new_data)}
  @data = new_data
end