如何使用YAML读/写?

时间:2014-12-05 11:44:53

标签: ruby

我一直在尝试编写一个通过STDIN处理空格分隔参数的程序。

echo "Add Tom 4111111111111111 $1000" | ruby basicCC.rb
echo "Charge Tom $500" | ruby basicCC.rb
echo "Charge Tom $800" | ruby basicCC.rb

这是我的代码:

load 'creditCard.rb'
require 'yaml'
people = YAML::load_file "settings.yml"
puts people.inspect
data = ARGF.read
puts people

def run(file, people)
  rand_num = Random.rand(9999)
  file.each_line do |line, index|
    line = line.split(' ')
    function = line[0]
    if function == 'Add'
      name, cc, limit = line[1..-1]
      limit = limit[1..-1].to_i
      people[name] = Credit.new(name, cc, limit)
    elsif function == 'Charge'
      name, amount = line[1..-1]
      amount = amount[1..-1].to_i
      if people[name].nil?
        puts "Could not find #{name}"
      else
        people[name].charge(amount)
      end
    elsif function == 'Credit'
      name, amount = line[1..-1]
      amount = amount[1..-1].to_i
      if people[name].nil?
        puts "Could not find #{name}"
      else
        people[name].credit(amount)
      end
    end
    puts people
    File.open("settings.yml", "w") do |file|
      file.write people[name].to_yaml
    end
  end
end

run(data, people)

我无法弄清楚如何编写和读取我的settings.yml。我无法执行"Charge Tom $500",因为没有可读取和编辑的数据。

1 个答案:

答案 0 :(得分:0)

你说你试图从命令行读取空格分隔的参数,然后说问题是你无法读取YAML文件。当你提出一个问题时,重要的是要清楚地知道你想要用这个问题完成什么。如果不这样做会导致投票结果下降和问题被关闭。

您的代码结构不是很好。我会像这样(未经测试的)代码编写它:

require 'yaml'
require_relative 'creditCard.rb'

def process_data(new_data, data_store)

  new_data.each_line do |line, index|

    line = line.split
    function = line.shift

    case function
    when 'Add'

      name, cc, limit = line
      limit = limit[1..-1].to_i
      data_store[name] = Credit.new(name, cc, limit)

    when 'Charge'
      name, amount = line
      amount = amount[1..-1].to_i

      if data_store[name]
        data_store[name].charge(amount)
      else
        puts "Could not find #{name}"
      end

    when 'Credit'

      name, amount = line
      amount = amount[1..-1].to_i

      if data_store[name]
        data_store[name].credit(amount)
      else
        puts "Could not find #{name}"
      end

    end

    puts data_store

    File.write("settings.yml", data_store.to_yaml)

  end
end

people = YAML::load_file "settings.yml"
process_data(ARGF.read, people)

代码中突出的事情:

  • 格式(间距和缩进)不好。代码中需要有空格,这样我们的眼睛和大脑就能更容易地看到逻辑。空格不会降低程序的执行速度,并且在维护代码时会产生很大的不同,所以请将其放入。
  • 如果您正在从同一目录中的单独文件中读取代码,请使用require_relative。 (另外,不要使用camelCase来命名文件,请使用snake_case。这是另一个OfOTThoseReadabilityThings。)
  • 不要调用方法run。使用一个名称来指示它正在或将要返回的内容。在这种情况下,run表示无效,但process_data表示无效。
  • 用于传入数据的参数名称不反映数据是什么,但是这些参数名称加上方法的名称应该为您提供了一个很好的线索。

    process_data(new_data, data_store)
    

    告诉我们的不仅仅是

    run(file, people)
    
  • split(' ')split的作用相同,因此请使用较短的表格。

  • function = line[0]强制您重复访问line[1..-1。而是使用line.shift来清除对line的其他访问。
  • if / elseif / else链条噪音很大。 case / when很好地清理它。

您没有将完整的YAML文件写回磁盘,而是用一个名称的信息覆盖了该文件。我认为这不是你想要的,所以

File.write("settings.yml", data_store.to_yaml)

将重写整个文件,这应该可以解决问题。