Skip to content

Commit

Permalink
Refactor: RecordMarshal#dump use attributes before type cast, RecordM…
Browse files Browse the repository at this point in the history
…arshal#load simplify
  • Loading branch information
OuYangJinTing committed Apr 9, 2020
1 parent 4f661c2 commit e1ccb2d
Show file tree
Hide file tree
Showing 2 changed files with 5 additions and 38 deletions.
41 changes: 4 additions & 37 deletions lib/second_level_cache/record_marshal.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,52 +2,19 @@

module RecordMarshal
class << self
# dump ActiveRecord instace with only attributes.
# ["User",
# {"id"=>30,
# "email"=>"[email protected]",
# "created_at"=>2012-07-25 18:25:57 UTC
# }
# ]

# dump ActiveRecord instance with only attributes before type cast.
def dump(record)
[record.class.name, record.attributes]
[record.class.name, record.attributes_before_type_cast]
end

# load a cached record
def load(serialized, &block)
return unless serialized
# fix issues 19
# fix 2.1.2 object.changed? ActiveRecord::SerializationTypeMismatch: Attribute was supposed to be a Hash, but was a String. -- "{:a=>\"t\", :b=>\"x\"}"
# fix 2.1.4 object.changed? is true
# fix Rails 4.2 is deprecating `serialized_attributes` without replacement to Rails 5 is deprecating `serialized_attributes` without replacement
klass = serialized[0].constantize
attributes = serialized[1]

# for ActiveRecord 5.0.0
klass.columns.each do |c|
name = c.name
cast_type = klass.attribute_types[name]
next unless cast_type.is_a?(::ActiveRecord::Type::Serialized)
coder = cast_type.coder
next if attributes[name].nil? || attributes[name].is_a?(String)
if coder.is_a?(::ActiveRecord::Coders::YAMLColumn)
attributes[name] = coder.dump(attributes[name]) if attributes[name].is_a?(coder.object_class)
elsif coder.is_a?(::ActiveRecord::Store::IndifferentCoder)
# https://github.com/rails/rails/blob/5b14129/activerecord/lib/active_record/store.rb#L179
attributes[name] = coder.dump(attributes[name])
elsif coder == ::ActiveRecord::Coders::JSON
attributes[name] = attributes[name].to_json
end
end

klass.defined_enums.each do |key, value|
attributes[key] = value[attributes[key]] if attributes[key].is_a?(String)
end

klass.instantiate(attributes, &block)
serialized[0].constantize.instantiate(serialized[1], &block)
end

# load multi cached records
def load_multi(serializeds, &block)
serializeds.map { |serialized| load(serialized, &block) }
end
Expand Down
2 changes: 1 addition & 1 deletion test/record_marshal_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ def test_should_dump_active_record_object
dumped = RecordMarshal.dump(@user)
assert dumped.is_a?(Array)
assert_equal "User", dumped[0]
assert_equal @user.attributes, dumped[1]
assert_equal dumped[1], ActiveRecord::Base.connection.select_all(User.where(id: @user.id)).first
end

def test_should_load_active_record_object
Expand Down

0 comments on commit e1ccb2d

Please sign in to comment.