userializer 0.1.3 → 0.3.0
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/.circleci/config.yml +18 -0
- data/.gitignore +1 -0
- data/README.md +173 -1
- data/lib/userializer.rb +1 -0
- data/lib/userializer/array_serializer.rb +17 -4
- data/lib/userializer/base_serializer.rb +2 -2
- data/lib/userializer/composite_serializer.rb +78 -0
- data/lib/userializer/has_many.rb +12 -2
- data/lib/userializer/has_one.rb +12 -5
- data/lib/userializer/version.rb +1 -1
- data/userializer.gemspec +2 -2
- metadata +12 -12
- data/Gemfile.lock +0 -50
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: f3ef32ea4a17b463844f6c5f59453e206253c59c21735ea9aa6e97c353db2c3d
|
4
|
+
data.tar.gz: 77c4cdcba82ef5a5470da04db24e2984ae7754d8ba25593c0097470f3c0fdf65
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 4e48196e2d4264d655eb4da209e7635c56f4849eac2e977522379f358ccf7969cd6189bf3fe5675a721ef3ac9f2e89392099541189ef97f503a1ed1c0ea94f4f
|
7
|
+
data.tar.gz: d8a897a3e951c27488e700fb1f80385501367088219ab7b24505f1a7420b478f5171734f4641d319c9b8d9bf2a119407a8f2012c1bf4d5e6926709b33c99c7db
|
@@ -0,0 +1,18 @@
|
|
1
|
+
version: 2
|
2
|
+
jobs:
|
3
|
+
run_tests:
|
4
|
+
docker:
|
5
|
+
- image: circleci/ruby:2.7
|
6
|
+
|
7
|
+
working_directory: ~/userializer
|
8
|
+
|
9
|
+
steps:
|
10
|
+
- checkout
|
11
|
+
- run: bundle install --path=vendor/bundle
|
12
|
+
- run: bundle exec rspec --color --require spec_helper --format progress spec
|
13
|
+
|
14
|
+
workflows:
|
15
|
+
version: 2
|
16
|
+
test:
|
17
|
+
jobs:
|
18
|
+
- run_tests
|
data/.gitignore
CHANGED
data/README.md
CHANGED
@@ -20,7 +20,179 @@ Or install it yourself as:
|
|
20
20
|
|
21
21
|
## Usage
|
22
22
|
|
23
|
-
|
23
|
+
USerializer's DSL is relatively close to Active Model Serializer's,
|
24
|
+
while having a few additional features including:
|
25
|
+
* Attributes Conditional Declaration
|
26
|
+
* Attributes Inline Definition
|
27
|
+
|
28
|
+
### Attributes Conditional Declaration
|
29
|
+
|
30
|
+
USerializer allows you to dynamically decide wether an attribute should
|
31
|
+
be serialized or not by passing its definition an `if` block as follows:
|
32
|
+
```ruby
|
33
|
+
attributes :conditional_attr, if: proc { |_, opts| ... }
|
34
|
+
```
|
35
|
+
|
36
|
+
Eg: Let's say you want to serialize an `Order` object but want to
|
37
|
+
include its `price` only if it's superior to *10*, your serializer
|
38
|
+
would look like the following:
|
39
|
+
```ruby
|
40
|
+
class Order < ActiveRecord::Base
|
41
|
+
def price
|
42
|
+
10
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
class OrderSerializer < USerializer::BaseSerializer
|
47
|
+
attributes :price, if: proc do |obj, _|
|
48
|
+
obj.price > 10
|
49
|
+
end
|
50
|
+
end
|
51
|
+
```
|
52
|
+
|
53
|
+
In that case for example, the `price` attribute would be omitted from
|
54
|
+
the final response.
|
55
|
+
|
56
|
+
### Attributes Inline Definition
|
57
|
+
|
58
|
+
Using AMS, the only way to rewrite an attribute prior to serialization
|
59
|
+
is to override it using a method with the same name, leading to
|
60
|
+
something like this:
|
61
|
+
```ruby
|
62
|
+
class MyObject < ActiveRecord::Base
|
63
|
+
def random_attr
|
64
|
+
0
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
class MyObjectSerializer < ActiveModel::Serializer
|
69
|
+
attributes :random_attr
|
70
|
+
|
71
|
+
def random_attr
|
72
|
+
object.random_attr + 1
|
73
|
+
end
|
74
|
+
end
|
75
|
+
```
|
76
|
+
|
77
|
+
While this code works perfectly, it pushes the serialized attribute
|
78
|
+
value definition back from its declaration, causing developers to lose
|
79
|
+
focus when listing their serialized attributes because the overriding is
|
80
|
+
done farther.
|
81
|
+
|
82
|
+
With USerializer, all of this is done in an inline way, so that you can
|
83
|
+
override the attribute's value while declaring using a block as
|
84
|
+
follows:
|
85
|
+
```ruby
|
86
|
+
attributes :your_attribute do |object, _|
|
87
|
+
...
|
88
|
+
end
|
89
|
+
```
|
90
|
+
|
91
|
+
Our `random_attr` serialization would then looks like this with
|
92
|
+
USerializer:
|
93
|
+
```ruby
|
94
|
+
class MyObjectSerializer < USerializer::BaseSerializer
|
95
|
+
attributes :random_attr do |object, _|
|
96
|
+
object.random_attr + 1
|
97
|
+
end
|
98
|
+
end
|
99
|
+
```
|
100
|
+
|
101
|
+
Way nicer, right?
|
102
|
+
|
103
|
+
### Relationships
|
104
|
+
|
105
|
+
Just like AMS, USerializer supports `has_one` and `has_many`
|
106
|
+
relationships
|
107
|
+
|
108
|
+
### Serialized Output
|
109
|
+
|
110
|
+
The following outputs will be based an on our `Order` object in
|
111
|
+
different situations:
|
112
|
+
|
113
|
+
* Order is serialized without any relationships:
|
114
|
+
```json
|
115
|
+
{
|
116
|
+
"order": {
|
117
|
+
"id": 1,
|
118
|
+
"attr_1": "value_1",
|
119
|
+
"attr_2": "value_2",
|
120
|
+
"attr_3": "value_3",
|
121
|
+
}
|
122
|
+
}
|
123
|
+
```
|
124
|
+
|
125
|
+
* Order has a `has_one` relationship with a `Client` model
|
126
|
+
```json
|
127
|
+
{
|
128
|
+
"clients": [
|
129
|
+
{
|
130
|
+
"id": 4,
|
131
|
+
"name": "userializer client",
|
132
|
+
...
|
133
|
+
}
|
134
|
+
],
|
135
|
+
"order": {
|
136
|
+
"id": 1,
|
137
|
+
"attr_1": "value_1",
|
138
|
+
"attr_2": "value_2",
|
139
|
+
"attr_3": "value_3",
|
140
|
+
"client_id": 4
|
141
|
+
}
|
142
|
+
}
|
143
|
+
```
|
144
|
+
|
145
|
+
* Order has a `has_many` relationship with an `Article` model
|
146
|
+
```json
|
147
|
+
{
|
148
|
+
"articles": [
|
149
|
+
{
|
150
|
+
"id": 1,
|
151
|
+
"name": "Article #1",
|
152
|
+
...
|
153
|
+
},
|
154
|
+
{
|
155
|
+
"id": 1,
|
156
|
+
"name": "Article #2",
|
157
|
+
...
|
158
|
+
}
|
159
|
+
],
|
160
|
+
"order": {
|
161
|
+
"id": 1,
|
162
|
+
"attr_1": "value_1",
|
163
|
+
"attr_2": "value_2",
|
164
|
+
"attr_3": "value_3",
|
165
|
+
"article_ids": [1, 2]
|
166
|
+
}
|
167
|
+
}
|
168
|
+
```
|
169
|
+
|
170
|
+
### CompositeSerializer
|
171
|
+
|
172
|
+
Imagine you have a compound of different data that you want to return to the same payload.
|
173
|
+
For example, you have an **array** of a `Foo` class and a `Bar` value to return.
|
174
|
+
You can use a `CompositeSerializer` to serialize both.
|
175
|
+
|
176
|
+
```ruby
|
177
|
+
array_foo = [Foo.new, Foo.new]
|
178
|
+
bar = Bar.new
|
179
|
+
|
180
|
+
CompositeSerializer.new(
|
181
|
+
{ key_foo: array_foo, key_bar: bar },
|
182
|
+
each_serializer: { key_foo: FooCustomSerializer },
|
183
|
+
serializer: { key_bar: BarSerializer },
|
184
|
+
root: { key_foo: :foo_root, key_bar: :bar_root }
|
185
|
+
).to_json
|
186
|
+
```
|
187
|
+
|
188
|
+
this will render:
|
189
|
+
|
190
|
+
```json
|
191
|
+
{
|
192
|
+
"foo_root": [{... foo1 attributes ...}, {... foo2 attributes ...}],
|
193
|
+
"bar_root": {... bar attributes ...}
|
194
|
+
}
|
195
|
+
```
|
24
196
|
|
25
197
|
## Development
|
26
198
|
|
data/lib/userializer.rb
CHANGED
@@ -19,14 +19,18 @@ module USerializer
|
|
19
19
|
ActiveSupport::Inflector.underscore(obj_class.name).split('/').last
|
20
20
|
).to_sym if obj_class
|
21
21
|
|
22
|
-
|
23
|
-
|
24
|
-
)
|
22
|
+
serializer = opts[:each_serializer]
|
23
|
+
|
24
|
+
@serializer = if serializer&.is_a?(Proc)
|
25
|
+
serializer
|
26
|
+
elsif serializer
|
27
|
+
proc { serializer }
|
28
|
+
end
|
25
29
|
end
|
26
30
|
|
27
31
|
def merge_root(res, opts)
|
28
32
|
@objs.each do |obj|
|
29
|
-
|
33
|
+
serializer(obj, opts).merge_root(res, @root_key, false, opts)
|
30
34
|
end
|
31
35
|
end
|
32
36
|
|
@@ -46,5 +50,14 @@ module USerializer
|
|
46
50
|
end
|
47
51
|
|
48
52
|
def scope; @opts[:scope]; end
|
53
|
+
|
54
|
+
private
|
55
|
+
|
56
|
+
def serializer(obj, opts)
|
57
|
+
return @serializer.call(obj, opts).new(obj, @opts) if @serializer
|
58
|
+
return obj.serialize if obj.respond_to?(:serialize)
|
59
|
+
|
60
|
+
USerializer.infered_serializer_class(obj.class).new(obj, @opts)
|
61
|
+
end
|
49
62
|
end
|
50
63
|
end
|
@@ -8,8 +8,8 @@ module USerializer
|
|
8
8
|
class BaseSerializer
|
9
9
|
class << self
|
10
10
|
def inherited(subclass)
|
11
|
-
subclass.attrs = self.attrs || { id: Attribute.new(:id, {}, nil) }
|
12
|
-
subclass.relations = self.relations || {}
|
11
|
+
subclass.attrs = self.attrs.dup || { id: Attribute.new(:id, {}, nil) }
|
12
|
+
subclass.relations = self.relations.dup || {}
|
13
13
|
end
|
14
14
|
|
15
15
|
def attributes(*attrs, &block)
|
@@ -0,0 +1,78 @@
|
|
1
|
+
require 'oj'
|
2
|
+
|
3
|
+
module USerializer
|
4
|
+
class CompositeObject
|
5
|
+
def initialize(obj, opts = {})
|
6
|
+
@obj = obj
|
7
|
+
@opts = opts
|
8
|
+
@root_key = opts[:root].to_sym
|
9
|
+
serializer = opts[:serializer]
|
10
|
+
@serializer = if serializer.is_a?(Proc)
|
11
|
+
serializer
|
12
|
+
elsif serializer
|
13
|
+
proc { serializer }
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
def merge_root(res, opts)
|
18
|
+
serializer(@obj, opts).merge_root(res, @root_key, true, opts)
|
19
|
+
end
|
20
|
+
|
21
|
+
private
|
22
|
+
|
23
|
+
def serializer(obj, opts)
|
24
|
+
return @serializer.call(obj, opts).new(obj, @opts) if @serializer
|
25
|
+
return obj.serialize if obj.respond_to?(:serialize)
|
26
|
+
|
27
|
+
USerializer.infered_serializer_class(obj.class).new(obj, @opts)
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
class CompositeSerializer
|
32
|
+
def initialize(objs, opts = {})
|
33
|
+
@opts = opts
|
34
|
+
@objs = compose_objs(objs)
|
35
|
+
end
|
36
|
+
|
37
|
+
def merge_root(res, opts)
|
38
|
+
@objs.each do |obj|
|
39
|
+
obj.merge_root(res, opts)
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
def to_hash
|
44
|
+
res = {}
|
45
|
+
|
46
|
+
merge_root(res, @opts)
|
47
|
+
res
|
48
|
+
end
|
49
|
+
|
50
|
+
def serialize(*_args)
|
51
|
+
to_hash
|
52
|
+
end
|
53
|
+
|
54
|
+
def to_json(*_args)
|
55
|
+
Oj.dump(to_hash, mode: :compat)
|
56
|
+
end
|
57
|
+
|
58
|
+
private
|
59
|
+
|
60
|
+
def compose_objs(objs)
|
61
|
+
objs.map do |(key, obj)|
|
62
|
+
opts = options_for(key)
|
63
|
+
|
64
|
+
if obj.is_a? Enumerable
|
65
|
+
ArraySerializer.new(obj, opts)
|
66
|
+
else
|
67
|
+
CompositeObject.new(obj, opts)
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
def options_for(key)
|
73
|
+
@opts.reduce({}) do |acc, (opt_key, values)|
|
74
|
+
acc.merge(opt_key.to_sym => values[key.to_sym])
|
75
|
+
end.compact.merge(root: key) { |_, x, y| x || y }
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
data/lib/userializer/has_many.rb
CHANGED
@@ -8,21 +8,31 @@ module USerializer
|
|
8
8
|
@opts = opts
|
9
9
|
@id_key = "#{ActiveSupport::Inflector.singularize(key)}_ids".to_sym
|
10
10
|
|
11
|
+
@embed_key = opts[:embed_key] || :id
|
11
12
|
@conditional_block = opts[:if] || proc { true }
|
12
13
|
end
|
13
14
|
|
14
15
|
def merge_attributes(res, ser, opts)
|
15
16
|
return unless @conditional_block.call(ser.object, opts)
|
16
17
|
|
17
|
-
res[@id_key] = (ser
|
18
|
+
res[@id_key] = (entities(ser) || []).compact.map do |obj|
|
19
|
+
obj.nil? ? nil : obj.send(@embed_key)
|
20
|
+
end.compact
|
18
21
|
end
|
19
22
|
|
20
23
|
def merge_root(res, ser, opts)
|
21
|
-
objs = ser
|
24
|
+
objs = entities(ser) || []
|
22
25
|
|
23
26
|
return if objs.empty? || !@conditional_block.call(ser.object, opts)
|
24
27
|
|
25
28
|
ArraySerializer.new(objs, @opts).merge_root(res, opts)
|
26
29
|
end
|
30
|
+
|
31
|
+
def entities(ser)
|
32
|
+
obj = ser.send(@key) || []
|
33
|
+
return obj unless @opts[:scope]
|
34
|
+
|
35
|
+
obj.send(@opts[:scope])
|
36
|
+
end
|
27
37
|
end
|
28
38
|
end
|
data/lib/userializer/has_one.rb
CHANGED
@@ -6,8 +6,15 @@ module USerializer
|
|
6
6
|
@id_key = "#{key}_id".to_sym
|
7
7
|
@root_key = opts[:root]&.to_sym
|
8
8
|
|
9
|
-
|
9
|
+
serializer = opts[:serializer]
|
10
10
|
|
11
|
+
@serializer = if serializer&.is_a?(Proc)
|
12
|
+
@serializer = serializer
|
13
|
+
elsif serializer
|
14
|
+
proc { serializer }
|
15
|
+
end
|
16
|
+
|
17
|
+
@embed_key = opts[:embed_key] || :id
|
11
18
|
@conditional_block = opts[:if] || proc { true }
|
12
19
|
end
|
13
20
|
|
@@ -17,7 +24,7 @@ module USerializer
|
|
17
24
|
return unless @conditional_block.call(ser.object, opts)
|
18
25
|
|
19
26
|
obj = ser.send(@key)
|
20
|
-
res[@id_key] = obj
|
27
|
+
res[@id_key] = obj.nil? ? nil : obj.send(@embed_key)
|
21
28
|
end
|
22
29
|
|
23
30
|
def merge_root(res, ser, opts)
|
@@ -25,13 +32,13 @@ module USerializer
|
|
25
32
|
|
26
33
|
return if obj.nil? || !@conditional_block.call(ser.object, opts)
|
27
34
|
|
28
|
-
serializer(obj).merge_root(res, root_key(obj), false, opts)
|
35
|
+
serializer(obj, opts).merge_root(res, root_key(obj), false, opts)
|
29
36
|
end
|
30
37
|
|
31
38
|
private
|
32
39
|
|
33
|
-
def serializer(obj)
|
34
|
-
return @serializer.new(obj, @opts) if @serializer
|
40
|
+
def serializer(obj, opts)
|
41
|
+
return @serializer.call(obj, opts).new(obj, @opts) if @serializer
|
35
42
|
return obj.serialize if obj.respond_to?(:serialize)
|
36
43
|
|
37
44
|
USerializer.infered_serializer_class(obj.class).new(obj, @opts)
|
data/lib/userializer/version.rb
CHANGED
data/userializer.gemspec
CHANGED
@@ -20,8 +20,8 @@ Gem::Specification.new do |spec|
|
|
20
20
|
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
21
21
|
spec.require_paths = ["lib"]
|
22
22
|
|
23
|
-
spec.add_development_dependency "bundler", "~>
|
24
|
-
spec.add_development_dependency "rake", "~>
|
23
|
+
spec.add_development_dependency "bundler", "~> 2.0"
|
24
|
+
spec.add_development_dependency "rake", "~> 13.0"
|
25
25
|
spec.add_development_dependency "rspec", "~> 3.0"
|
26
26
|
spec.add_dependency "oj"
|
27
27
|
spec.add_dependency "activesupport"
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: userializer
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.3.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Alexis Montagne
|
8
|
-
autorequire:
|
8
|
+
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2021-05-10 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -16,28 +16,28 @@ dependencies:
|
|
16
16
|
requirements:
|
17
17
|
- - "~>"
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version: '
|
19
|
+
version: '2.0'
|
20
20
|
type: :development
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
24
|
- - "~>"
|
25
25
|
- !ruby/object:Gem::Version
|
26
|
-
version: '
|
26
|
+
version: '2.0'
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
28
|
name: rake
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
30
30
|
requirements:
|
31
31
|
- - "~>"
|
32
32
|
- !ruby/object:Gem::Version
|
33
|
-
version: '
|
33
|
+
version: '13.0'
|
34
34
|
type: :development
|
35
35
|
prerelease: false
|
36
36
|
version_requirements: !ruby/object:Gem::Requirement
|
37
37
|
requirements:
|
38
38
|
- - "~>"
|
39
39
|
- !ruby/object:Gem::Version
|
40
|
-
version: '
|
40
|
+
version: '13.0'
|
41
41
|
- !ruby/object:Gem::Dependency
|
42
42
|
name: rspec
|
43
43
|
requirement: !ruby/object:Gem::Requirement
|
@@ -87,11 +87,11 @@ executables: []
|
|
87
87
|
extensions: []
|
88
88
|
extra_rdoc_files: []
|
89
89
|
files:
|
90
|
+
- ".circleci/config.yml"
|
90
91
|
- ".gitignore"
|
91
92
|
- ".rspec"
|
92
93
|
- ".travis.yml"
|
93
94
|
- Gemfile
|
94
|
-
- Gemfile.lock
|
95
95
|
- README.md
|
96
96
|
- Rakefile
|
97
97
|
- bin/console
|
@@ -100,6 +100,7 @@ files:
|
|
100
100
|
- lib/userializer/array_serializer.rb
|
101
101
|
- lib/userializer/attribute.rb
|
102
102
|
- lib/userializer/base_serializer.rb
|
103
|
+
- lib/userializer/composite_serializer.rb
|
103
104
|
- lib/userializer/has_many.rb
|
104
105
|
- lib/userializer/has_one.rb
|
105
106
|
- lib/userializer/version.rb
|
@@ -107,7 +108,7 @@ files:
|
|
107
108
|
homepage: https://github.com/upfluence/userializer
|
108
109
|
licenses: []
|
109
110
|
metadata: {}
|
110
|
-
post_install_message:
|
111
|
+
post_install_message:
|
111
112
|
rdoc_options: []
|
112
113
|
require_paths:
|
113
114
|
- lib
|
@@ -122,9 +123,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
122
123
|
- !ruby/object:Gem::Version
|
123
124
|
version: '0'
|
124
125
|
requirements: []
|
125
|
-
|
126
|
-
|
127
|
-
signing_key:
|
126
|
+
rubygems_version: 3.1.4
|
127
|
+
signing_key:
|
128
128
|
specification_version: 4
|
129
129
|
summary: Write a short summary, because RubyGems requires one.
|
130
130
|
test_files: []
|
data/Gemfile.lock
DELETED
@@ -1,50 +0,0 @@
|
|
1
|
-
PATH
|
2
|
-
remote: .
|
3
|
-
specs:
|
4
|
-
userializer (0.1.3)
|
5
|
-
activesupport
|
6
|
-
oj
|
7
|
-
|
8
|
-
GEM
|
9
|
-
remote: https://rubygems.org/
|
10
|
-
specs:
|
11
|
-
activesupport (5.2.3)
|
12
|
-
concurrent-ruby (~> 1.0, >= 1.0.2)
|
13
|
-
i18n (>= 0.7, < 2)
|
14
|
-
minitest (~> 5.1)
|
15
|
-
tzinfo (~> 1.1)
|
16
|
-
concurrent-ruby (1.1.5)
|
17
|
-
diff-lcs (1.3)
|
18
|
-
i18n (1.6.0)
|
19
|
-
concurrent-ruby (~> 1.0)
|
20
|
-
minitest (5.11.3)
|
21
|
-
oj (3.7.12)
|
22
|
-
rake (10.4.2)
|
23
|
-
rspec (3.8.0)
|
24
|
-
rspec-core (~> 3.8.0)
|
25
|
-
rspec-expectations (~> 3.8.0)
|
26
|
-
rspec-mocks (~> 3.8.0)
|
27
|
-
rspec-core (3.8.0)
|
28
|
-
rspec-support (~> 3.8.0)
|
29
|
-
rspec-expectations (3.8.3)
|
30
|
-
diff-lcs (>= 1.2.0, < 2.0)
|
31
|
-
rspec-support (~> 3.8.0)
|
32
|
-
rspec-mocks (3.8.0)
|
33
|
-
diff-lcs (>= 1.2.0, < 2.0)
|
34
|
-
rspec-support (~> 3.8.0)
|
35
|
-
rspec-support (3.8.0)
|
36
|
-
thread_safe (0.3.6)
|
37
|
-
tzinfo (1.2.5)
|
38
|
-
thread_safe (~> 0.1)
|
39
|
-
|
40
|
-
PLATFORMS
|
41
|
-
ruby
|
42
|
-
|
43
|
-
DEPENDENCIES
|
44
|
-
bundler (~> 1.16)
|
45
|
-
rake (~> 10.0)
|
46
|
-
rspec (~> 3.0)
|
47
|
-
userializer!
|
48
|
-
|
49
|
-
BUNDLED WITH
|
50
|
-
1.16.1
|