YAML文件范围,将字符串转换为数组,抛出未定义的方法`to_a'

时间:2016-08-01 18:56:41

标签: arrays ruby range yaml

我有一个YAML文件,其中包含一系列范围作为值:

combat_power:
  Bulbasaur: (12.2..1071)
  Ivysaur: (19.5..1632)
  Venusaur: (32.2..2580)
  Charmander: (10.7..955)
  Charmeleon: (18.5..1557)
  Charizard: (32.5..2602)
  Squirtle: (11.4..1008)
  Wartortle: (18.9..1582)
  Blastoise: (31.7..2542)
  Caterpie: (4.3..443)
  Metapod: (4.7..477)
  Butterfree: (17.2..1454)

尝试将这些范围转换为数组时,我收到错误:<main>': undefined method to_a'

我如何尝试这样做非常简单:

require 'yaml'

data = YAML.load_file('./lib/lists/yamls/combat_power.yml')

print 'Enter a name: '
name = gets.chomp.capitalize

new_data = data['combat_power'][name]

puts new_data.to_a

运行时:

Enter a name: Charmeleon
go.rb:10:in `<main>': undefined method `to_a' for "(18.5..1557)":String (NoMetho
dError)
Did you mean?  to_yaml
               to_f
               to_r
               to_i
               to_s
               to_c

我的问题是,当从YAML文件提供范围键时,如何将范围键转换为数组?您可以使用to_a函数将范围转换为数组的任何其他方式,但它似乎不起作用。是否有一个我缺少的简单解决方案,或者不允许在YAML文件中使用范围?

1 个答案:

答案 0 :(得分:1)

一些事情:

  1. Ruby的YAML实现不会在没有明确告知它的情况下反序列化ruby对象。这既是一个安全特性(一些代码对于反序列化很危险),也是一个不太可能完成的任务(如何知道你打算评估什么?)。因此,要将范围字符串转换为实际的Ruby Range对象,您需要eval它:

    require 'yaml'
    
    data = YAML.load_file('./yamls.yaml')
    
    print 'Enter a name: '
    name = gets.chomp.capitalize
    
    new_data = data['combat_power'][name]
    
    puts eval(new_data).class
    # => Range
    puts eval(new_data).to_a
    

    请注意,您应该只显示您明确写入的eval文本 - 来自随机源的eval代码(例如用户输入)可能是一个严重的安全问题。但只要您只是eval您编写的YAML文件中的值,就应该没问题。

  2. Ruby不知道如何枚举一系列花车,因此(17.2..1454).to_a会抛出TypeError。这是因为口译员可能不知道您是想要增加+1+0.1等。我不确定您希望如何解决此问题,因为解决方案将基于您的数据的含义具体。