mirror of
https://github.com/rails/rails.git
synced 2022-11-09 12:12:34 -05:00
5b47e26732
We had removed the dedicated `MysqlDateTime`, `MysqlJson`, and
`OID::Json` classes in the past (f1a0fa9
, #29666), so legacy YAML
loading has no longer always perfectly compatiblity.
Fortunately, v2 (Rails 5.1 style) YAML doesn't contain type information
in almost all cases (unless serializing object using custom select), so
usually removing dedicated type affects to legacy YAML older than v1
(Rails 5.0 style) YAML only.
This restores legacy YAML compatibility for MySQL with v1 format by
adding the class alias in YAML for `MysqlString` which is most recently
reported about compatibility concern. It also affects to legacy Rails
4.2 style YAML, but 4.2 style YAML had already broken by removing
`MysqlDateTime` over 4 years ago.
162 lines
4.5 KiB
Ruby
162 lines
4.5 KiB
Ruby
# frozen_string_literal: true
|
|
|
|
require "cases/helper"
|
|
require "models/topic"
|
|
require "models/reply"
|
|
require "models/post"
|
|
require "models/author"
|
|
|
|
class YamlSerializationTest < ActiveRecord::TestCase
|
|
fixtures :topics, :authors, :author_addresses, :posts
|
|
|
|
def test_to_yaml_with_time_with_zone_should_not_raise_exception
|
|
with_timezone_config aware_attributes: true, zone: "Pacific Time (US & Canada)" do
|
|
topic = Topic.new(written_on: DateTime.now)
|
|
assert_nothing_raised { topic.to_yaml }
|
|
end
|
|
end
|
|
|
|
def test_roundtrip
|
|
topic = Topic.first
|
|
assert topic
|
|
t = YAML.load YAML.dump topic
|
|
assert_equal topic, t
|
|
end
|
|
|
|
def test_roundtrip_serialized_column
|
|
topic = Topic.new(content: { omg: :lol })
|
|
assert_equal({ omg: :lol }, YAML.load(YAML.dump(topic)).content)
|
|
end
|
|
|
|
def test_psych_roundtrip
|
|
topic = Topic.first
|
|
assert topic
|
|
t = Psych.load Psych.dump topic
|
|
assert_equal topic, t
|
|
end
|
|
|
|
def test_psych_roundtrip_new_object
|
|
topic = Topic.new
|
|
assert topic
|
|
t = Psych.load Psych.dump topic
|
|
assert_equal topic.attributes, t.attributes
|
|
end
|
|
|
|
def test_active_record_relation_serialization
|
|
[Topic.all].to_yaml
|
|
end
|
|
|
|
def test_raw_types_are_not_changed_on_round_trip
|
|
topic = Topic.new(parent_id: "123")
|
|
assert_equal "123", topic.parent_id_before_type_cast
|
|
assert_equal "123", YAML.load(YAML.dump(topic)).parent_id_before_type_cast
|
|
end
|
|
|
|
def test_cast_types_are_not_changed_on_round_trip
|
|
topic = Topic.new(parent_id: "123")
|
|
assert_equal 123, topic.parent_id
|
|
assert_equal 123, YAML.load(YAML.dump(topic)).parent_id
|
|
end
|
|
|
|
def test_new_records_remain_new_after_round_trip
|
|
topic = Topic.new
|
|
|
|
assert topic.new_record?, "Sanity check that new records are new"
|
|
assert YAML.load(YAML.dump(topic)).new_record?, "Record should be new after deserialization"
|
|
|
|
topic.save!
|
|
|
|
assert_not topic.new_record?, "Saved records are not new"
|
|
assert_not YAML.load(YAML.dump(topic)).new_record?, "Saved record should not be new after deserialization"
|
|
|
|
topic = Topic.select("title").last
|
|
|
|
assert_not topic.new_record?, "Loaded records without ID are not new"
|
|
assert_not YAML.load(YAML.dump(topic)).new_record?, "Record should not be new after deserialization"
|
|
end
|
|
|
|
def test_types_of_virtual_columns_are_not_changed_on_round_trip
|
|
author = Author.select("authors.*, count(posts.id) as posts_count")
|
|
.joins(:posts)
|
|
.group("authors.id")
|
|
.first
|
|
dumped = YAML.load(YAML.dump(author))
|
|
|
|
assert_equal 5, author.posts_count
|
|
assert_equal 5, dumped.posts_count
|
|
end
|
|
|
|
def test_a_yaml_version_is_provided_for_future_backwards_compat
|
|
coder = {}
|
|
Topic.first.encode_with(coder)
|
|
|
|
assert coder["active_record_yaml_version"]
|
|
end
|
|
|
|
def test_deserializing_rails_v2_yaml
|
|
topic = YAML.load(yaml_fixture("rails_v2"))
|
|
|
|
assert_not_predicate topic, :new_record?
|
|
assert_equal 1, topic.id
|
|
assert_equal "The First Topic", topic.title
|
|
assert_equal "Have a nice day", topic.content
|
|
end
|
|
|
|
def test_deserializing_rails_v1_mysql_yaml
|
|
topic = YAML.load(yaml_fixture("rails_v1_mysql"))
|
|
|
|
assert_not_predicate topic, :new_record?
|
|
assert_equal 1, topic.id
|
|
assert_equal "The First Topic", topic.title
|
|
assert_equal "Have a nice day", topic.content
|
|
end
|
|
|
|
def test_deserializing_rails_41_yaml
|
|
topic = assert_deprecated do
|
|
YAML.load(yaml_fixture("rails_4_1"))
|
|
end
|
|
|
|
assert_predicate topic, :new_record?
|
|
assert_nil topic.id
|
|
assert_equal "The First Topic", topic.title
|
|
assert_equal({ omg: :lol }, topic.content)
|
|
end
|
|
|
|
def test_deserializing_rails_4_2_0_yaml
|
|
topic = assert_deprecated do
|
|
YAML.load(yaml_fixture("rails_4_2_0"))
|
|
end
|
|
|
|
assert_not_predicate topic, :new_record?
|
|
assert_equal 1, topic.id
|
|
assert_equal "The First Topic", topic.title
|
|
assert_equal("Have a nice day", topic.content)
|
|
end
|
|
|
|
def test_yaml_encoding_keeps_mutations
|
|
author = Author.first
|
|
author.name = "Sean"
|
|
dumped = YAML.load(YAML.dump(author))
|
|
|
|
assert_equal "Sean", dumped.name
|
|
assert_equal author.name_was, dumped.name_was
|
|
assert_equal author.changes, dumped.changes
|
|
end
|
|
|
|
def test_yaml_encoding_keeps_false_values
|
|
topic = Topic.first
|
|
topic.approved = false
|
|
dumped = YAML.load(YAML.dump(topic))
|
|
|
|
assert_equal false, dumped.approved
|
|
end
|
|
|
|
private
|
|
def yaml_fixture(file_name)
|
|
path = File.expand_path(
|
|
"support/yaml_compatibility_fixtures/#{file_name}.yml",
|
|
TEST_ROOT
|
|
)
|
|
File.read(path)
|
|
end
|
|
end
|