1

RangeRails コンテキストで、YAML を使用してruby​​ をシリアライズする必要があります。整数の範囲と文字列の範囲が正しくシリアル化されているかどうかを確認したかったのです。

これが私のテストでした:

# classic irb
require 'yaml'         # => true
YAML::VERSION          # => "0.60"
YAML.dump(1..2)        # => "--- !ruby/range \nbegin: 1\nend: 2\nexcl: false\n"
YAML.dump("1".."2")    # => "--- !ruby/range \nbegin: \"1\"\nend: \"2\"\nexcl: false\n"

2 つの出力は厳密に区別されているので、先に進み、Rails アプリケーション内でコーディングしました。

しかし、Rails コンテキスト内では、Ruby は整数の範囲を適切にシリアライズする方法を忘れているようです!

# ./script/rails console
Rails::VERSION::STRING # => "3.0.15"
RUBY_VERSION           # => "1.8.7"
YAML::VERSION          # => "0.60"
YAML.dump(1..2)        # => "--- !ruby/range\n  begin: 1\n  end: 2\n  excl: false"
YAML.dump("1".."2")    # => "--- !ruby/range\n  begin: 1\n  end: 2\n  excl: false"
# The two outputs are identical, the distinction between integers and strings is lost!

ruby と ruby​​ on rails はどちらも同じバージョンの YAML ライブラリを使用しているようです。誤解がなければ、私のバージョンの Ruby は複数のコーダー エンジン間の切り替えをサポートしていません。

いくつかの質問を聞きたいんです:

  1. この違いの原因は何ですか?
  2. この問題は、新しいバージョンのruby ​​/ railsで発生しますか?
  3. どうすれば互換性のある方法で適切に修正できますか?

ご協力ありがとうございました。

4

1 に答える 1

0

範囲は Ruby 内部のものであり、整数や文字列のような YAML 基本型ではありません。範囲をそのままエンコードするのではなく、その開始点と終了点を使用して、受信側で範囲を再構築します。

私は次のようなものを使用します:

[1] (pry) main: 0> range = 0..1
=> 0..1
[2] (pry) main: 0> require 'yaml'
=> true
[3] (pry) main: 0> YAML.dump(range)
=> "--- !ruby/range\nbegin: 0\nend: 1\nexcl: false\n"
[4] (pry) main: 0> YAML.dump({'min' => range.min, 'max' => range.max})
=> "---\nmin: 0\nmax: 1\n"

そして、次のようなものを使用して、受信側で範囲を再作成できます。

Range.new(*YAML.load(YAML.dump({'min' => range.min, 'max' => range.max})).values)
=> 0..1

または、これがわからない場合は、正しい順序になります'min''max'

[19] (pry) main: 0> Range.new(*YAML.load(YAML.dump({'min' => range.min, 'max' => range.max})).values_at('min', 'max'))
=> 0..1

文字の範囲をシリアライズするRuby 1.9.3+に関するいくつかの情報を追加します:

[2] (pry) main: 0> range = '0'..'1'
=> "0".."1"
[3] (pry) main: 0> YAML.dump(range)
=> "--- !ruby/range\nbegin: '0'\nend: '1'\nexcl: false\n"

[5] (pry) main: 0> RUBY_VERSION
=> "1.9.3"

そして再び1.9.2+で:

[2] (pry) main: 0> range = '0'..'1'
=> "0".."1"
[3] (pry) main: 0> YAML.dump(range)
=> "--- !ruby/range \nbegin: \"0\"\nend: \"1\"\nexcl: false\n"
[4] (pry) main: 0> RUBY_VERSION
=> "1.9.2"

また、回避策は範囲の開始/終了タイプを維持します。

[6] (pry) main: 0> Range.new(*YAML.load(YAML.dump({'min' => range.min, 'max' => range.max})).values_at('min', 'max'))
=> "0".."1"

どちらの場合も、YAML_VERSION は0.60.

于 2012-07-09T19:30:13.273 に答える