Ya config file parser

I'm wondering how to extend the config-yaml parser at
http://www.mjijackson.com/2010/02/flexible-ruby-config-objects so I can
write to the file through the variable.

right now it works like this:

yaml_data = "

···

---
database: mydb
auth:
  user: myuser
  pass: mypass
"

require 'yaml'
config = Config.new(YAML.load(yaml_data))

config.auth.user # "myuser"

and I want to add some magic so I can do this instead:

config = Config.new(yaml_filename_variable)
config.a = "test"
p config.a
=> "test"
config.write()
config = nil
config = Config.new(yaml_filename_variable)
p config-a
=> "test"

to load the file on new(), I changed the class like this:

require 'yaml'

class ConfigYaml

  def initialize(file)
    if file.nil?? then
      yaml_conf = YAML.load_file(file)
    end
    @data = case yaml_conf.nil?
      when true then YAML.load_file(file)
      else {}
    end
    update!(data)
  end

private
...
--
Posted via http://www.ruby-forum.com/.

Roberto Cm wrote:

to load the file on new(), I changed the class like this:

require 'yaml'

class ConfigYaml

  def initialize(file)
    if file.nil?? then
      yaml_conf = YAML.load_file(file)
    end
    @data = case yaml_conf.nil?
      when true then YAML.load_file(file)
      else {}
    end
    update!(data)
  end

That looks a bit broken - 'data' is a local variable or method, which
you don't seem to have, which is different from @data which is an
instance variable.

You could try this as a starting point:

class ConfigYaml
  def initialize(file)
    @filename = file
    load
  end

  def load
    @data = YAML.load_file(@filename)
  rescue Errno::ENOENT
    @data = {}
  end

  def save
    File.open(@filename,"w") { |f| f.write YAML.dump(@data) }
  end

  ... rest as before
end

···

--
Posted via http://www.ruby-forum.com/\.

Brian Candler wrote:

That looks a bit broken - 'data' is a local variable or method, which
you don't seem to have, which is different from @data which is an
instance variable.

yea it's a typo. Thanks for the rescue though! --

  rescue Errno::ENOENT

-- The problem with the save method is .. well actually nothing, I need
that too :slight_smile: But I want to not have to explicitly call save, and instead
have the object detect changes and behave dynamically -- ie, assignment
to the config instance should write directly to disk as well as to the
attribute during the set_x methods.

But how do I change setter methods that don't exist yet?

···

--
Posted via http://www.ruby-forum.com/\.

Roberto Cm wrote:

-- The problem with the save method is .. well actually nothing, I need
that too :slight_smile: But I want to not have to explicitly call save, and instead
have the object detect changes and behave dynamically -- ie, assignment
to the config instance should write directly to disk as well as to the
attribute during the set_x methods.

But how do I change setter methods that don't exist yet?

I don't see what you mean. You are defining the = method yourself, so
you can make it do whatever you like, including call 'save'. It doesn't
matter if you define the = method first, or the save method first.
What matters is whether the method exists *at the time it is called*.

If you are subclassing you can use super:

class AutoSaveConfig < ConfigYAML
  def =(*args)
    super
    save
  end
end

If you are monkey-patching (overriding code in an existing class without
modifying the original source file) you can use alias:

class ConfigYAML
  alias :old_set :=
  def =(*args)
    old_set(*args)
    save
  end
end

Note: the class name "Config" (in the original code) is not a good
choice, because Ruby has its own Config class, commonly used when
building extensions.

require 'rbconfig'
puts Config::CONFIG['libdir']

···

--
Posted via http://www.ruby-forum.com/\.