Ruby - 使用 YAML 解析哈希的字符串 - 如果哈希输入原始并强制转换为字符串而不是作为字符串输入则出错

Ruby - Parsing a string of a Hash using YAML - Error if hash entered raw and coerced to string rather than entered as string

我创建了一个 gem,将 Git 包装为 key:value 商店 (dictionary/hash)。来源是 here.

它在引用的过程中的工作方式如下:

  1. 运行 函数 set 包含一个键和一个值参数
  2. 用 git 散列这些,在散列中有关键点
  3. return 如果此操作成功并且它被添加到全局字典中的键和散列

现在,如果我调用类似

db.set('key', {some: 'value'})
# => 'key'

然后尝试检索这个,

db.get('key')
Psych::SyntaxError: (<unknown>): did not find expected node content while parsing a flow node at line 1 column 2
from /home/bobby/.rvm/rubies/ruby-2.2.1/lib/ruby/2.2.0/psych.rb:370:in `parse'
from /home/bobby/.rvm/rubies/ruby-2.2.1/lib/ruby/2.2.0/psych.rb:370:in `parse_stream'
from /home/bobby/.rvm/rubies/ruby-2.2.1/lib/ruby/2.2.0/psych.rb:318:in `parse'
from /home/bobby/.rvm/rubies/ruby-2.2.1/lib/ruby/2.2.0/psych.rb:245:in `load'
from /home/bobby/.rvm/gems/ruby-2.2.1/gems/gkv-0.2.1/lib/gkv/database.rb:21:in `get'
from (irb):6
from /home/bobby/.rvm/rubies/ruby-2.2.1/bin/irb:11:in `<main>'

现在,如果我将键设置为同一个字典,但设置为字符串:

db.set('key', "{some: 'value'}")
# => 'key'
db.get('key')
# => {"key"=>"value"} 
db.get('key').class
=> Hash

正在执行 git 操作并将它们包装到 kv 存储源的操作是:

...
    def get(key)
      if $ITEMS.keys.include? key
        YAML.load(Gkv::GitFunctions.cat_file($ITEMS[key].last))
      else
        raise KeyError
      end
    end

    def set(key, value)
      update_items(key, value.to_s)
      key
    end
...

此处引用的 get_items 函数的来源是:

...    
  def update_items(key, value)
      if $ITEMS.keys.include? key
        history = $ITEMS[key]
        history << Gkv::GitFunctions.hash_object(value.to_s)
        $ITEMS[key] = history
      else
        $ITEMS[key] = [Gkv::GitFunctions.hash_object(value.to_s)]
      end
    end
  end
...

hash_objectcat_object 简单包装 git hash-objectgit cat-file 方法将输入写入 tmpfile,git adding 它,然后擦除临时文件。

我真的不知道为什么这适用于字符串而不适用于真正的字典。如果您也使用旧的 hashrocket 语法,它会导致完全相同的错误:

db.set('a', {:key => 'value'})
=> "a" 
db.get('a')
# => Psych::SyntaxError: (<unknown>): did not find expected node content while parsing a flow node at line 1 column 2
from /home/bobby/.rvm/rubies/ruby-2.2.1/lib/ruby/2.2.0/psych.rb:370:in `parse'
from /home/bobby/.rvm/rubies/ruby-2.2.1/lib/ruby/2.2.0/psych.rb:370:in `parse_stream'
from /home/bobby/.rvm/rubies/ruby-2.2.1/lib/ruby/2.2.0/psych.rb:318:in `parse'
from /home/bobby/.rvm/rubies/ruby-2.2.1/lib/ruby/2.2.0/psych.rb:245:in `load'
from /home/bobby/.rvm/gems/ruby-2.2.1/gems/gkv-0.2.1/lib/gkv/database.rb:21:in `get'
from (irb):6
from /home/bobby/.rvm/rubies/ruby-2.2.1/bin/irb:11:in `<main>'

有什么想法吗?

在您的 get 方法中您调用 YAML.load,但在您的设置方法中您使用 .to_s。这意味着 YAML 解析器正在尝试读取任意字符串,就好像它是 YAML 一样。为了对称性,YAML.dump 应该在 set 方法中使用。

我已经创建了包含更改的拉取请求。