conglomerate 0.7.0 → 0.8.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitignore +1 -0
- data/conglomerate.gemspec +1 -1
- data/lib/conglomerate/array.rb +30 -0
- data/lib/conglomerate/collection.rb +15 -0
- data/lib/conglomerate/datum.rb +9 -0
- data/lib/conglomerate/error.rb +9 -0
- data/lib/conglomerate/item.rb +10 -0
- data/lib/conglomerate/link.rb +11 -0
- data/lib/conglomerate/particle.rb +73 -0
- data/lib/conglomerate/query.rb +12 -0
- data/lib/conglomerate/root.rb +6 -0
- data/lib/conglomerate/template.rb +7 -0
- data/lib/conglomerate/tree_deserializer.rb +53 -0
- data/lib/conglomerate/tree_serializer.rb +48 -0
- data/lib/conglomerate/version.rb +1 -1
- data/lib/conglomerate.rb +15 -0
- data/spec/collection_spec.rb +40 -0
- data/spec/datum_spec.rb +23 -0
- data/spec/link_spec.rb +14 -0
- data/spec/particle_spec.rb +30 -0
- data/spec/query_spec.rb +30 -0
- data/spec/tree_deserializer_spec.rb +38 -0
- metadata +27 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: f9f3f14b27e132968770842dd2d3fe7796a25fbc
|
4
|
+
data.tar.gz: 2174933a1f8470094242bbb92f77f967aaaa0dfc
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 080da2cec601bb44e310a6afad4dad3560bd47aa56f2de7feb0f9aef7ced1049fe5547d15028965583fe47e66486c42f9ad909458e7743ca0449635bfd211770
|
7
|
+
data.tar.gz: f5b2ea4b96a812f0f54d5b12a0f5bf5212d8af9d8441d4d8397bfe6586a63f8bfd7594eb21a0ed8236fb1fcaff88fe62b83813ce29b6a2e16b0fa9099e430218
|
data/.gitignore
CHANGED
data/conglomerate.gemspec
CHANGED
@@ -6,7 +6,7 @@ require "conglomerate/version"
|
|
6
6
|
Gem::Specification.new do |spec|
|
7
7
|
spec.name = "conglomerate"
|
8
8
|
spec.version = Conglomerate::VERSION
|
9
|
-
spec.authors = ["Shane Emmons"]
|
9
|
+
spec.authors = ["Shane Emmons", "Emily Dobervich"]
|
10
10
|
spec.email = ["oss@teamsnap.com"]
|
11
11
|
spec.summary = "A library to serialize Ruby objects into collection+json"
|
12
12
|
spec.description = "A library to serialize Ruby objects into collection+json"
|
@@ -0,0 +1,30 @@
|
|
1
|
+
module Conglomerate
|
2
|
+
class Array
|
3
|
+
include Enumerable
|
4
|
+
|
5
|
+
def initialize(type)
|
6
|
+
self.type = type
|
7
|
+
self.storage = []
|
8
|
+
end
|
9
|
+
|
10
|
+
def <<(val)
|
11
|
+
if type
|
12
|
+
raise "TypeMismatch" unless val.is_a?(type)
|
13
|
+
end
|
14
|
+
|
15
|
+
storage << val
|
16
|
+
end
|
17
|
+
|
18
|
+
def empty?
|
19
|
+
storage.empty?
|
20
|
+
end
|
21
|
+
|
22
|
+
def each(&block)
|
23
|
+
storage.each(&block)
|
24
|
+
end
|
25
|
+
|
26
|
+
private
|
27
|
+
|
28
|
+
attr_accessor :storage, :type
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
module Conglomerate
|
2
|
+
class Collection
|
3
|
+
include Particle
|
4
|
+
|
5
|
+
attribute :version, :default => "1.0"
|
6
|
+
attribute :href
|
7
|
+
|
8
|
+
attribute :template, :type => Template
|
9
|
+
attribute :error, :type => Error
|
10
|
+
|
11
|
+
array :items, :contains => Item
|
12
|
+
array :links, :contains => Link
|
13
|
+
array :queries, :contains => Query
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,11 @@
|
|
1
|
+
module Conglomerate
|
2
|
+
class Link
|
3
|
+
include Conglomerate::Particle
|
4
|
+
|
5
|
+
attribute :href, :type => String, :required => true
|
6
|
+
attribute :rel, :type => String, :required => true
|
7
|
+
attribute :name, :type => String
|
8
|
+
attribute :render, :type => String
|
9
|
+
attribute :prompt, :type => String
|
10
|
+
end
|
11
|
+
end
|
@@ -0,0 +1,73 @@
|
|
1
|
+
module Conglomerate
|
2
|
+
module Particle
|
3
|
+
def self.included(object)
|
4
|
+
object.send(:extend, ClassMethods)
|
5
|
+
end
|
6
|
+
|
7
|
+
def initialize(attributes = {})
|
8
|
+
self.class.attributes.each do |attr, attr_metadata|
|
9
|
+
if attr_metadata[:required]
|
10
|
+
raise "MissingAttribute" unless attributes[attr] || attributes[attr.to_s]
|
11
|
+
end
|
12
|
+
|
13
|
+
if attr_metadata[:type] == :array
|
14
|
+
self.instance_variable_set("@#{attr}", Conglomerate::Array.new(attr_metadata[:contains]))
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
attributes.each do |key, value|
|
19
|
+
attrs = self.class.attributes
|
20
|
+
if attrs[key.to_sym] && attrs[key.to_sym][:type] == :array
|
21
|
+
array = value
|
22
|
+
value = Conglomerate::Array.new(attrs[key.to_sym][:contains])
|
23
|
+
array.each { |item| value << item }
|
24
|
+
self.instance_variable_set("@#{key}", value)
|
25
|
+
end
|
26
|
+
|
27
|
+
self.send("#{key}=", value) if self.respond_to?("#{key}=")
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
private
|
32
|
+
|
33
|
+
module ClassMethods
|
34
|
+
def self.extended(klass)
|
35
|
+
klass.instance_variable_set("@attributes", {})
|
36
|
+
end
|
37
|
+
|
38
|
+
def attributes
|
39
|
+
instance_variable_get("@attributes").dup
|
40
|
+
end
|
41
|
+
|
42
|
+
private
|
43
|
+
|
44
|
+
def array(attr, contains: nil, cull: true)
|
45
|
+
attribute(attr, :type => :array, :contains => contains, :cull => cull)
|
46
|
+
end
|
47
|
+
|
48
|
+
def attribute(attr, default: nil, type: nil, contains: nil, cull: true, required: nil)
|
49
|
+
instance_variable_get("@attributes")[attr] = {
|
50
|
+
:default => default,
|
51
|
+
:type => type,
|
52
|
+
:contains => contains,
|
53
|
+
:cull => cull,
|
54
|
+
:required => required
|
55
|
+
}
|
56
|
+
|
57
|
+
self.send(:attr_reader, attr)
|
58
|
+
|
59
|
+
if type != :array
|
60
|
+
self.send(:define_method, :"#{attr}=") do |val|
|
61
|
+
attr_metadata = self.class.attributes[attr]
|
62
|
+
|
63
|
+
if type = attr_metadata[:type]
|
64
|
+
raise "TypeMismatch" if !val.is_a?(type)
|
65
|
+
end
|
66
|
+
|
67
|
+
self.instance_variable_set("@#{attr}", val)
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
@@ -0,0 +1,12 @@
|
|
1
|
+
module Conglomerate
|
2
|
+
class Query
|
3
|
+
include Conglomerate::Particle
|
4
|
+
|
5
|
+
attribute :href, :type => String, :required => true
|
6
|
+
attribute :rel, :type => String, :required => true
|
7
|
+
attribute :name, :type => String
|
8
|
+
attribute :prompt, :type => String
|
9
|
+
|
10
|
+
array :data, :contains => Datum
|
11
|
+
end
|
12
|
+
end
|
@@ -0,0 +1,53 @@
|
|
1
|
+
module Conglomerate
|
2
|
+
class TreeDeserializer
|
3
|
+
PARTICLES = [Collection, Item, Error, Template, Datum, Query, Item]
|
4
|
+
|
5
|
+
def initialize(object)
|
6
|
+
self.object = object
|
7
|
+
end
|
8
|
+
|
9
|
+
def deserialize(item = object)
|
10
|
+
raise "ObjectNotCollectionRoot" if !object["collection"]
|
11
|
+
deserialize_particle(object["collection"], Collection)
|
12
|
+
end
|
13
|
+
|
14
|
+
private
|
15
|
+
|
16
|
+
attr_accessor :object
|
17
|
+
|
18
|
+
def deserialize_particle(object, klass)
|
19
|
+
attributes = {}
|
20
|
+
attribute_info = klass.attributes
|
21
|
+
|
22
|
+
attribute_info.each do |attr, attr_metadata|
|
23
|
+
attr = attr.to_s
|
24
|
+
if object[attr]
|
25
|
+
attributes[attr] = deserialize_attribute(object[attr], attr_metadata)
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
particle = klass.new(attributes)
|
30
|
+
end
|
31
|
+
|
32
|
+
def deserialize_attribute(attribute, attr_metadata)
|
33
|
+
if PARTICLES.include?(attr_metadata[:type])
|
34
|
+
deserialize_particle(attribute, attr_metadata[:type])
|
35
|
+
elsif attr_metadata[:type] == :array
|
36
|
+
raise "ArrayExpected" unless attribute.is_a?(::Array)
|
37
|
+
deserialize_array(attribute, attr_metadata[:contains])
|
38
|
+
else
|
39
|
+
attribute
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
def deserialize_array(items, contains)
|
44
|
+
array = Conglomerate::Array.new(contains)
|
45
|
+
|
46
|
+
items.each do |item|
|
47
|
+
array << deserialize_particle(item, contains)
|
48
|
+
end
|
49
|
+
|
50
|
+
array
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
@@ -0,0 +1,48 @@
|
|
1
|
+
module Conglomerate
|
2
|
+
class TreeSerializer
|
3
|
+
def initialize(object)
|
4
|
+
self.object = object
|
5
|
+
end
|
6
|
+
|
7
|
+
def serialize(item = object)
|
8
|
+
if Conglomerate::Particle === item
|
9
|
+
serialize_particle(item)
|
10
|
+
elsif Conglomerate::Array === item
|
11
|
+
serialize_array(item)
|
12
|
+
elsif Array === item
|
13
|
+
serialize_array(item)
|
14
|
+
elsif item.is_a?(Numeric) || item.is_a?(String) || item.nil?
|
15
|
+
item
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
private
|
20
|
+
|
21
|
+
attr_accessor :object
|
22
|
+
|
23
|
+
def serialize_particle(particle)
|
24
|
+
attributes = particle.class.attributes
|
25
|
+
|
26
|
+
attributes.inject({}) do |hash, (attr, attr_metadata)|
|
27
|
+
hash.tap do |h|
|
28
|
+
attribute = particle.send(attr)
|
29
|
+
attribute ||= attr_metadata[:default]
|
30
|
+
|
31
|
+
unless attr_metadata[:cull] && cull_attribute(attribute)
|
32
|
+
h[attr.to_s] = serialize(attribute)
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
def serialize_array(array)
|
39
|
+
array.map do |item|
|
40
|
+
serialize(item)
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
def cull_attribute(attribute)
|
45
|
+
!attribute || (Conglomerate::Array === attribute && attribute.empty?)
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
data/lib/conglomerate/version.rb
CHANGED
data/lib/conglomerate.rb
CHANGED
@@ -1,6 +1,21 @@
|
|
1
|
+
require_relative "conglomerate/tree_serializer"
|
2
|
+
require_relative "conglomerate/array"
|
3
|
+
require_relative "conglomerate/particle"
|
1
4
|
require_relative "conglomerate/serializer"
|
5
|
+
require_relative "conglomerate/link"
|
6
|
+
require_relative "conglomerate/error"
|
7
|
+
require_relative "conglomerate/datum"
|
8
|
+
require_relative "conglomerate/template"
|
9
|
+
require_relative "conglomerate/item"
|
10
|
+
require_relative "conglomerate/query"
|
11
|
+
require_relative "conglomerate/collection"
|
12
|
+
require_relative "conglomerate/tree_deserializer"
|
2
13
|
|
3
14
|
module Conglomerate
|
15
|
+
def self.serialize(serializable)
|
16
|
+
Conglomerate::TreeSerializer.new(serializable).serialize
|
17
|
+
end
|
18
|
+
|
4
19
|
def self.serializer
|
5
20
|
Module.new do
|
6
21
|
def self.included(descendant)
|
@@ -0,0 +1,40 @@
|
|
1
|
+
require_relative "spec_helper"
|
2
|
+
require_relative "../lib/conglomerate"
|
3
|
+
|
4
|
+
describe Conglomerate::Collection do
|
5
|
+
let(:collection) { Conglomerate::Collection.new }
|
6
|
+
subject(:serialized_empty_collection) { Conglomerate.serialize(collection) }
|
7
|
+
subject(:reference_empty_collection) {
|
8
|
+
{
|
9
|
+
"version" => "1.0"
|
10
|
+
}
|
11
|
+
}
|
12
|
+
|
13
|
+
it "empty collection serializes properly" do
|
14
|
+
expect(serialized_empty_collection).to eq(reference_empty_collection)
|
15
|
+
end
|
16
|
+
|
17
|
+
context "links" do
|
18
|
+
it "serializes links correctly" do
|
19
|
+
link = Conglomerate::Link.new(
|
20
|
+
:href => "http://this.is.a.link",
|
21
|
+
:rel => "Something"
|
22
|
+
)
|
23
|
+
|
24
|
+
collection.links << link
|
25
|
+
expect(Conglomerate.serialize(collection)["links"]).to include(Conglomerate.serialize(link))
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
context "queries" do
|
30
|
+
it "serializes queries correctly" do
|
31
|
+
query = Conglomerate::Query.new(
|
32
|
+
:href => "http://this.is.a.query",
|
33
|
+
:rel => "Something"
|
34
|
+
)
|
35
|
+
|
36
|
+
collection.queries << query
|
37
|
+
expect(Conglomerate.serialize(collection)["queries"]).to include(Conglomerate.serialize(query))
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
data/spec/datum_spec.rb
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
require_relative "spec_helper"
|
2
|
+
require_relative "../lib/conglomerate"
|
3
|
+
|
4
|
+
describe Conglomerate::Datum do
|
5
|
+
context "required attributes" do
|
6
|
+
specify "name" do
|
7
|
+
expect { Conglomerate::Datum.new }.to raise_error("MissingAttribute")
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
context "optional attributes" do
|
12
|
+
specify "value" do
|
13
|
+
datum = Conglomerate::Datum.new(:name => "name")
|
14
|
+
expect(datum).to respond_to(:"value=")
|
15
|
+
end
|
16
|
+
|
17
|
+
specify "prompt" do
|
18
|
+
datum = Conglomerate::Datum.new(:name => "name")
|
19
|
+
expect(datum).to respond_to(:"prompt=")
|
20
|
+
expect { datum.prompt = 3 }.to raise_error
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
data/spec/link_spec.rb
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
require_relative "spec_helper"
|
2
|
+
require_relative "../lib/conglomerate"
|
3
|
+
|
4
|
+
describe Conglomerate::Link do
|
5
|
+
context "required attributes" do
|
6
|
+
specify "href" do
|
7
|
+
expect { Conglomerate::Link.new(:rel => "") }.to raise_error("MissingAttribute")
|
8
|
+
end
|
9
|
+
|
10
|
+
specify "rel" do
|
11
|
+
expect { Conglomerate::Link.new(:href => "") }.to raise_error("MissingAttribute")
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
require_relative "spec_helper"
|
2
|
+
require_relative "../lib/conglomerate"
|
3
|
+
|
4
|
+
class ParticleTest
|
5
|
+
include Conglomerate::Particle
|
6
|
+
|
7
|
+
attribute :default, :default => "this is the default value"
|
8
|
+
attribute :string, :type => String
|
9
|
+
end
|
10
|
+
|
11
|
+
describe Conglomerate::Particle do
|
12
|
+
subject(:serialized_particle_test) { Conglomerate.serialize(ParticleTest.new) }
|
13
|
+
subject(:mass_assigned) { ParticleTest.new(:string => "An string", :default => "Not an default") }
|
14
|
+
|
15
|
+
it "default values are exposed when serialized" do
|
16
|
+
expect(serialized_particle_test["default"]).to eq("this is the default value")
|
17
|
+
end
|
18
|
+
|
19
|
+
it "enforces type on attributes" do
|
20
|
+
particle_test = ParticleTest.new
|
21
|
+
expect {
|
22
|
+
particle_test.string = 1
|
23
|
+
}.to raise_error("TypeMismatch")
|
24
|
+
end
|
25
|
+
|
26
|
+
it "allows mass-assignment via constructor" do
|
27
|
+
expect(mass_assigned.string).to eq("An string")
|
28
|
+
expect(mass_assigned.default).to eq("Not an default")
|
29
|
+
end
|
30
|
+
end
|
data/spec/query_spec.rb
ADDED
@@ -0,0 +1,30 @@
|
|
1
|
+
require_relative "spec_helper"
|
2
|
+
require_relative "../lib/conglomerate"
|
3
|
+
|
4
|
+
describe Conglomerate::Query do
|
5
|
+
let(:query) {
|
6
|
+
Conglomerate::Query.new(
|
7
|
+
:href => "http://this.is.a.query/",
|
8
|
+
:rel => "some_query"
|
9
|
+
)
|
10
|
+
}
|
11
|
+
|
12
|
+
context "required attributes" do
|
13
|
+
specify "href" do
|
14
|
+
expect { Conglomerate::Query.new(:rel => "") }.to raise_error("MissingAttribute")
|
15
|
+
end
|
16
|
+
|
17
|
+
specify "rel" do
|
18
|
+
expect { Conglomerate::Query.new(:href => "") }.to raise_error("MissingAttribute")
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
context "data" do
|
23
|
+
it "serializes properly" do
|
24
|
+
datum = Conglomerate::Datum.new(:name => "name")
|
25
|
+
|
26
|
+
query.data << datum
|
27
|
+
expect(Conglomerate.serialize(query)["data"]).to include(Conglomerate.serialize(datum))
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
require_relative "spec_helper"
|
2
|
+
require_relative "../lib/conglomerate"
|
3
|
+
|
4
|
+
require "json"
|
5
|
+
|
6
|
+
describe Conglomerate::TreeDeserializer do
|
7
|
+
it "deserializes collection with error" do
|
8
|
+
json = '{"collection":{"version":"1.0","href":"https://apiv3.teamsnap.com/","links":[{"rel":"root","href":"https://apiv3.teamsnap.com/"},{"rel":"self","href":"https://apiv3.teamsnap.com/"}],"error":{"message":"translation missing: en.errors.messages.unauthorized"}}}'
|
9
|
+
obj = JSON.parse(json)
|
10
|
+
deserializer = Conglomerate::TreeDeserializer.new(obj)
|
11
|
+
tree = deserializer.deserialize
|
12
|
+
|
13
|
+
expect(tree.class).to eq(Conglomerate::Collection)
|
14
|
+
expect(tree.error.class).to eq(Conglomerate::Error)
|
15
|
+
expect(tree.href).to eq("https://apiv3.teamsnap.com/")
|
16
|
+
end
|
17
|
+
|
18
|
+
it "deserializes collection with items" do
|
19
|
+
obj = {
|
20
|
+
"collection" => {
|
21
|
+
"version" => "1.0",
|
22
|
+
"href" => "http://example.com/",
|
23
|
+
"items" => [
|
24
|
+
{ "href" => "http://example.com/1", "data" => [{
|
25
|
+
"name" => "is_unicorn", "value" => true
|
26
|
+
}]}
|
27
|
+
]
|
28
|
+
}
|
29
|
+
}
|
30
|
+
|
31
|
+
deserializer = Conglomerate::TreeDeserializer.new(obj)
|
32
|
+
tree = deserializer.deserialize
|
33
|
+
|
34
|
+
expect(
|
35
|
+
tree.items.first.data.find { |datum| datum.name == "is_unicorn" }.value
|
36
|
+
).to eq(true)
|
37
|
+
end
|
38
|
+
end
|
metadata
CHANGED
@@ -1,14 +1,15 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: conglomerate
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.8.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Shane Emmons
|
8
|
+
- Emily Dobervich
|
8
9
|
autorequire:
|
9
10
|
bindir: bin
|
10
11
|
cert_chain: []
|
11
|
-
date: 2014-
|
12
|
+
date: 2014-05-13 00:00:00.000000000 Z
|
12
13
|
dependencies:
|
13
14
|
- !ruby/object:Gem::Dependency
|
14
15
|
name: bundler
|
@@ -66,10 +67,28 @@ files:
|
|
66
67
|
- Rakefile
|
67
68
|
- conglomerate.gemspec
|
68
69
|
- lib/conglomerate.rb
|
70
|
+
- lib/conglomerate/array.rb
|
71
|
+
- lib/conglomerate/collection.rb
|
72
|
+
- lib/conglomerate/datum.rb
|
73
|
+
- lib/conglomerate/error.rb
|
74
|
+
- lib/conglomerate/item.rb
|
75
|
+
- lib/conglomerate/link.rb
|
76
|
+
- lib/conglomerate/particle.rb
|
77
|
+
- lib/conglomerate/query.rb
|
78
|
+
- lib/conglomerate/root.rb
|
69
79
|
- lib/conglomerate/serializer.rb
|
80
|
+
- lib/conglomerate/template.rb
|
81
|
+
- lib/conglomerate/tree_deserializer.rb
|
82
|
+
- lib/conglomerate/tree_serializer.rb
|
70
83
|
- lib/conglomerate/version.rb
|
84
|
+
- spec/collection_spec.rb
|
71
85
|
- spec/conglomerate_spec.rb
|
86
|
+
- spec/datum_spec.rb
|
87
|
+
- spec/link_spec.rb
|
88
|
+
- spec/particle_spec.rb
|
89
|
+
- spec/query_spec.rb
|
72
90
|
- spec/spec_helper.rb
|
91
|
+
- spec/tree_deserializer_spec.rb
|
73
92
|
homepage: https://github.com/teamsnap/conglomerate
|
74
93
|
licenses:
|
75
94
|
- MIT
|
@@ -95,5 +114,11 @@ signing_key:
|
|
95
114
|
specification_version: 4
|
96
115
|
summary: A library to serialize Ruby objects into collection+json
|
97
116
|
test_files:
|
117
|
+
- spec/collection_spec.rb
|
98
118
|
- spec/conglomerate_spec.rb
|
119
|
+
- spec/datum_spec.rb
|
120
|
+
- spec/link_spec.rb
|
121
|
+
- spec/particle_spec.rb
|
122
|
+
- spec/query_spec.rb
|
99
123
|
- spec/spec_helper.rb
|
124
|
+
- spec/tree_deserializer_spec.rb
|