Ruby将String隐式转换为Integer(typeError)

Fel*_*Ogg 0 ruby yaml

我正在尝试使用YAML文件,从中读取并向其写入值列表.在第一次运行此脚本时,正确创建了yaml文件,但是在第二次运行时它会抛出一个我不知道要修复的转换TypeError.

db_yml = 'store.yml'

require 'psych'
begin
    if File.exist?(db_yml)
        yml = Psych.load_file(db_yml)
        puts "done load"        

        yml['reminders']['reminder_a'] = [123,456] 
        yml['reminders']['reminder_b'] = [457,635,123]
        File.write(db_yml, Psych.dump(yml) ) 
    else 
      #the file does not exist yet, create an empty one.
        File.write(db_yml, Psych.dump(
        {'reminders' => [
            {'reminder_a'=> [nil]}, 
            {'reminder_b'=> [nil]}
        ]}
  )) #Store
    end
rescue IOError => msg  
  # display the system generated error message  
  puts msg 
end
Run Code Online (Sandbox Code Playgroud)

在第一次运行时生成文件store.yml:

---
reminders:
- reminder_a:
  - 
- reminder_b:
  - 
Run Code Online (Sandbox Code Playgroud)

到现在为止还挺好.但是在第二次运行时,它失败了

done load
yamlstore.rb:23:in `[]=': no implicit conversion of String into Integer (TypeError)
        from yamlstore.rb:23:in `<main>'
Run Code Online (Sandbox Code Playgroud)

你能告诉我哪里出错吗?

Jör*_*tag 6

错误消息表明您正在传递StringRuby期望可隐式转换为的内容Integer.Ruby期望可以隐式转换为a的东西的第一个位置Integer是索引到Array.因此,每当您看到此错误消息时,您可以99%确定您Array使用您认为是Integer但不是的内容索引,或者您正在索引Array您认为是其他内容(很可能是a Hash).(另一种可能性是,你正在尝试做算术用的混合IntegersStrings.)

仅仅因为Ruby是一种动态类型的编程语言并不意味着你不需要关心类型.特别是,YAML是(某种程度上)类型化的序列化格式.

您正在创建的文件类型如下所示:

Map<String, Sequence<Map<String, Sequence<Int | null>>>>
Run Code Online (Sandbox Code Playgroud)

但是,您正在访问它,就好像它是这样输入的:

Map<String, Map<String, Sequence<Int | null>>>
Run Code Online (Sandbox Code Playgroud)

说得更加具体,要创建对应键的值'reminders'作为一个序列(在YAML方面,一个Array在Ruby中的术语)的地图(HashES).Arrays被索引Integers.

但是,您正在使用a索引它String,就好像它是一个Hash.

因此,您需要更改访问值的方式,如下所示:

yml['reminders'][0]['reminder_a'] = [123, 456]
#               ???

yml['reminders'][1]['reminder_b'] = [457,635,123]
#               ???
Run Code Online (Sandbox Code Playgroud)

或者更改初始化文件的方式,如下所示:

File.write(db_yml, Psych.dump(
{ 'reminders' => {
#                ?
    'reminder_a' => [nil],
#  ?                     ?
    'reminder_b' => [nil]
#  ?                     ?
}
Run Code Online (Sandbox Code Playgroud)

以便生成的YAML文档如下所示:

---
reminders:
  reminder_a:
    - 
  reminder_b:
    - 
Run Code Online (Sandbox Code Playgroud)