mirror of
https://github.com/paper-trail-gem/paper_trail.git
synced 2022-11-09 11:33:19 -05:00
Add the ability to use a custom serializer for storing the object in the database
This commit is contained in:
parent
f057bee9db
commit
41e255bf51
8 changed files with 118 additions and 10 deletions
10
README.md
10
README.md
|
@ -727,6 +727,16 @@ Or a block:
|
|||
end
|
||||
```
|
||||
|
||||
## Using a custom serializer
|
||||
|
||||
By default, PaperTrail stores your changes as a YAML dump. You can override this with the serializer config option:
|
||||
|
||||
```ruby
|
||||
>> PaperTrail.serializer = MyCustomSerializer
|
||||
```
|
||||
|
||||
The serializer needs to be a class that responds to a `load` and `dump` method.
|
||||
|
||||
## Deleting Old Versions
|
||||
|
||||
Over time your `versions` table will grow to an unwieldy size. Because each version is self-contained (see the Diffing section above for more) you can simply delete any records you don't want any more. For example:
|
||||
|
|
|
@ -5,6 +5,7 @@ require 'paper_trail/config'
|
|||
require 'paper_trail/controller'
|
||||
require 'paper_trail/has_paper_trail'
|
||||
require 'paper_trail/version'
|
||||
require 'paper_trail/serializers/yaml'
|
||||
|
||||
# PaperTrail's module methods can be called in both models and controllers.
|
||||
module PaperTrail
|
||||
|
@ -69,6 +70,9 @@ module PaperTrail
|
|||
paper_trail_store[:controller_info] = value
|
||||
end
|
||||
|
||||
def self.serializer
|
||||
PaperTrail.config.serializer
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
|
|
|
@ -1,12 +1,13 @@
|
|||
module PaperTrail
|
||||
class Config
|
||||
include Singleton
|
||||
attr_accessor :enabled, :timestamp_field
|
||||
attr_accessor :enabled, :timestamp_field, :serializer
|
||||
|
||||
def initialize
|
||||
# Indicates whether PaperTrail is on or off.
|
||||
@enabled = true
|
||||
@timestamp_field = :created_at
|
||||
@serializer = PaperTrail::Serializers::Yaml
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -162,9 +162,10 @@ module PaperTrail
|
|||
}
|
||||
if version_class.column_names.include? 'object_changes'
|
||||
# The double negative (reject, !include?) preserves the hash structure of self.changes.
|
||||
data[:object_changes] = self.changes.reject do |key, value|
|
||||
changes = self.changes.reject do |key, value|
|
||||
!notably_changed.include?(key)
|
||||
end.to_yaml
|
||||
end
|
||||
data[:object_changes] = PaperTrail.serializer.dump(changes)
|
||||
end
|
||||
send(self.class.versions_association_name).build merge_metadata(data)
|
||||
end
|
||||
|
@ -215,7 +216,7 @@ module PaperTrail
|
|||
end
|
||||
|
||||
def object_to_string(object)
|
||||
object.attributes.except(*self.class.skip).to_yaml
|
||||
PaperTrail.serializer.dump object.attributes.except(*self.class.skip)
|
||||
end
|
||||
|
||||
def changed_notably?
|
||||
|
|
23
lib/paper_trail/serializers/yaml.rb
Normal file
23
lib/paper_trail/serializers/yaml.rb
Normal file
|
@ -0,0 +1,23 @@
|
|||
require 'yaml'
|
||||
|
||||
module PaperTrail
|
||||
module Serializers
|
||||
class Yaml
|
||||
def self.load(string)
|
||||
new.load(string)
|
||||
end
|
||||
|
||||
def self.dump(hash)
|
||||
new.dump(hash)
|
||||
end
|
||||
|
||||
def load(string)
|
||||
YAML.load(string)
|
||||
end
|
||||
|
||||
def dump(hash)
|
||||
YAML.dump(hash)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -55,7 +55,7 @@ class Version < ActiveRecord::Base
|
|||
options.reverse_merge! :has_one => false
|
||||
|
||||
unless object.nil?
|
||||
attrs = YAML::load object
|
||||
attrs = PaperTrail.serializer.load object
|
||||
|
||||
# Normally a polymorphic belongs_to relationship allows us
|
||||
# to get the object we belong to by calling, in this case,
|
||||
|
@ -103,7 +103,7 @@ class Version < ActiveRecord::Base
|
|||
def changeset
|
||||
if self.class.column_names.include? 'object_changes'
|
||||
if changes = object_changes
|
||||
HashWithIndifferentAccess[YAML::load(changes)]
|
||||
HashWithIndifferentAccess[PaperTrail.serializer.load(changes)]
|
||||
else
|
||||
{}
|
||||
end
|
||||
|
|
|
@ -49,11 +49,11 @@ class HasPaperTrailModelTest < ActiveSupport::TestCase
|
|||
end
|
||||
|
||||
should 'have removed the skipped attributes when saving the previous version' do
|
||||
assert_equal nil, YAML::load(@old_article.object)['file_upload']
|
||||
assert_equal nil, PaperTrail.serializer.load(@old_article.object)['file_upload']
|
||||
end
|
||||
|
||||
should 'have kept the non-skipped attributes in the previous version' do
|
||||
assert_equal 'Some text here.', YAML::load(@old_article.object)['content']
|
||||
assert_equal 'Some text here.', PaperTrail.serializer.load(@old_article.object)['content']
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -184,7 +184,7 @@ class HasPaperTrailModelTest < ActiveSupport::TestCase
|
|||
end
|
||||
|
||||
should 'have stored changes' do
|
||||
assert_equal ({'name' => ['Henry', 'Harry']}), YAML::load(@widget.versions.last.object_changes)
|
||||
assert_equal ({'name' => ['Henry', 'Harry']}), PaperTrail.serializer.load(@widget.versions.last.object_changes)
|
||||
assert_equal ({'name' => ['Henry', 'Harry']}), @widget.versions.last.changeset
|
||||
end
|
||||
|
||||
|
|
69
test/unit/serializer_test.rb
Normal file
69
test/unit/serializer_test.rb
Normal file
|
@ -0,0 +1,69 @@
|
|||
require 'test_helper'
|
||||
|
||||
class CustomSerializer
|
||||
require 'json'
|
||||
def self.dump(object_hash)
|
||||
JSON.dump object_hash
|
||||
end
|
||||
|
||||
def self.load(string)
|
||||
JSON.parse string
|
||||
end
|
||||
end
|
||||
|
||||
class SerializerTest < ActiveSupport::TestCase
|
||||
|
||||
context 'YAML Serializer' do
|
||||
setup do
|
||||
Fluxor.instance_eval <<-END
|
||||
has_paper_trail
|
||||
END
|
||||
|
||||
@fluxor = Fluxor.create :name => 'Some text.'
|
||||
@fluxor.update_attributes :name => 'Some more text.'
|
||||
end
|
||||
|
||||
should 'work with the default yaml serializer' do
|
||||
# Normal behaviour
|
||||
assert_equal 2, @fluxor.versions.length
|
||||
assert_nil @fluxor.versions[0].reify
|
||||
assert_equal 'Some text.', @fluxor.versions[1].reify.name
|
||||
|
||||
|
||||
# Check values are stored as YAML.
|
||||
assert_equal "---\nwidget_id: \nname: Some text.\nid: 1\n", @fluxor.versions[1].object
|
||||
assert_equal ({"widget_id" => nil,"name" =>"Some text.","id" =>1}), YAML.load(@fluxor.versions[1].object)
|
||||
|
||||
end
|
||||
end
|
||||
|
||||
context 'Custom Serializer' do
|
||||
setup do
|
||||
PaperTrail.config.serializer = CustomSerializer
|
||||
|
||||
Fluxor.instance_eval <<-END
|
||||
has_paper_trail
|
||||
END
|
||||
|
||||
@fluxor = Fluxor.create :name => 'Some text.'
|
||||
@fluxor.update_attributes :name => 'Some more text.'
|
||||
end
|
||||
|
||||
teardown do
|
||||
PaperTrail.config.serializer = PaperTrail::Serializers::Yaml
|
||||
end
|
||||
|
||||
should 'work with custom serializer' do
|
||||
# Normal behaviour
|
||||
assert_equal 2, @fluxor.versions.length
|
||||
assert_nil @fluxor.versions[0].reify
|
||||
assert_equal 'Some text.', @fluxor.versions[1].reify.name
|
||||
|
||||
# Check values are stored as JSON.
|
||||
assert_equal "{\"widget_id\":null,\"name\":\"Some text.\",\"id\":1}", @fluxor.versions[1].object
|
||||
assert_equal ({"widget_id" => nil,"name" =>"Some text.","id" =>1}), JSON.parse(@fluxor.versions[1].object)
|
||||
|
||||
end
|
||||
end
|
||||
|
||||
end
|
Loading…
Reference in a new issue