简体   繁体   中英

Why does this only return the first setting?

I started looking into Ruby and thought I'd build something; I started writing a simple configuration file parser in it. The simple principle is that you feed it a properly formatted file, and it spits out a hash of the settings. For example, this is a config file:

localhost: 4000;
auto: true;

and this is what it gives back:

{"localhost" => "4000", "auto" => "true"}

Now, I have got it to work when this is entered directly with the following code:

  def spit_direct(input = "", *args)
    spat = Hash.new
    args.each do |arg|
      if input.include? arg
        strip = input.match(/#{arg}:\s(\w*);/)
        spat[arg] = strip[1]
      else
        # error message
        break
      end
    end
    spat
  end

  spit_direct("localhost: 4000; auto: true;", "localhost", "auto")
  # => {"localhost"=>"4000", "auto"=>"true"}

This works as I want it to however I though it would be better if an actual file could be fed. I came up with the following code however it only seems to return the first setting, and not the second one:

  def spit_file(input = "", *args)
    spat = Hash.new
    args.each do |arg|
      File.open(input).each_line do |line|
        if line.include? arg
          strip = line.match(/#{arg}:\s(\w*);/)
          spat[arg] = strip[1]
        else
          # error message
          break
        end
      end
    end
    spat
  end

If I feed it a file called config.cnfg with the same contents as the above couple of setting files, like so:

spit_file("(path)/config.cnfg", "localhost", "auto")

It only returns:

# => {"localhost"=>"4000"}

Why is that? I've spent couple of hours on it last night but can't seem to figure out what the problem.

You're doing it wrong. For each arg in args, you open the file again, and if the first line of this file matches the arg, then the hash gets updated, and then the file gets closed, otherwise, the file gets closed immediately.

Invert the loops nesting:

def spit_file(input = "", *args)
  spat = Hash.new
  File.open(input).each_line do |line|
    args.each do |arg|
      if line.include? arg
        strip = line.match(/#{arg}:\s(\w*);/)
        spat[arg] = strip[1]
      end
    end
  end
  spat
end


1.9.3p327 :001 > spit_file('cfg.cfg', 'localhost', 'auto')
 => {"localhost"=>"4000", "auto"=>"true"}

Your code would work without that break statement. It breaks out of the args.each loop and not the each_line loop. The first time a line does not have the exact arg that you are on, the loop breaks. You should use a next statement instead.

def spit_file(input = "", *args)
    spat = Hash.new
    args.each do |arg|
      File.open(input).each_line do |line|
        if line.include? arg
          strip = line.match(/#{arg}:\s(\w*);/)
          spat[arg] = strip[1]
        else
          # error message
          next
        end
      end
    end
    spat
  end

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM