Created
July 22, 2015 17:54
-
-
Save sikachu/2ab126c4c9a61d94387d to your computer and use it in GitHub Desktop.
YAML Serializer with Syck Fallback
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# Usage | |
class User | |
serialize :data, YAMLColumnWithSyckFallback.new | |
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# lib/yaml_column_with_syck_fallback.rb | |
class YAMLColumnWithSyckFallback | |
def initialize | |
@serializer = ActiveRecord::Coders::YAMLColumn.new | |
end | |
def dump(object) | |
@serializer.dump(object) | |
end | |
def load(yaml) | |
result = @serializer.load(yaml) | |
if result.is_a?(String) | |
result = Syck.load(result) | |
end | |
if yaml =~ /!binary/ | |
Hash[ | |
result.map do |attribute_name, values| | |
[force_encoding(attribute_name.dup), force_encoding(values.dup)] | |
end | |
] | |
else | |
result | |
end | |
end | |
private | |
def force_encoding(string_or_array) | |
if string_or_array.is_a?(Array) | |
string_or_array.map { |value| force_encoding(value) } | |
else | |
if string_or_array.respond_to?(:force_encoding) | |
string_or_array.force_encoding("UTF-8") | |
end | |
end | |
end | |
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# spec/lib/yaml_column_with_syck_fallback_spec.rb | |
require 'spec_helper' | |
describe YAMLColumnWithSyckFallback do | |
let(:serializer) { YAMLColumnWithSyckFallback.new } | |
describe '#dump' do | |
it 'converts data to YAML using serializer' do | |
data = { 'name' => ['John', 'Joe'] } | |
expected_yaml = ActiveRecord::Coders::YAMLColumn.new.dump(data) | |
expect(serializer.dump(data)).to eq expected_yaml | |
end | |
end | |
describe '#load' do | |
context 'when default serializer is able to deserialize the YAML' do | |
it 'does not use Syck to parse the YAML' do | |
allow(Syck).to receive(:load).never | |
yaml = YAML.dump('name' => ['John', 'Joe']) | |
expect(serializer.load(yaml)).to eq('name' => ['John', 'Joe']) | |
end | |
it 'parses change with single value' do | |
yaml = "--- \nname: John" | |
expect(serializer.load(yaml)).to eq('name' => 'John') | |
end | |
it 'parses data into UTF-8 encoding' do | |
yaml = <<-YAML.strip_heredoc | |
--- | |
? !binary "6Kit6KiI5aOr44OR44Oz44OB44Oq44K544OI\n" | |
: | |
- "1" | |
- "0" | |
description: | |
- <no description> | |
- !binary | | |
VGhlIGNhYmxlIGxhZGRlcnMgYXJlIG5vdCBwYWludGVkLCB0aGVpciBzaGFy | |
cCBlZGdlcyBhcmUgbm90IGZpbGVkIHRvIGJlIGZsYXQu55S157yG5qGl5p62 | |
5rKh5pyJ5Za35ryG77yM6ZSL5Yip6L6557yY5Lmf5rKh5pyJ5aSE55CG44CC | |
YAML | |
result = serializer.load(yaml) | |
expect(result.keys[0].encoding).to eq(Encoding::UTF_8) | |
expect(result.keys[1].encoding).to eq(Encoding::UTF_8) | |
expect(result['description'][0].encoding).to eq(Encoding::UTF_8) | |
expect(result['description'][1].encoding).to eq(Encoding::UTF_8) | |
end | |
end | |
context 'when default serializer is unable to deserialize the YAML' do | |
it 'tries to use Syck to parse the YAML' do | |
allow(Syck).to receive(:load).and_call_original | |
yaml = "--- \nNational Grid Ref: \n- \"\"\n- ,jkjhkjhlk\n" | |
expect(serializer.load(yaml)). | |
to eq('National Grid Ref' => ['', ',jkjhkjhlk']) | |
expect(Syck).to have_received(:load) | |
end | |
end | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment