undo-serializer-active_model 0.0.4 → 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.ruby-version +1 -1
- data/Gemfile +0 -1
- data/README.md +23 -28
- data/VERSION +1 -1
- data/gemfiles/3.0.gemfile +0 -1
- data/gemfiles/3.1.gemfile +0 -1
- data/gemfiles/3.2.gemfile +0 -1
- data/gemfiles/4.0.gemfile +0 -1
- data/gemfiles/4.1.gemfile +0 -1
- data/lib/undo/serializer/active_model.rb +96 -37
- data/spec/undo/serializer/active_model_integration_spec.rb +20 -14
- data/spec/undo/serializer/active_model_spec.rb +52 -20
- data/undo-serializer-active_model.gemspec +2 -3
- metadata +7 -22
- data/spec/support/active_record/user_serializer.rb +0 -6
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: a295ea13f84f57828d1f8f160c46776e92cff623
|
4
|
+
data.tar.gz: 65880e189d3907d9a4ff5ca31fe3f9fca9156619
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: d995320ec3063c1f92e11062ce5f75190f78ae98313ad6f8cb5eeef8a54ff7cc64621af57ec3048da98d4ad9353866503cacb024e047b53252a5124d335d26a2
|
7
|
+
data.tar.gz: 6d197310535c87d08e0f27564ee6b2be3fc4854b0fd5e6c3289250edcb5566cdb71cf1e92b7d4a557ebbf8f894adbf124cb3a989cdd8c9379c08c678244b72ac
|
data/.ruby-version
CHANGED
@@ -1 +1 @@
|
|
1
|
-
2.1.
|
1
|
+
2.1.1
|
data/Gemfile
CHANGED
data/README.md
CHANGED
@@ -4,10 +4,9 @@ Undo
|
|
4
4
|
[![Gemnasium Build Status](https://gemnasium.com/AlexParamonov/undo-serializer-active_model.png)](http://gemnasium.com/AlexParamonov/undo-serializer-active_model)
|
5
5
|
[![Coverage Status](https://coveralls.io/repos/AlexParamonov/undo-serializer-active_model/badge.png?branch=master)](https://coveralls.io/r/AlexParamonov/undo-serializer-active_model?branch=master)
|
6
6
|
[![Gem Version](https://badge.fury.io/rb/undo-serializer-active_model.png)](http://badge.fury.io/rb/undo-serializer-active_model)
|
7
|
+
[![Code Climate](https://codeclimate.com/github/AlexParamonov/undo-serializer-active_model.png)](https://codeclimate.com/github/AlexParamonov/undo-serializer-active_model)
|
7
8
|
|
8
|
-
ActiveModel serializer for Undo gem.
|
9
|
-
|
10
|
-
Designed to be used with `gem "active_model_serializers"`, but does not depends on it.
|
9
|
+
ActiveModel serializer for Undo gem. Does not require anything from Rails so is friendly to use with POROs.
|
11
10
|
|
12
11
|
Contents
|
13
12
|
---------
|
@@ -33,16 +32,19 @@ Or install it yourself as:
|
|
33
32
|
|
34
33
|
$ gem install undo-serializer-active_model
|
35
34
|
|
35
|
+
Most likely you'll install undo gem as well:
|
36
|
+
|
37
|
+
$ gem install undo
|
38
|
+
|
36
39
|
Requirements
|
37
40
|
------------
|
38
41
|
1. Ruby >= 1.9
|
39
|
-
1. `activesupport` (`active_model_serializers` depends on it)
|
40
42
|
|
41
43
|
Usage
|
42
44
|
------------
|
43
45
|
|
44
46
|
Gem is designed to be used with Undo gem.
|
45
|
-
|
47
|
+
Customize Undo to use serializer in global configuration:
|
46
48
|
|
47
49
|
``` ruby
|
48
50
|
Undo.configure do |config|
|
@@ -50,43 +52,36 @@ Undo.configure do |config|
|
|
50
52
|
end
|
51
53
|
```
|
52
54
|
|
53
|
-
Custom
|
55
|
+
Custom primary_key set, find_or_initialize and persist `Proc`s could be provided to the adapter:
|
54
56
|
``` ruby
|
55
57
|
Undo.configure do |config|
|
56
|
-
config.serializer =
|
57
|
-
|
58
|
+
config.serializer = Undo::Serializer::ActiveModel.new(
|
59
|
+
primary_key: [:id, :status],
|
60
|
+
find_or_initialize: ->(object_class, pk_attributes) { object_class.find_or_initialize_by pk_attributes },
|
61
|
+
serialize_attributes: ->(object) { object.serializable_hash },
|
62
|
+
persist: ->(object) { object.save! },
|
63
|
+
)
|
58
64
|
end
|
59
65
|
```
|
60
66
|
|
61
|
-
|
62
|
-
|
63
|
-
Undo.configure do |config|
|
64
|
-
config.serializer =
|
65
|
-
Undo::Serializer::ActiveModel.new CustomSerializer.new
|
66
|
-
end
|
67
|
-
```
|
67
|
+
For ActiveRecord Undo uses reasonable defaults, so most of the time it is not needed to overwrite them.
|
68
|
+
It should work with most Virtus objects as well.
|
68
69
|
|
69
|
-
As usual any Undo configuration may be set in place on wrap and restore:
|
70
|
+
As usual any Undo configuration may be set in place on store, wrap and restore:
|
70
71
|
``` ruby
|
71
|
-
Undo.
|
72
|
-
Undo.restore uuid,
|
73
|
-
```
|
74
|
-
|
75
|
-
In place using the specific serializer from `gem "active_model_serializers"`:
|
76
|
-
``` ruby
|
77
|
-
Undo.wrap user, serializer: Undo::Serializer::ActiveModel.new(UserSerializer.new(user))
|
72
|
+
Undo.store user, serializer: Undo::Serializer::ActiveRecord.new(primary_key: :uuid)
|
73
|
+
Undo.restore uuid, primary_key: :uuid, persist: ->(object) { object.write_to_disk! }
|
78
74
|
```
|
79
75
|
|
80
76
|
### Associations
|
81
77
|
|
82
|
-
|
78
|
+
Add `include` option to serialize the association
|
83
79
|
``` ruby
|
84
|
-
|
85
|
-
|
86
|
-
has_many :roles, key: :has_many___roles
|
87
|
-
end
|
80
|
+
uuid = Undo.store post, include: comments
|
81
|
+
Undo.restore uuid
|
88
82
|
```
|
89
83
|
|
84
|
+
Will restore post with related comments.
|
90
85
|
|
91
86
|
Contacts
|
92
87
|
-------------
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.0
|
1
|
+
0.1.0
|
data/gemfiles/3.0.gemfile
CHANGED
data/gemfiles/3.1.gemfile
CHANGED
data/gemfiles/3.2.gemfile
CHANGED
data/gemfiles/4.0.gemfile
CHANGED
data/gemfiles/4.1.gemfile
CHANGED
@@ -1,65 +1,124 @@
|
|
1
|
-
require "active_support"
|
2
|
-
|
3
1
|
module Undo
|
4
2
|
module Serializer
|
5
3
|
class ActiveModel
|
6
|
-
def initialize(
|
7
|
-
options
|
8
|
-
@serializer = args.first
|
9
|
-
@serializer_source = options.fetch :serializer,
|
10
|
-
->(object) { object.active_model_serializer.new object }
|
4
|
+
def initialize(options = {})
|
5
|
+
load_options options
|
11
6
|
end
|
12
7
|
|
13
|
-
def serialize(object)
|
14
|
-
|
8
|
+
def serialize(object, options = {})
|
9
|
+
return object.map do |record|
|
10
|
+
serialize record, options
|
11
|
+
end if array? object
|
12
|
+
|
13
|
+
load_options options
|
14
|
+
|
15
|
+
attributes = serialize_attributes(object) || {}
|
16
|
+
associations = {}
|
17
|
+
Array(options[:include]).map do |association|
|
18
|
+
associations[association] = serialize(object.public_send association)
|
19
|
+
end
|
20
|
+
pk_attributes = symbolize_keys(attributes).select do |attribute|
|
21
|
+
primary_key_fields.include? attribute
|
22
|
+
end
|
23
|
+
|
24
|
+
{
|
25
|
+
attributes: attributes,
|
26
|
+
associations: associations,
|
27
|
+
meta: {
|
28
|
+
pk_attributes: pk_attributes,
|
29
|
+
class_name: object.class.name,
|
30
|
+
}
|
31
|
+
}
|
15
32
|
end
|
16
33
|
|
17
|
-
def deserialize(
|
18
|
-
|
19
|
-
|
20
|
-
|
34
|
+
def deserialize(object, options = {})
|
35
|
+
return object.map do |record|
|
36
|
+
deserialize record
|
37
|
+
end if array? object
|
38
|
+
|
39
|
+
load_options options
|
21
40
|
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
41
|
+
hash = symbolize_keys object
|
42
|
+
object_meta = hash.fetch :meta
|
43
|
+
associations = hash.fetch :associations
|
44
|
+
attributes = hash.fetch :attributes
|
26
45
|
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
46
|
+
with_transaction do
|
47
|
+
initialize_object(object_meta).tap do |object|
|
48
|
+
attributes.each do |field, value|
|
49
|
+
deserialize_field object, field, value
|
31
50
|
end
|
32
51
|
|
33
|
-
object.
|
52
|
+
# QUESTION: Set associations? object.association_name = deserialize association ?
|
53
|
+
associations.each do |(association_name, association)|
|
54
|
+
deserialize association
|
55
|
+
end
|
56
|
+
|
57
|
+
persist object
|
34
58
|
end
|
35
59
|
end
|
36
|
-
|
37
60
|
end
|
38
61
|
|
39
62
|
private
|
40
|
-
attr_reader :
|
63
|
+
attr_reader :serialize_attributes_source,
|
64
|
+
:initialize_object_source,
|
65
|
+
:persist_object_source
|
41
66
|
|
42
|
-
def
|
43
|
-
|
67
|
+
def deserialize_field(object, field, value)
|
68
|
+
object.send "#{field}=", value # not public_send!
|
44
69
|
end
|
45
70
|
|
46
|
-
def
|
47
|
-
|
48
|
-
|
71
|
+
def initialize_object(meta)
|
72
|
+
object_class = constantize meta.fetch(:class_name)
|
73
|
+
pk_attributes = meta.fetch :pk_attributes
|
74
|
+
|
75
|
+
find_or_initialize object_class, pk_attributes
|
76
|
+
end
|
77
|
+
|
78
|
+
def with_transaction(&block)
|
79
|
+
if defined? ActiveRecord
|
80
|
+
ActiveRecord::Base.transaction(&block)
|
81
|
+
else
|
82
|
+
block.call
|
49
83
|
end
|
50
84
|
end
|
51
85
|
|
52
|
-
def
|
53
|
-
|
86
|
+
def load_options(options)
|
87
|
+
@serialize_attributes_source = options.fetch :serialize_attributes, @serialize_attributes_source ||
|
88
|
+
->(object) { object.attributes }
|
89
|
+
|
90
|
+
@initialize_object_source = options.fetch :find_or_initialize, @initialize_object_source ||
|
91
|
+
->(object_class, pk_query) { object_class.respond_to?(:where) && object_class.where(pk_query).first || object_class.new(pk_query) }
|
92
|
+
|
93
|
+
@persist_object_source = options.fetch :persist, @persist_object_source ||
|
94
|
+
->(object) { object.respond_to?(:save!) && object.save! }
|
95
|
+
|
96
|
+
@primary_key_fields = options.fetch :primary_key, @primary_key_fields || :id
|
54
97
|
end
|
55
98
|
|
56
|
-
def
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
99
|
+
def primary_key_fields
|
100
|
+
Array(@primary_key_fields)
|
101
|
+
end
|
102
|
+
|
103
|
+
def serialize_attributes(*args); serialize_attributes_source.call(*args) end
|
104
|
+
def find_or_initialize(*args); initialize_object_source.call(*args) end
|
105
|
+
def persist(*args); persist_object_source.call(*args) end
|
106
|
+
|
107
|
+
def array?(object)
|
108
|
+
object.respond_to?(:map) && ! object.is_a?(Hash)
|
109
|
+
end
|
110
|
+
# ActiveSupport methods
|
111
|
+
def symbolize_keys(hash)
|
112
|
+
hash.each_with_object({}) do |(key, value), result|
|
113
|
+
new_key = key.is_a?(String) ? key.to_sym : key
|
114
|
+
new_value = value.is_a?(Hash) ? symbolize_keys(value) : value
|
115
|
+
|
116
|
+
result[new_key] = new_value
|
117
|
+
end
|
118
|
+
end
|
61
119
|
|
62
|
-
|
120
|
+
def constantize(class_name)
|
121
|
+
class_name.split('::').inject(Kernel) { |object, name| object = object.const_get(name); object }
|
63
122
|
end
|
64
123
|
end
|
65
124
|
end
|
@@ -2,7 +2,6 @@ require "spec_helper"
|
|
2
2
|
require "support/active_record"
|
3
3
|
require "user"
|
4
4
|
require "role"
|
5
|
-
require "user_serializer"
|
6
5
|
|
7
6
|
describe Undo::Serializer::ActiveModel do
|
8
7
|
subject { described_class }
|
@@ -19,17 +18,19 @@ describe Undo::Serializer::ActiveModel do
|
|
19
18
|
expect(restored_user).to be_persisted
|
20
19
|
end
|
21
20
|
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
21
|
+
describe "associations" do
|
22
|
+
it "restores provided associations" do
|
23
|
+
roles = create_list :role, 3, user: user
|
24
|
+
hash = serializer.serialize user, include: :roles
|
25
|
+
user.delete
|
26
|
+
Role.delete_all # HACK for ActiveRecord 3.0
|
27
27
|
|
28
|
-
|
28
|
+
restored_user = serializer.deserialize hash
|
29
29
|
|
30
|
-
|
31
|
-
|
32
|
-
|
30
|
+
restored_user.reload # HACK for ActiveRecord 3.0
|
31
|
+
expect(restored_user).to eq user
|
32
|
+
expect(restored_user.roles).to eq roles
|
33
|
+
end
|
33
34
|
end
|
34
35
|
|
35
36
|
it "reverts changes to object" do
|
@@ -43,9 +44,14 @@ describe Undo::Serializer::ActiveModel do
|
|
43
44
|
expect(restored_user).to eq user.reload
|
44
45
|
end
|
45
46
|
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
47
|
+
describe "array of objects" do
|
48
|
+
it "restores a collection" do
|
49
|
+
users = create_list :user, 3
|
50
|
+
array = serializer.serialize users, include: :roles
|
51
|
+
users.each &:delete
|
52
|
+
|
53
|
+
restored_users = serializer.deserialize array
|
54
|
+
expect(restored_users).to eq users
|
55
|
+
end
|
50
56
|
end
|
51
57
|
end
|
@@ -3,38 +3,70 @@ require "spec_helper"
|
|
3
3
|
describe Undo::Serializer::ActiveModel do
|
4
4
|
subject { described_class }
|
5
5
|
let(:serializer) { subject.new }
|
6
|
-
let(:object) { double :object }
|
7
|
-
|
6
|
+
let(:object) { double :object, attributes: { id: 1, foo: "bar", bar: "baz", hello: "world" } }
|
7
|
+
|
8
|
+
describe "custom finder fields" do
|
9
|
+
it "uses finder fields to find the object" do
|
10
|
+
FooBarTestObject = Class.new
|
11
|
+
serializer = subject.new primary_key: [:foo, :bar]
|
12
|
+
allow(object).to receive(:class) { FooBarTestObject }
|
13
|
+
|
14
|
+
expect(FooBarTestObject).to receive(:new).with(foo: "bar", bar: "baz") { object.as_null_object }
|
15
|
+
|
16
|
+
hash = serializer.serialize object
|
17
|
+
serializer.deserialize hash
|
18
|
+
end
|
19
|
+
end
|
8
20
|
|
9
21
|
describe "custom serializer" do
|
10
|
-
it "uses provided
|
11
|
-
|
12
|
-
serializer = subject.new
|
22
|
+
it "uses provided attribute serialization" do
|
23
|
+
attribute_serializer = double :attribute_serializer
|
24
|
+
serializer = subject.new serialize_attributes: attribute_serializer
|
13
25
|
|
14
|
-
expect(
|
26
|
+
expect(attribute_serializer).to receive(:call).with(object)
|
15
27
|
serializer.serialize object
|
16
28
|
end
|
17
29
|
|
18
|
-
it "uses
|
19
|
-
|
20
|
-
|
21
|
-
serializer = subject.new serializer: custom_serializer_source
|
30
|
+
it "uses provided find_or_initialize deserialization" do
|
31
|
+
deserializer = double :find_or_initialize_deserializer
|
32
|
+
serializer = subject.new find_or_initialize: deserializer
|
22
33
|
|
23
|
-
|
24
|
-
expect(
|
25
|
-
serializer.
|
34
|
+
hash = serializer.serialize object
|
35
|
+
expect(deserializer).to receive(:call).with(object.class, id: 1) { object.as_null_object }
|
36
|
+
serializer.deserialize hash
|
26
37
|
end
|
27
38
|
|
28
|
-
it "
|
29
|
-
|
30
|
-
custom_serializer = double :custom_serializer
|
39
|
+
it "uses provided way of persisting object" do
|
40
|
+
persister = double :persister
|
31
41
|
|
32
|
-
|
42
|
+
deserializer = double :find_or_initialize_deserializer
|
43
|
+
allow(deserializer).to receive(:call) { object.as_null_object }
|
44
|
+
serializer = subject.new persist: persister, find_or_initialize: deserializer
|
33
45
|
|
34
|
-
|
35
|
-
expect(
|
46
|
+
hash = serializer.serialize object
|
47
|
+
expect(persister).to receive(:call).with(object)
|
48
|
+
serializer.deserialize hash
|
49
|
+
end
|
50
|
+
end
|
36
51
|
|
37
|
-
|
52
|
+
describe "in place serializer options" do
|
53
|
+
specify "#serialize" do
|
54
|
+
attribute_serializer = double :attribute_serializer
|
55
|
+
serializer = subject.new
|
56
|
+
|
57
|
+
expect(attribute_serializer).to receive(:call).with(object)
|
58
|
+
serializer.serialize object,
|
59
|
+
serialize_attributes: attribute_serializer
|
60
|
+
end
|
61
|
+
|
62
|
+
specify "#deserialize" do
|
63
|
+
deserializer = double :find_or_initialize_deserializer
|
64
|
+
serializer = subject.new
|
65
|
+
|
66
|
+
hash = serializer.serialize object
|
67
|
+
expect(deserializer).to receive(:call).with(object.class, id: 1) { object.as_null_object }
|
68
|
+
serializer.deserialize hash,
|
69
|
+
find_or_initialize: deserializer
|
38
70
|
end
|
39
71
|
end
|
40
72
|
|
@@ -7,8 +7,8 @@ Gem::Specification.new do |spec|
|
|
7
7
|
spec.version = IO.read("VERSION")
|
8
8
|
spec.authors = ["Alexander Paramonov"]
|
9
9
|
spec.email = ["alexander.n.paramonov@gmail.com"]
|
10
|
-
spec.summary = %q{ActiveModel serializer for Undo gem.}
|
11
|
-
spec.description = %q{ActiveModel serializer for Undo gem.}
|
10
|
+
spec.summary = %q{ActiveModel serializer for Undo gem. Does not require anything from Rails so is friendly to use with POROs.}
|
11
|
+
spec.description = %q{ActiveModel serializer for Undo gem. Does not require anything from Rails so is friendly to use with POROs.}
|
12
12
|
spec.homepage = "http://github.com/AlexParamonov/undo-serializer-active_model"
|
13
13
|
spec.license = "MIT"
|
14
14
|
|
@@ -17,6 +17,5 @@ Gem::Specification.new do |spec|
|
|
17
17
|
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
18
18
|
spec.require_paths = ["lib"]
|
19
19
|
|
20
|
-
spec.add_dependency "activesupport"
|
21
20
|
spec.add_development_dependency 'bundler', '~> 1.0'
|
22
21
|
end
|
metadata
CHANGED
@@ -1,29 +1,15 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: undo-serializer-active_model
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0
|
4
|
+
version: 0.1.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Alexander Paramonov
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2014-
|
11
|
+
date: 2014-03-16 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
|
-
- !ruby/object:Gem::Dependency
|
14
|
-
name: activesupport
|
15
|
-
requirement: !ruby/object:Gem::Requirement
|
16
|
-
requirements:
|
17
|
-
- - ">="
|
18
|
-
- !ruby/object:Gem::Version
|
19
|
-
version: '0'
|
20
|
-
type: :runtime
|
21
|
-
prerelease: false
|
22
|
-
version_requirements: !ruby/object:Gem::Requirement
|
23
|
-
requirements:
|
24
|
-
- - ">="
|
25
|
-
- !ruby/object:Gem::Version
|
26
|
-
version: '0'
|
27
13
|
- !ruby/object:Gem::Dependency
|
28
14
|
name: bundler
|
29
15
|
requirement: !ruby/object:Gem::Requirement
|
@@ -38,7 +24,8 @@ dependencies:
|
|
38
24
|
- - "~>"
|
39
25
|
- !ruby/object:Gem::Version
|
40
26
|
version: '1.0'
|
41
|
-
description: ActiveModel serializer for Undo gem.
|
27
|
+
description: ActiveModel serializer for Undo gem. Does not require anything from Rails
|
28
|
+
so is friendly to use with POROs.
|
42
29
|
email:
|
43
30
|
- alexander.n.paramonov@gmail.com
|
44
31
|
executables: []
|
@@ -68,7 +55,6 @@ files:
|
|
68
55
|
- spec/support/active_record/role.rb
|
69
56
|
- spec/support/active_record/schema.rb
|
70
57
|
- spec/support/active_record/user.rb
|
71
|
-
- spec/support/active_record/user_serializer.rb
|
72
58
|
- spec/support/ci_helper.rb
|
73
59
|
- spec/support/factories.rb
|
74
60
|
- spec/undo/serializer/active_model_integration_spec.rb
|
@@ -94,19 +80,18 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
94
80
|
version: '0'
|
95
81
|
requirements: []
|
96
82
|
rubyforge_project:
|
97
|
-
rubygems_version: 2.
|
83
|
+
rubygems_version: 2.1.11
|
98
84
|
signing_key:
|
99
85
|
specification_version: 4
|
100
|
-
summary: ActiveModel serializer for Undo gem.
|
86
|
+
summary: ActiveModel serializer for Undo gem. Does not require anything from Rails
|
87
|
+
so is friendly to use with POROs.
|
101
88
|
test_files:
|
102
89
|
- spec/spec_helper.rb
|
103
90
|
- spec/support/active_record.rb
|
104
91
|
- spec/support/active_record/role.rb
|
105
92
|
- spec/support/active_record/schema.rb
|
106
93
|
- spec/support/active_record/user.rb
|
107
|
-
- spec/support/active_record/user_serializer.rb
|
108
94
|
- spec/support/ci_helper.rb
|
109
95
|
- spec/support/factories.rb
|
110
96
|
- spec/undo/serializer/active_model_integration_spec.rb
|
111
97
|
- spec/undo/serializer/active_model_spec.rb
|
112
|
-
has_rdoc:
|