0

I'm using YAML in ruby (1.9.3) to dump and load options used by the application.

The path for the file is stored in a constant in a constants.rb file that gets loaded by the main executable for the app. The options are loaded as a Options class which directly inherits from hash (class Options < Hash).

When I try to load the YAML saved in the options file, I get a SystemStackError: stack too deep (in irb from workspace.rb:80 or from the command line to_ruby.rb:306).

I will put the code for the class below. Glad to have any comments. Thanks

class Options < Hash
  attr_reader :path, :default_content

  def initialize
    @path = LOG_DIR + '/options.yml'
    @default_content = { auto: true, cbz: true, is_set_up: false }

    if File.exists?( @path )
      self.merge!( YAML.load( File.read( @path ) ) )
    else
      load_default
    end
  end

  def update( key, value )
    if self.has_key?( key )
      self[key] = value
      File.open( @path, 'w' ).write( YAML.dump( self ) )
    else
      puts 'That key does not exist'
    end
  end

  def load_default
    # load default options
    self.merge!( @default_content )
  end
end

Options.new

Here is the yaml that is trying to be loaded:

--- !ruby/hash:Options
:auto: true
:cbz: true
:is_set_up: true
4

1 回答 1

0

Remove this:

--- !ruby/hash:Options

Leaving this:

:auto: true
:cbz: true
:is_set_up: true

That line is a serialized instance of the Options class, and having the Options class load an instance of itself in its initializer is a recipe for stack explosions.

This should get things working:

def update( key, value )
  if self.has_key?( key )
    self[key] = value
    File.open( @path, 'w' ) do |f|
      f.write( to_h.to_yaml )
    end
  else
    puts 'That key does not exist'
  end
end

to_h.to_yaml writes the hash out as YAML. Also, using the block form of File.open ensures the file is closed at the end of the block.

于 2013-09-01T15:12:35.343 回答