Merge pull request #846 from airblade/fix_issue_798

Fix enum serialization in rails 4.2
This commit is contained in:
Jared Beck 2016-08-14 21:33:42 -04:00 committed by GitHub
commit 375ae1a060
5 changed files with 31 additions and 6 deletions

View File

@ -14,7 +14,9 @@
### Fixed ### Fixed
- None - [#798](https://github.com/airblade/paper_trail/issues/798) -
Fix a rare bug with serialization of enums in rails 4.2 only when
using `touch_with_version`.
## 5.2.0 (2016-06-27) ## 5.2.0 (2016-06-27)

View File

@ -34,8 +34,13 @@ module PaperTrail
end end
def serialize(attr, val) def serialize(attr, val)
val = defined_enums[attr][val] if defined_enums[attr] castable_val = val
@klass.type_for_attribute(attr).type_cast_for_database(val) if defined_enums[attr]
# `attr` is an enum. Find the number that corresponds to `val`. If `val` is
# a number already, there won't be a corresponding entry, just use `val`.
castable_val = defined_enums[attr][val] || val
end
@klass.type_for_attribute(attr).type_cast_for_database(castable_val)
end end
def deserialize(attr, val) def deserialize(attr, val)
@ -49,6 +54,8 @@ module PaperTrail
private private
# ActiveRecord::Enum was added in AR 4.1
# http://edgeguides.rubyonrails.org/4_1_release_notes.html#active-record-enums
def defined_enums def defined_enums
@defined_enums ||= (@klass.respond_to?(:defined_enums) ? @klass.defined_enums : {}) @defined_enums ||= (@klass.respond_to?(:defined_enums) ? @klass.defined_enums : {})
end end

View File

@ -1,7 +1,7 @@
require "rails_helper" require "rails_helper"
# This model is in the test suite soley for the purpose of testing ActiveRecord::Enum, # This model tests ActiveRecord::Enum, which was added in AR 4.1
# which is available in ActiveRecord4+ only # http://edgeguides.rubyonrails.org/4_1_release_notes.html#active-record-enums
describe PostWithStatus, type: :model do describe PostWithStatus, type: :model do
if defined?(ActiveRecord::Enum) if defined?(ActiveRecord::Enum)
with_versioning do with_versioning do
@ -22,6 +22,19 @@ describe PostWithStatus, type: :model do
expect(subject.changeset["status"]).to eql %w(published archived) expect(subject.changeset["status"]).to eql %w(published archived)
end end
end end
describe "#touch_with_version" do
it "preserves the enum value (and all other attributes)" do
post = described_class.create(status: :draft)
expect(post.versions.count).to eq(1)
expect(post.status).to eq("draft")
Timecop.travel 1.second.since # because MySQL lacks fractional seconds precision
post.paper_trail.touch_with_version
expect(post.versions.count).to eq(2)
expect(post.versions.last[:object]).to include("status: 0")
expect(post.paper_trail.previous_version.status).to eq("draft")
end
end
end end
end end
end end

View File

@ -173,6 +173,7 @@ class SetUpTestTables < ActiveRecord::Migration
create_table :post_with_statuses, force: true do |t| create_table :post_with_statuses, force: true do |t|
t.integer :status t.integer :status
t.timestamps null: false
end end
create_table :animals, force: true do |t| create_table :animals, force: true do |t|

View File

@ -162,7 +162,9 @@ ActiveRecord::Schema.define(version: 20110208155312) do
add_index "post_versions", ["item_type", "item_id"], name: "index_post_versions_on_item_type_and_item_id" add_index "post_versions", ["item_type", "item_id"], name: "index_post_versions_on_item_type_and_item_id"
create_table "post_with_statuses", force: :cascade do |t| create_table "post_with_statuses", force: :cascade do |t|
t.integer "status" t.integer "status"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end end
create_table "posts", force: :cascade do |t| create_table "posts", force: :cascade do |t|