undo-serializer-active_model 0.1.0 → 0.2.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.travis.yml +6 -5
- data/Appraisals +21 -9
- data/README.md +4 -1
- data/VERSION +1 -1
- data/gemfiles/{3.1.gemfile → activerecord_3.1.gemfile} +0 -0
- data/gemfiles/{3.2.gemfile → activerecord_3.2.gemfile} +0 -0
- data/gemfiles/{4.0.gemfile → activerecord_4.0.gemfile} +0 -0
- data/gemfiles/{4.1.gemfile → activerecord_4.1.gemfile} +0 -0
- data/gemfiles/{3.0.gemfile → activerecord_head.gemfile} +1 -1
- data/gemfiles/undo_1.0.0.gemfile +32 -0
- data/gemfiles/undo_head.gemfile +31 -0
- data/lib/undo/serializer/active_model.rb +46 -67
- data/lib/undo/serializer/active_model/connector.rb +61 -0
- data/spec/{undo/serializer/active_model_integration_spec.rb → integration/active_record_spec.rb} +36 -2
- data/spec/integration/undo_spec.rb +20 -0
- data/spec/spec_helper.rb +0 -6
- data/spec/undo/serializer/active_model/connector_spec.rb +38 -0
- data/spec/undo/serializer/active_model_spec.rb +87 -57
- data/undo-serializer-active_model.gemspec +4 -0
- metadata +72 -9
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA1:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 8576d795a1e019748983cc40635c7f08f5eae3a4
|
|
4
|
+
data.tar.gz: 3b8e2c05b390f9b5369d401143c34b606580f96a
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 6c1a19f280729c09cc6e5cea07755ed7be7362e157927b5b9749ac0ba95dc8af90a00f67281a1215839d6a8741fc39c0200bbf6ab8796cd45788bb8c2c4a357d
|
|
7
|
+
data.tar.gz: 68fd5978c65bc28eefb1c1a33a0207873744ec5fa3b5c79ba219bba56f3ebce1d7d261eae5e92cffb62abfe834ce24cfb8a006b41211dab04df22f623a9fedc0
|
data/.travis.yml
CHANGED
|
@@ -11,11 +11,12 @@ rvm:
|
|
|
11
11
|
- jruby-head
|
|
12
12
|
|
|
13
13
|
gemfile:
|
|
14
|
-
- gemfiles/
|
|
15
|
-
- gemfiles/
|
|
16
|
-
- gemfiles/
|
|
17
|
-
- gemfiles/
|
|
18
|
-
- gemfiles/
|
|
14
|
+
- gemfiles/activerecord_3.1.gemfile
|
|
15
|
+
- gemfiles/activerecord_3.2.gemfile
|
|
16
|
+
- gemfiles/activerecord_4.0.gemfile
|
|
17
|
+
- gemfiles/activerecord_4.1.gemfile
|
|
18
|
+
- gemfiles/activerecord_head.gemfile
|
|
19
|
+
- gemfiles/undo_head.gemfile
|
|
19
20
|
|
|
20
21
|
matrix:
|
|
21
22
|
allow_failures:
|
data/Appraisals
CHANGED
|
@@ -1,24 +1,36 @@
|
|
|
1
|
-
appraise "3.
|
|
2
|
-
gem "activerecord", "~> 3.0.20"
|
|
3
|
-
gem "undo-serializer-active_model", :path => "../"
|
|
4
|
-
end
|
|
5
|
-
|
|
6
|
-
appraise "3.1" do
|
|
1
|
+
appraise "activerecord-3.1" do
|
|
7
2
|
gem "activerecord", "~> 3.1.12"
|
|
8
3
|
gem "undo-serializer-active_model", :path => "../"
|
|
9
4
|
end
|
|
10
5
|
|
|
11
|
-
appraise "3.2" do
|
|
6
|
+
appraise "activerecord-3.2" do
|
|
12
7
|
gem "activerecord", "~> 3.2.15"
|
|
13
8
|
gem "undo-serializer-active_model", :path => "../"
|
|
14
9
|
end
|
|
15
10
|
|
|
16
|
-
appraise "4.0" do
|
|
11
|
+
appraise "activerecord-4.0" do
|
|
17
12
|
gem "activerecord", "~> 4.0.0"
|
|
18
13
|
gem "undo-serializer-active_model", :path => "../"
|
|
19
14
|
end
|
|
20
15
|
|
|
21
|
-
appraise "4.1" do
|
|
16
|
+
appraise "activerecord-4.1" do
|
|
22
17
|
gem "activerecord", "~> 4.1.0.beta"
|
|
23
18
|
gem "undo-serializer-active_model", :path => "../"
|
|
24
19
|
end
|
|
20
|
+
|
|
21
|
+
appraise "activerecord-head" do
|
|
22
|
+
gem "activerecord"
|
|
23
|
+
gem "undo-serializer-active_model", :path => "../"
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
appraise "undo-1.0.0" do
|
|
27
|
+
gem "activerecord"
|
|
28
|
+
gem "undo", "~> 1.0.0"
|
|
29
|
+
gem "undo-serializer-active_model", :path => "../"
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
appraise "undo-head" do
|
|
33
|
+
gem "activerecord"
|
|
34
|
+
gem "undo"
|
|
35
|
+
gem "undo-serializer-active_model", :path => "../"
|
|
36
|
+
end
|
data/README.md
CHANGED
|
@@ -6,7 +6,9 @@ Undo
|
|
|
6
6
|
[](http://badge.fury.io/rb/undo-serializer-active_model)
|
|
7
7
|
[](https://codeclimate.com/github/AlexParamonov/undo-serializer-active_model)
|
|
8
8
|
|
|
9
|
-
ActiveModel serializer for Undo gem.
|
|
9
|
+
ActiveModel serializer for [Undo gem](https://github.com/AlexParamonov/undo).
|
|
10
|
+
|
|
11
|
+
Does not require anything from Rails so is friendly to use with POROs.
|
|
10
12
|
|
|
11
13
|
Contents
|
|
12
14
|
---------
|
|
@@ -39,6 +41,7 @@ Most likely you'll install undo gem as well:
|
|
|
39
41
|
Requirements
|
|
40
42
|
------------
|
|
41
43
|
1. Ruby >= 1.9
|
|
44
|
+
1. Undo gem
|
|
42
45
|
|
|
43
46
|
Usage
|
|
44
47
|
------------
|
data/VERSION
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
0.
|
|
1
|
+
0.2.2
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
# This file was generated by Appraisal
|
|
2
|
+
|
|
3
|
+
source "https://rubygems.org"
|
|
4
|
+
|
|
5
|
+
gem "rake"
|
|
6
|
+
gem "activerecord"
|
|
7
|
+
gem "undo", "~> 1.0.0"
|
|
8
|
+
gem "undo-serializer-active_model", :path=>"../"
|
|
9
|
+
|
|
10
|
+
group :development do
|
|
11
|
+
gem "pry"
|
|
12
|
+
gem "appraisal", :github=>"thoughtbot/appraisal"
|
|
13
|
+
|
|
14
|
+
platforms :ruby_19, :ruby_20 do
|
|
15
|
+
gem "pry-plus"
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
group :test do
|
|
20
|
+
gem "coveralls", :require=>false
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
group :test, :development do
|
|
24
|
+
gem "rspec", ">= 3.0.0.beta1"
|
|
25
|
+
gem "activerecord", ">= 3.0.0"
|
|
26
|
+
gem "activerecord-jdbcsqlite3-adapter", :platform=>:jruby
|
|
27
|
+
gem "sqlite3", :platform=>[:ruby, :mswin, :mingw]
|
|
28
|
+
gem "factory_girl"
|
|
29
|
+
gem "faker"
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
gemspec :path=>".././"
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
# This file was generated by Appraisal
|
|
2
|
+
|
|
3
|
+
source "https://rubygems.org"
|
|
4
|
+
|
|
5
|
+
gem "rake"
|
|
6
|
+
gem "activerecord"
|
|
7
|
+
gem "undo"
|
|
8
|
+
gem "undo-serializer-active_model", :path=>"../"
|
|
9
|
+
|
|
10
|
+
group :development do
|
|
11
|
+
gem "pry"
|
|
12
|
+
gem "appraisal", :github=>"thoughtbot/appraisal"
|
|
13
|
+
|
|
14
|
+
platforms :ruby_19, :ruby_20 do
|
|
15
|
+
gem "pry-plus"
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
group :test do
|
|
20
|
+
gem "coveralls", :require=>false
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
group :test, :development do
|
|
24
|
+
gem "rspec", ">= 3.0.0.beta1"
|
|
25
|
+
gem "activerecord-jdbcsqlite3-adapter", :platform=>:jruby
|
|
26
|
+
gem "sqlite3", :platform=>[:ruby, :mswin, :mingw]
|
|
27
|
+
gem "factory_girl"
|
|
28
|
+
gem "faker"
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
gemspec :path=>".././"
|
|
@@ -1,8 +1,15 @@
|
|
|
1
|
+
require_relative "active_model/connector"
|
|
2
|
+
require "undo/serializer/primitive"
|
|
3
|
+
|
|
1
4
|
module Undo
|
|
2
5
|
module Serializer
|
|
3
6
|
class ActiveModel
|
|
4
7
|
def initialize(options = {})
|
|
5
|
-
|
|
8
|
+
@connector = self.class.connector.with options
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
def name
|
|
12
|
+
"active_model"
|
|
6
13
|
end
|
|
7
14
|
|
|
8
15
|
def serialize(object, options = {})
|
|
@@ -10,71 +17,76 @@ module Undo
|
|
|
10
17
|
serialize record, options
|
|
11
18
|
end if array? object
|
|
12
19
|
|
|
13
|
-
|
|
20
|
+
return primitive_serializer.serialize(object) if primitive_serializer.serialize? object
|
|
21
|
+
serialize_object(object, options)
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def deserialize(input, options = {})
|
|
25
|
+
return input.map do |record|
|
|
26
|
+
deserialize record
|
|
27
|
+
end if array? input
|
|
28
|
+
|
|
29
|
+
return primitive_serializer.deserialize(input) if primitive_serializer.deserialize? input
|
|
30
|
+
deserialize_object(input)
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
private
|
|
34
|
+
attr_reader :connector
|
|
14
35
|
|
|
15
|
-
|
|
36
|
+
def primitive_serializer
|
|
37
|
+
@primitive_serializer ||= Serializer::Primitive.new
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
def serialize_object(object, options)
|
|
41
|
+
attributes = connector.serialize_attributes object
|
|
42
|
+
|
|
43
|
+
association_names = Array(options[:include])
|
|
16
44
|
associations = {}
|
|
17
|
-
|
|
45
|
+
association_names.map do |association|
|
|
18
46
|
associations[association] = serialize(object.public_send association)
|
|
19
47
|
end
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
48
|
+
|
|
49
|
+
pk_attributes = connector.primary_key_attributes object, attributes
|
|
50
|
+
is_persisted = object.respond_to?(:persisted?) && object.persisted?
|
|
23
51
|
|
|
24
52
|
{
|
|
53
|
+
serializer: name,
|
|
25
54
|
attributes: attributes,
|
|
26
55
|
associations: associations,
|
|
27
56
|
meta: {
|
|
28
57
|
pk_attributes: pk_attributes,
|
|
29
58
|
class_name: object.class.name,
|
|
59
|
+
persisted: is_persisted,
|
|
30
60
|
}
|
|
31
61
|
}
|
|
32
62
|
end
|
|
33
63
|
|
|
34
|
-
def
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
load_options options
|
|
40
|
-
|
|
41
|
-
hash = symbolize_keys object
|
|
42
|
-
object_meta = hash.fetch :meta
|
|
43
|
-
associations = hash.fetch :associations
|
|
44
|
-
attributes = hash.fetch :attributes
|
|
64
|
+
def deserialize_object(object_data)
|
|
65
|
+
object_meta = connector.get_option :meta, object_data
|
|
66
|
+
associations = connector.get_option :associations, object_data
|
|
67
|
+
attributes = connector.get_option :attributes, object_data
|
|
45
68
|
|
|
46
69
|
with_transaction do
|
|
47
|
-
initialize_object(object_meta).tap do |object|
|
|
70
|
+
connector.initialize_object(object_meta).tap do |object|
|
|
71
|
+
return if object.nil?
|
|
72
|
+
|
|
48
73
|
attributes.each do |field, value|
|
|
49
74
|
deserialize_field object, field, value
|
|
50
75
|
end
|
|
51
76
|
|
|
52
|
-
# QUESTION: Set associations? object.association_name = deserialize association ?
|
|
53
77
|
associations.each do |(association_name, association)|
|
|
54
|
-
deserialize
|
|
78
|
+
connector.associate object, association_name, deserialize(association)
|
|
55
79
|
end
|
|
56
80
|
|
|
57
|
-
persist object
|
|
81
|
+
connector.persist object, object_meta
|
|
58
82
|
end
|
|
59
83
|
end
|
|
60
84
|
end
|
|
61
85
|
|
|
62
|
-
private
|
|
63
|
-
attr_reader :serialize_attributes_source,
|
|
64
|
-
:initialize_object_source,
|
|
65
|
-
:persist_object_source
|
|
66
|
-
|
|
67
86
|
def deserialize_field(object, field, value)
|
|
68
87
|
object.send "#{field}=", value # not public_send!
|
|
69
88
|
end
|
|
70
89
|
|
|
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
90
|
def with_transaction(&block)
|
|
79
91
|
if defined? ActiveRecord
|
|
80
92
|
ActiveRecord::Base.transaction(&block)
|
|
@@ -83,43 +95,10 @@ module Undo
|
|
|
83
95
|
end
|
|
84
96
|
end
|
|
85
97
|
|
|
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
|
|
97
|
-
end
|
|
98
|
-
|
|
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
98
|
def array?(object)
|
|
108
99
|
object.respond_to?(:map) && ! object.is_a?(Hash)
|
|
109
100
|
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
101
|
|
|
116
|
-
result[new_key] = new_value
|
|
117
|
-
end
|
|
118
|
-
end
|
|
119
|
-
|
|
120
|
-
def constantize(class_name)
|
|
121
|
-
class_name.split('::').inject(Kernel) { |object, name| object = object.const_get(name); object }
|
|
122
|
-
end
|
|
123
102
|
end
|
|
124
103
|
end
|
|
125
104
|
end
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
require "virtus"
|
|
2
|
+
|
|
3
|
+
module Undo
|
|
4
|
+
module Serializer
|
|
5
|
+
class ActiveModel
|
|
6
|
+
def self.connector
|
|
7
|
+
@config ||= Connector.new
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
private
|
|
11
|
+
class Connector
|
|
12
|
+
include Virtus.value_object
|
|
13
|
+
values do
|
|
14
|
+
attribute :attribute_serializer, Proc, default: proc { -> object { object.attributes } }
|
|
15
|
+
attribute :persister, Proc, default: proc { -> object { object.respond_to?(:save!) && object.save! } }
|
|
16
|
+
attribute :primary_key_fetcher, Proc, default: proc { -> object { object.respond_to?(:primary_key) && object.primary_key || :id }}
|
|
17
|
+
attribute :associator, Proc, default: proc { -> object, association_name, value { setter = "#{association_name}="; object.respond_to?(setter) && object.send(setter, value) }}
|
|
18
|
+
attribute :object_initializer, Proc, default: proc { -> object_class, attributes { object_class.respond_to?(:where) && object_class.where(attributes).first || object_class.new(attributes) }}
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def primary_key_attributes(object, attributes)
|
|
22
|
+
fields = Array(primary_key_fetcher.call(object)).map(&:to_sym)
|
|
23
|
+
|
|
24
|
+
fields.each_with_object({}) do |field, pk_attributes|
|
|
25
|
+
pk_attributes[field] = attributes[field] || attributes[field.to_s]
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def initialize_object(meta)
|
|
30
|
+
object_class = constantize get_option :class_name, meta
|
|
31
|
+
pk_attributes = get_option :pk_attributes, meta
|
|
32
|
+
|
|
33
|
+
object_initializer.call object_class, pk_attributes
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
def persist(object, object_meta)
|
|
37
|
+
persister.call object unless [false, nil, 0, "false"].include? get_option :persisted, object_meta
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
def associate(object, association, associations)
|
|
41
|
+
associator.call object, association, associations
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
def serialize_attributes(object)
|
|
45
|
+
attribute_serializer.call(object) || {}
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
def constantize(class_name)
|
|
49
|
+
class_name.split('::').inject(Kernel) { |object, name| object = object.const_get(name); object }
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
def get_option(name, options)
|
|
53
|
+
options.fetch name.to_sym do
|
|
54
|
+
options.fetch name.to_s
|
|
55
|
+
end
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
end
|
|
59
|
+
end
|
|
60
|
+
end
|
|
61
|
+
end
|
data/spec/{undo/serializer/active_model_integration_spec.rb → integration/active_record_spec.rb}
RENAMED
|
@@ -18,16 +18,37 @@ describe Undo::Serializer::ActiveModel do
|
|
|
18
18
|
expect(restored_user).to be_persisted
|
|
19
19
|
end
|
|
20
20
|
|
|
21
|
+
describe "not persisted object" do
|
|
22
|
+
let(:user) { build :user }
|
|
23
|
+
|
|
24
|
+
it "restores object" do
|
|
25
|
+
hash = serializer.serialize user
|
|
26
|
+
restored_user = serializer.deserialize hash
|
|
27
|
+
|
|
28
|
+
expect(restored_user.attributes).to eq user.attributes
|
|
29
|
+
expect(restored_user).not_to be_persisted
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
it "restores provided associations" do
|
|
33
|
+
roles = build_list :role, 3
|
|
34
|
+
user.roles = roles
|
|
35
|
+
hash = serializer.serialize user, include: :roles
|
|
36
|
+
|
|
37
|
+
restored_user = serializer.deserialize hash
|
|
38
|
+
|
|
39
|
+
expect(restored_user).not_to be_persisted
|
|
40
|
+
expect(restored_user.roles.map(&:attributes)).to match roles.map(&:attributes)
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
|
|
21
44
|
describe "associations" do
|
|
22
45
|
it "restores provided associations" do
|
|
23
46
|
roles = create_list :role, 3, user: user
|
|
24
47
|
hash = serializer.serialize user, include: :roles
|
|
25
48
|
user.delete
|
|
26
|
-
Role.delete_all # HACK for ActiveRecord 3.0
|
|
27
49
|
|
|
28
50
|
restored_user = serializer.deserialize hash
|
|
29
51
|
|
|
30
|
-
restored_user.reload # HACK for ActiveRecord 3.0
|
|
31
52
|
expect(restored_user).to eq user
|
|
32
53
|
expect(restored_user.roles).to eq roles
|
|
33
54
|
end
|
|
@@ -54,4 +75,17 @@ describe Undo::Serializer::ActiveModel do
|
|
|
54
75
|
expect(restored_users).to eq users
|
|
55
76
|
end
|
|
56
77
|
end
|
|
78
|
+
|
|
79
|
+
describe "json store" do
|
|
80
|
+
it "restores object" do
|
|
81
|
+
hash = serializer.serialize user
|
|
82
|
+
hash = hash.to_json
|
|
83
|
+
user.delete
|
|
84
|
+
restored_user = serializer.deserialize JSON.load(hash)
|
|
85
|
+
|
|
86
|
+
expect(restored_user).to eq user
|
|
87
|
+
expect(user).not_to be_persisted
|
|
88
|
+
expect(restored_user).to be_persisted
|
|
89
|
+
end
|
|
90
|
+
end
|
|
57
91
|
end
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
require "spec_helper"
|
|
2
|
+
require "undo"
|
|
3
|
+
require "support/active_record"
|
|
4
|
+
require "user"
|
|
5
|
+
require 'undo/integration/shared_undo_integration_examples.rb'
|
|
6
|
+
|
|
7
|
+
Undo.configure do |config|
|
|
8
|
+
config.serializer = Undo::Serializer::ActiveModel.new
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
describe Undo do
|
|
12
|
+
let(:object) { create :user }
|
|
13
|
+
|
|
14
|
+
include_examples "undo integration"
|
|
15
|
+
|
|
16
|
+
it "stores and restores symbols" do
|
|
17
|
+
uuid = subject.store :foo
|
|
18
|
+
expect(subject.restore uuid).to eq :foo
|
|
19
|
+
end
|
|
20
|
+
end
|
data/spec/spec_helper.rb
CHANGED
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
require "spec_helper"
|
|
2
|
+
|
|
3
|
+
describe Undo::Serializer::ActiveModel::Connector do
|
|
4
|
+
let(:object) { double :object }
|
|
5
|
+
let(:serializer) { subject }
|
|
6
|
+
|
|
7
|
+
describe "#primary_key_attributes" do
|
|
8
|
+
let(:attributes) { { uuid: "identifier", foo: :bar, "hello" => "world" } }
|
|
9
|
+
|
|
10
|
+
it "extracts object primary key attributes" do
|
|
11
|
+
expect(object).to receive(:primary_key) { "uuid" }
|
|
12
|
+
|
|
13
|
+
expect(serializer.primary_key_attributes object, attributes).to eq uuid: "identifier"
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
it "redefines primary key attribute names by primary_key_fetcher" do
|
|
17
|
+
serializer = described_class.new primary_key_fetcher: -> object { %w[hello uuid] }
|
|
18
|
+
|
|
19
|
+
expect(serializer.primary_key_attributes object, attributes).to eq ({
|
|
20
|
+
hello: "world",
|
|
21
|
+
uuid: "identifier"
|
|
22
|
+
})
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
it "use nil value when no primary_key attributes available" do
|
|
26
|
+
allow(object).to receive(:primary_key) { "unknown" }
|
|
27
|
+
|
|
28
|
+
expect(serializer.primary_key_attributes object, attributes).to eq unknown: nil
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
it "accepts string and symbol as uuid key" do
|
|
32
|
+
allow(object).to receive(:primary_key) { "uuid" }
|
|
33
|
+
expect(serializer.primary_key_attributes object, attributes).to eq uuid: "identifier"
|
|
34
|
+
allow(object).to receive(:primary_key) { :uuid }
|
|
35
|
+
expect(serializer.primary_key_attributes object, attributes).to eq uuid: "identifier"
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
end
|
|
@@ -1,73 +1,103 @@
|
|
|
1
1
|
require "spec_helper"
|
|
2
2
|
|
|
3
|
+
class FooBarTestObject < OpenStruct
|
|
4
|
+
def attributes; marshal_dump end
|
|
5
|
+
end
|
|
6
|
+
|
|
3
7
|
describe Undo::Serializer::ActiveModel do
|
|
4
8
|
subject { described_class }
|
|
5
9
|
let(:serializer) { subject.new }
|
|
6
|
-
let(:
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
expect(attribute_serializer).to receive(:call).with(object)
|
|
27
|
-
serializer.serialize object
|
|
10
|
+
let(:object_class) { FooBarTestObject }
|
|
11
|
+
let(:object) { FooBarTestObject.new }
|
|
12
|
+
|
|
13
|
+
describe "options" do
|
|
14
|
+
describe "attribute_serializer" do
|
|
15
|
+
let(:attribute_serializer) { double :attribute_serializer }
|
|
16
|
+
let(:serializer) { subject.new attribute_serializer: attribute_serializer }
|
|
17
|
+
|
|
18
|
+
it "uses provided attribute serialization" do
|
|
19
|
+
expect(attribute_serializer).to receive(:call).with(object) { {} }
|
|
20
|
+
serializer.serialize object
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
context "when nil" do
|
|
24
|
+
let(:attribute_serializer) { proc { nil } }
|
|
25
|
+
|
|
26
|
+
it "does not raise" do
|
|
27
|
+
expect { serializer.serialize object }.not_to raise_error
|
|
28
|
+
end
|
|
29
|
+
end
|
|
28
30
|
end
|
|
29
31
|
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
serializer
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
32
|
+
describe "object_initializer" do
|
|
33
|
+
let(:initializer) { double :initializer }
|
|
34
|
+
let(:serializer) { subject.new object_initializer: initializer }
|
|
35
|
+
before do
|
|
36
|
+
object.id = 1
|
|
37
|
+
object.foo = :bar
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
it "uses provided initializer" do
|
|
41
|
+
hash = serializer.serialize object
|
|
42
|
+
expect(initializer).to receive(:call).with(object.class, id: 1) { double.as_null_object }
|
|
43
|
+
serializer.deserialize hash
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
context "when nil" do
|
|
47
|
+
let(:initializer) { proc { nil } }
|
|
48
|
+
|
|
49
|
+
it "returns nil" do
|
|
50
|
+
hash = serializer.serialize object
|
|
51
|
+
expect(serializer.deserialize hash).to eq nil
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
it "does not assigns attributes" do
|
|
55
|
+
hash = serializer.serialize object
|
|
56
|
+
expect{ serializer.deserialize hash }.not_to raise_error
|
|
57
|
+
expect(serializer.deserialize hash).to eq nil
|
|
58
|
+
end
|
|
59
|
+
end
|
|
37
60
|
end
|
|
38
61
|
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
allow(deserializer).to receive(:call) { object.as_null_object }
|
|
44
|
-
serializer = subject.new persist: persister, find_or_initialize: deserializer
|
|
45
|
-
|
|
46
|
-
hash = serializer.serialize object
|
|
47
|
-
expect(persister).to receive(:call).with(object)
|
|
48
|
-
serializer.deserialize hash
|
|
49
|
-
end
|
|
50
|
-
end
|
|
62
|
+
describe "assign associations" do
|
|
63
|
+
it "uses provided way of assigning associations" do
|
|
64
|
+
associated_object = object_class.new name: "association"
|
|
65
|
+
object.association_name = [associated_object]
|
|
51
66
|
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
attribute_serializer = double :attribute_serializer
|
|
55
|
-
serializer = subject.new
|
|
67
|
+
associator = double :associator
|
|
68
|
+
serializer = subject.new associator: associator
|
|
56
69
|
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
70
|
+
hash = serializer.serialize object, include: :association_name
|
|
71
|
+
expect(associator).to receive(:call) do |object, name, associations|
|
|
72
|
+
expect(associations.map(&:name)).to eq [associated_object.name]
|
|
73
|
+
end
|
|
74
|
+
serializer.deserialize hash
|
|
75
|
+
end
|
|
60
76
|
end
|
|
61
77
|
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
78
|
+
describe "persist object" do
|
|
79
|
+
it "uses provided way of persisting object" do
|
|
80
|
+
allow(object).to receive(:persisted?) { true }
|
|
81
|
+
persister = double :persister
|
|
82
|
+
serializer = subject.new persister: persister,
|
|
83
|
+
object_initializer: proc { object }
|
|
84
|
+
|
|
85
|
+
hash = serializer.serialize object
|
|
86
|
+
expect(persister).to receive(:call).with(object)
|
|
87
|
+
serializer.deserialize hash
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
it "does not persist new record objects" do
|
|
91
|
+
persister = double :persister
|
|
92
|
+
serializer = subject.new persister: persister,
|
|
93
|
+
object_initializer: proc { object }
|
|
94
|
+
|
|
95
|
+
allow(object).to receive(:persisted?) { false }
|
|
96
|
+
|
|
97
|
+
hash = serializer.serialize object
|
|
98
|
+
expect(persister).not_to receive(:call)
|
|
99
|
+
serializer.deserialize hash
|
|
100
|
+
end
|
|
70
101
|
end
|
|
71
102
|
end
|
|
72
|
-
|
|
73
103
|
end
|
|
@@ -17,5 +17,9 @@ 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 'undo', '~> 1.0'
|
|
21
|
+
spec.add_dependency 'undo-serializer-primitive', '~> 0.1'
|
|
22
|
+
spec.add_dependency 'virtus', '~> 1.0'
|
|
20
23
|
spec.add_development_dependency 'bundler', '~> 1.0'
|
|
24
|
+
spec.add_development_dependency "rspec", ">= 3.0.0.beta1"
|
|
21
25
|
end
|
metadata
CHANGED
|
@@ -1,15 +1,57 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: undo-serializer-active_model
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.2.2
|
|
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-05-11 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
|
+
- !ruby/object:Gem::Dependency
|
|
14
|
+
name: undo
|
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
|
16
|
+
requirements:
|
|
17
|
+
- - "~>"
|
|
18
|
+
- !ruby/object:Gem::Version
|
|
19
|
+
version: '1.0'
|
|
20
|
+
type: :runtime
|
|
21
|
+
prerelease: false
|
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
23
|
+
requirements:
|
|
24
|
+
- - "~>"
|
|
25
|
+
- !ruby/object:Gem::Version
|
|
26
|
+
version: '1.0'
|
|
27
|
+
- !ruby/object:Gem::Dependency
|
|
28
|
+
name: undo-serializer-primitive
|
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
|
30
|
+
requirements:
|
|
31
|
+
- - "~>"
|
|
32
|
+
- !ruby/object:Gem::Version
|
|
33
|
+
version: '0.1'
|
|
34
|
+
type: :runtime
|
|
35
|
+
prerelease: false
|
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
37
|
+
requirements:
|
|
38
|
+
- - "~>"
|
|
39
|
+
- !ruby/object:Gem::Version
|
|
40
|
+
version: '0.1'
|
|
41
|
+
- !ruby/object:Gem::Dependency
|
|
42
|
+
name: virtus
|
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
|
44
|
+
requirements:
|
|
45
|
+
- - "~>"
|
|
46
|
+
- !ruby/object:Gem::Version
|
|
47
|
+
version: '1.0'
|
|
48
|
+
type: :runtime
|
|
49
|
+
prerelease: false
|
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
51
|
+
requirements:
|
|
52
|
+
- - "~>"
|
|
53
|
+
- !ruby/object:Gem::Version
|
|
54
|
+
version: '1.0'
|
|
13
55
|
- !ruby/object:Gem::Dependency
|
|
14
56
|
name: bundler
|
|
15
57
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -24,6 +66,20 @@ dependencies:
|
|
|
24
66
|
- - "~>"
|
|
25
67
|
- !ruby/object:Gem::Version
|
|
26
68
|
version: '1.0'
|
|
69
|
+
- !ruby/object:Gem::Dependency
|
|
70
|
+
name: rspec
|
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
|
72
|
+
requirements:
|
|
73
|
+
- - ">="
|
|
74
|
+
- !ruby/object:Gem::Version
|
|
75
|
+
version: 3.0.0.beta1
|
|
76
|
+
type: :development
|
|
77
|
+
prerelease: false
|
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
79
|
+
requirements:
|
|
80
|
+
- - ">="
|
|
81
|
+
- !ruby/object:Gem::Version
|
|
82
|
+
version: 3.0.0.beta1
|
|
27
83
|
description: ActiveModel serializer for Undo gem. Does not require anything from Rails
|
|
28
84
|
so is friendly to use with POROs.
|
|
29
85
|
email:
|
|
@@ -44,12 +100,17 @@ files:
|
|
|
44
100
|
- README.md
|
|
45
101
|
- Rakefile
|
|
46
102
|
- VERSION
|
|
47
|
-
- gemfiles/
|
|
48
|
-
- gemfiles/
|
|
49
|
-
- gemfiles/
|
|
50
|
-
- gemfiles/
|
|
51
|
-
- gemfiles/
|
|
103
|
+
- gemfiles/activerecord_3.1.gemfile
|
|
104
|
+
- gemfiles/activerecord_3.2.gemfile
|
|
105
|
+
- gemfiles/activerecord_4.0.gemfile
|
|
106
|
+
- gemfiles/activerecord_4.1.gemfile
|
|
107
|
+
- gemfiles/activerecord_head.gemfile
|
|
108
|
+
- gemfiles/undo_1.0.0.gemfile
|
|
109
|
+
- gemfiles/undo_head.gemfile
|
|
52
110
|
- lib/undo/serializer/active_model.rb
|
|
111
|
+
- lib/undo/serializer/active_model/connector.rb
|
|
112
|
+
- spec/integration/active_record_spec.rb
|
|
113
|
+
- spec/integration/undo_spec.rb
|
|
53
114
|
- spec/spec_helper.rb
|
|
54
115
|
- spec/support/active_record.rb
|
|
55
116
|
- spec/support/active_record/role.rb
|
|
@@ -57,7 +118,7 @@ files:
|
|
|
57
118
|
- spec/support/active_record/user.rb
|
|
58
119
|
- spec/support/ci_helper.rb
|
|
59
120
|
- spec/support/factories.rb
|
|
60
|
-
- spec/undo/serializer/
|
|
121
|
+
- spec/undo/serializer/active_model/connector_spec.rb
|
|
61
122
|
- spec/undo/serializer/active_model_spec.rb
|
|
62
123
|
- undo-serializer-active_model.gemspec
|
|
63
124
|
homepage: http://github.com/AlexParamonov/undo-serializer-active_model
|
|
@@ -86,6 +147,8 @@ specification_version: 4
|
|
|
86
147
|
summary: ActiveModel serializer for Undo gem. Does not require anything from Rails
|
|
87
148
|
so is friendly to use with POROs.
|
|
88
149
|
test_files:
|
|
150
|
+
- spec/integration/active_record_spec.rb
|
|
151
|
+
- spec/integration/undo_spec.rb
|
|
89
152
|
- spec/spec_helper.rb
|
|
90
153
|
- spec/support/active_record.rb
|
|
91
154
|
- spec/support/active_record/role.rb
|
|
@@ -93,5 +156,5 @@ test_files:
|
|
|
93
156
|
- spec/support/active_record/user.rb
|
|
94
157
|
- spec/support/ci_helper.rb
|
|
95
158
|
- spec/support/factories.rb
|
|
96
|
-
- spec/undo/serializer/
|
|
159
|
+
- spec/undo/serializer/active_model/connector_spec.rb
|
|
97
160
|
- spec/undo/serializer/active_model_spec.rb
|