cot 0.1.3 → 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Gemfile.lock +1 -1
- data/README.md +26 -1
- data/lib/cot.rb +1 -3
- data/lib/cot/collection.rb +55 -0
- data/lib/cot/frame.rb +7 -0
- data/lib/cot/version.rb +1 -1
- data/spec/lib/cot/collection_spec.rb +120 -0
- data/spec/lib/cot/frame_spec.rb +26 -0
- data/spec/spec_helper.rb +3 -0
- metadata +6 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: b47b0825bf582a0dded1ff4736bef69945d6f485
|
4
|
+
data.tar.gz: f10875feef7630460c617c154dd6564bb1eb210a
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: b1c6d69f790c266a5e73a29d4ed74dbb491d0f2111a3f1224c03abcc87e4520822ebd094e8a6979a77ede993cfb64a5e78187ce1a506468c5c8a62e0ba5f20e2
|
7
|
+
data.tar.gz: 155a93d43a4b96ed4f71d3e4e08653c251b4235ba4d35f53d61396327136e103b3a8972b66e809bd96a9896764f29bbe24d52e85e2275412a36b5c42fcb696b7
|
data/Gemfile.lock
CHANGED
data/README.md
CHANGED
@@ -5,12 +5,13 @@ Cot is a gem designed to help convert rest based resources into ruby objects. C
|
|
5
5
|
|
6
6
|
### Usage
|
7
7
|
|
8
|
-
Using cot is pretty simple,
|
8
|
+
Using cot is pretty simple. There are two main classes: Collection and Frame. Collections are basically big arrays that contain objects (presumably Frame objects). Collection provides some helper methods to manage the collection, but also delegates to Array, so each, map and all that good stuff are there as well. Frame allows you to declare how the object will convert a json payload into an object.
|
9
9
|
|
10
10
|
Frame provides some helpful methods:
|
11
11
|
- Class Methods
|
12
12
|
- property adds the first parameter as an accessor on the object. There are two optional arguments, from and searchable. From indicates that the property has an alternate key in the incoming/outgoing data. Searchable adds the property to the search mappings.
|
13
13
|
- search\_property adds the parameter to the search mapping. It takes an optional from argument which inidates the property has an alternate key in the incoming/outgoing data.
|
14
|
+
- enum *NOT SUPPORTED* If you'd like to see this let me know. Also let me know what you'd want it to look like.
|
14
15
|
- Instance Methods
|
15
16
|
- defined\_properties returns a list of the defined properties
|
16
17
|
- properties\_mapping returns a hash containing all of the renamed properties. The keys are the values of the from argument and the values are the property name.
|
@@ -19,6 +20,18 @@ Frame provides some helpful methods:
|
|
19
20
|
- inverted\_search\_mappings returns an inverted search\_mappings hash.
|
20
21
|
- serializable\_hash returns hash with the correct keys to post back. AKA, it reverts the keys to what the from arguments (if any) were.
|
21
22
|
- to\_json returns a json encoded version of serializable\_hash.
|
23
|
+
- valid? true if errors is empty
|
24
|
+
- errors used to store any errors associated with the object
|
25
|
+
|
26
|
+
Collection provides the following methods:
|
27
|
+
- Instance Methods
|
28
|
+
- The following methods collate the results from members
|
29
|
+
- serializable\_hash
|
30
|
+
- to\_json
|
31
|
+
- errors (pulls into a hash with member.id as the key)
|
32
|
+
- exists? returns true if *all* the members exist
|
33
|
+
- changed? returns true if *any* of the members have changed
|
34
|
+
- update\_members updates the members of the collection to based on the payload (this can add or remove members)
|
22
35
|
|
23
36
|
```ruby
|
24
37
|
class ExampleObject < Cot::Frame
|
@@ -28,9 +41,21 @@ class ExampleObject < Cot::Frame
|
|
28
41
|
search_property :created_at, :from => :createdOn
|
29
42
|
end
|
30
43
|
|
44
|
+
class ExampleCollection < Cot::Collection
|
45
|
+
def initialize(params)
|
46
|
+
super ExampleObject, params
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
31
50
|
thingy = ExampleObject.new(id: :my_id, name: 'awesome name', createdOn: Time.now)
|
32
51
|
thingy.id # 5
|
33
52
|
thingy.name # awesome name
|
34
53
|
thingy.created_at # what time it is now
|
35
54
|
thingy.defined\_properties # [:id, :name, :created_at]
|
55
|
+
|
56
|
+
collection = ExampleCollection.new [{ id: :my_id, name: 'awesome name', createdOn: Time.now }, { id: :my_id, name: 'awesome name', createdOn: Time.now }]
|
57
|
+
collection.first.name # 'awesome name'
|
58
|
+
collection.exists? # Do all of the entries exist?
|
59
|
+
collection.update_members [{ id: 1, name: 'new awesome name', createdOn: Time.now }, { id: 2, name: 'new awesome name', createdOn: Time.now }]
|
60
|
+
collection.first.name # 'new awesome name'
|
36
61
|
```
|
data/lib/cot.rb
CHANGED
@@ -0,0 +1,55 @@
|
|
1
|
+
module Cot
|
2
|
+
class Collection < SimpleDelegator
|
3
|
+
def initialize(klass, objects, sub_key = false)
|
4
|
+
@klass = klass
|
5
|
+
@sub_key = sub_key
|
6
|
+
@objects = objects
|
7
|
+
|
8
|
+
# If you pass in different types of things here we can't be friends
|
9
|
+
initialize_objects(objects) unless objects.first.is_a? klass
|
10
|
+
|
11
|
+
super @objects
|
12
|
+
end
|
13
|
+
|
14
|
+
def serializable_hash
|
15
|
+
@objects.map(&:serializable_hash)
|
16
|
+
end
|
17
|
+
|
18
|
+
def to_json
|
19
|
+
serializable_hash.to_json
|
20
|
+
end
|
21
|
+
|
22
|
+
def exists?
|
23
|
+
@objects.map(&:exists?).all?
|
24
|
+
end
|
25
|
+
|
26
|
+
def errors
|
27
|
+
Hash[@objects.reject { |x| x.valid? }.map { |x| [x.id, x.errors] }]
|
28
|
+
end
|
29
|
+
|
30
|
+
def update_members(payload)
|
31
|
+
# NOTE: replacing objects is lazy, but I don't want to deal with updating and such right now
|
32
|
+
initialize_objects(payload)
|
33
|
+
end
|
34
|
+
|
35
|
+
def changed?
|
36
|
+
@objects.map(&:changed?).include? true
|
37
|
+
end
|
38
|
+
|
39
|
+
private
|
40
|
+
|
41
|
+
def initialize_objects(objects)
|
42
|
+
@objects = []
|
43
|
+
@objects = objects.map do |payload|
|
44
|
+
if @sub_key
|
45
|
+
@klass.new payload[@sub_key]
|
46
|
+
else
|
47
|
+
@klass.new payload
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
# Set the delegator methods to point to the new objects array
|
52
|
+
__setobj__(@objects)
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
data/lib/cot/frame.rb
CHANGED
@@ -6,6 +6,7 @@ module Cot
|
|
6
6
|
include ActiveModel::Dirty
|
7
7
|
|
8
8
|
def initialize(payload = {})
|
9
|
+
@errors = {}
|
9
10
|
@data = convert_keys payload
|
10
11
|
end
|
11
12
|
|
@@ -68,6 +69,8 @@ module Cot
|
|
68
69
|
define_attribute_method name
|
69
70
|
end
|
70
71
|
|
72
|
+
attr_accessor :errors
|
73
|
+
|
71
74
|
def [](key)
|
72
75
|
@data[convert_key key]
|
73
76
|
end
|
@@ -76,6 +79,10 @@ module Cot
|
|
76
79
|
@data[convert_key key] = value
|
77
80
|
end
|
78
81
|
|
82
|
+
def valid?
|
83
|
+
errors.empty?
|
84
|
+
end
|
85
|
+
|
79
86
|
def to_json
|
80
87
|
serializable_hash.to_json
|
81
88
|
end
|
data/lib/cot/version.rb
CHANGED
@@ -0,0 +1,120 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
class FakeDouble < Cot::Frame
|
3
|
+
property :id
|
4
|
+
property :foo
|
5
|
+
property :fooy
|
6
|
+
end
|
7
|
+
|
8
|
+
describe Cot::Collection do
|
9
|
+
let(:obj1) { FakeDouble.new id: 1, foo: :bar }
|
10
|
+
let(:obj2) { FakeDouble.new id: 2, foo: :bar }
|
11
|
+
subject(:collection) { Cot::Collection.new FakeDouble, [obj1, obj2] }
|
12
|
+
|
13
|
+
context 'array like' do
|
14
|
+
it 'should take an array of objects and store them in a hash' do
|
15
|
+
expect(collection.length).to eq 2
|
16
|
+
end
|
17
|
+
|
18
|
+
it 'should respond to array methods' do
|
19
|
+
|
20
|
+
# In theory we'd test more, but that's good enough for me
|
21
|
+
expect(collection).to respond_to :[]
|
22
|
+
expect(collection).to respond_to :first
|
23
|
+
expect(collection).to respond_to :reverse
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
context 'serializable_hash' do
|
28
|
+
it 'is an array' do
|
29
|
+
expect(collection.serializable_hash).to be_kind_of Array
|
30
|
+
end
|
31
|
+
|
32
|
+
it 'has hash members' do
|
33
|
+
expect(collection.serializable_hash.first).to be_kind_of Hash
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
context 'to_json' do
|
38
|
+
it 'returns a string' do
|
39
|
+
expect(collection.to_json).to be_kind_of String
|
40
|
+
end
|
41
|
+
|
42
|
+
it 'is parseable json' do
|
43
|
+
expect(JSON.parse(collection.to_json)).to be_kind_of Array
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
context 'exists?' do
|
48
|
+
it 'returns true if all the objects exist' do
|
49
|
+
expect(obj1).to receive(:exists?).and_return true
|
50
|
+
expect(obj2).to receive(:exists?).and_return true
|
51
|
+
expect(collection.exists?).to be true
|
52
|
+
end
|
53
|
+
|
54
|
+
it 'returns false if any of the objects do not exist' do
|
55
|
+
expect(obj1).to receive(:exists?).and_return true
|
56
|
+
expect(obj2).to receive(:exists?).and_return false
|
57
|
+
expect(collection.exists?).to be false
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
context 'errors' do
|
62
|
+
it 'is empty if there are no errors' do
|
63
|
+
expect(collection.errors).to be_empty
|
64
|
+
end
|
65
|
+
|
66
|
+
it 'collates the errors of the contained objects' do
|
67
|
+
obj2.errors = { status: 400 }
|
68
|
+
expect(collection.errors.size).to be 1
|
69
|
+
expect(collection.errors[2]).to have_key :status
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
context 'initialize' do
|
74
|
+
it 'does not process the objects if they are already the correct class' do
|
75
|
+
coll = Cot::Collection.new FakeDouble, [FakeDouble.new(fooy: :bar), FakeDouble.new(asdf: :fdas)]
|
76
|
+
expect(coll.first).to be_kind_of FakeDouble
|
77
|
+
end
|
78
|
+
|
79
|
+
it 'creates new instances of the passed klass if the objects are not already the class' do
|
80
|
+
coll = Cot::Collection.new FakeDouble, [{ fooy: :bar }, { asdf: :fdas }]
|
81
|
+
expect(coll.first).to be_kind_of FakeDouble
|
82
|
+
end
|
83
|
+
|
84
|
+
it 'takes an optional sub_key to pull the object out of the payload' do
|
85
|
+
coll = Cot::Collection.new FakeDouble, [{ inner: { fooy: :bar } }, { inner: { asdf: :fdas } }], :inner
|
86
|
+
expect(coll.first).to be_kind_of FakeDouble
|
87
|
+
expect(coll.first.fooy).to eq :bar
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
context 'update members' do
|
92
|
+
it 'updates members' do
|
93
|
+
coll = Cot::Collection.new FakeDouble, [{ fooy: :bar }]
|
94
|
+
expect(coll.length).to eq 1
|
95
|
+
coll.update_members [{ id: 123, foo: :bar }]
|
96
|
+
expect(coll.first.id).to eq 123
|
97
|
+
end
|
98
|
+
|
99
|
+
it 'removes members that are not in the payload' do
|
100
|
+
coll = Cot::Collection.new FakeDouble, [{ fooy: :bar }, { asdf: :fdas }]
|
101
|
+
expect(coll.length).to eq 2
|
102
|
+
coll.update_members [{ id: 123, foo: :bar }]
|
103
|
+
expect(coll.first.id).to eq 123
|
104
|
+
expect(coll.length).to eq 1
|
105
|
+
end
|
106
|
+
end
|
107
|
+
|
108
|
+
context 'changed?' do
|
109
|
+
it 'returns true if one of the objects has changed' do
|
110
|
+
coll = Cot::Collection.new FakeDouble, [{ fooy: :bar }]
|
111
|
+
coll.first.fooy = 'baz'
|
112
|
+
expect(coll.changed?).to be true
|
113
|
+
end
|
114
|
+
|
115
|
+
it 'return false if none of the objects have changed' do
|
116
|
+
coll = Cot::Collection.new FakeDouble, [{ fooy: :bar }]
|
117
|
+
expect(coll.changed?).to be false
|
118
|
+
end
|
119
|
+
end
|
120
|
+
end
|
data/spec/lib/cot/frame_spec.rb
CHANGED
@@ -52,6 +52,7 @@ describe Cot::Frame do
|
|
52
52
|
it 'is true if id is present' do
|
53
53
|
expect(@foo.exists?).to be_truthy
|
54
54
|
end
|
55
|
+
|
55
56
|
it 'is false if id is not present' do
|
56
57
|
foo = TestObject.new(foo: 5)
|
57
58
|
expect(foo.exists?).to be_falsey
|
@@ -61,6 +62,7 @@ describe Cot::Frame do
|
|
61
62
|
it 'includes foo' do
|
62
63
|
expect(@foo.defined_properties).to include :foo
|
63
64
|
end
|
65
|
+
|
64
66
|
it 'is an array' do
|
65
67
|
expect(@foo.defined_properties).to be_kind_of Array
|
66
68
|
end
|
@@ -100,6 +102,7 @@ describe Cot::Frame do
|
|
100
102
|
expect(TestObject.mappings).to have_key :bar
|
101
103
|
expect(TestObject.mappings[:bar]).to be :foo
|
102
104
|
end
|
105
|
+
|
103
106
|
it 'creates accessor methods' do
|
104
107
|
foo = TestObject.new
|
105
108
|
expect(foo).to respond_to :foo
|
@@ -116,4 +119,27 @@ describe Cot::Frame do
|
|
116
119
|
expect(foo.foo).to eq 'this is foo'
|
117
120
|
end
|
118
121
|
end
|
122
|
+
|
123
|
+
context 'errors' do
|
124
|
+
it 'has an errors property' do
|
125
|
+
expect(@foo).to respond_to :errors
|
126
|
+
expect(@foo.errors).to be_empty
|
127
|
+
end
|
128
|
+
end
|
129
|
+
|
130
|
+
context 'errors=' do
|
131
|
+
it 'sets errors' do
|
132
|
+
@foo.errors = { status: 200 }
|
133
|
+
expect(@foo.errors[:status]).to eq 200
|
134
|
+
end
|
135
|
+
end
|
136
|
+
context 'enum' do
|
137
|
+
it 'is not implemented' do
|
138
|
+
expect do
|
139
|
+
class TestObject < Cot::Frame
|
140
|
+
enum 'asdf'
|
141
|
+
end
|
142
|
+
end.to raise_exception StandardError
|
143
|
+
end
|
144
|
+
end
|
119
145
|
end
|
data/spec/spec_helper.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: cot
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Joseph Henrich
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2014-
|
11
|
+
date: 2014-08-08 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activemodel
|
@@ -127,9 +127,11 @@ files:
|
|
127
127
|
- Rakefile
|
128
128
|
- cot.gemspec
|
129
129
|
- lib/cot.rb
|
130
|
+
- lib/cot/collection.rb
|
130
131
|
- lib/cot/frame.rb
|
131
132
|
- lib/cot/rspec/matchers.rb
|
132
133
|
- lib/cot/version.rb
|
134
|
+
- spec/lib/cot/collection_spec.rb
|
133
135
|
- spec/lib/cot/frame_spec.rb
|
134
136
|
- spec/spec_helper.rb
|
135
137
|
homepage: http://github.com/crimsonknave/cot
|
@@ -151,10 +153,11 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
151
153
|
version: '0'
|
152
154
|
requirements: []
|
153
155
|
rubyforge_project:
|
154
|
-
rubygems_version: 2.1.
|
156
|
+
rubygems_version: 2.1.9
|
155
157
|
signing_key:
|
156
158
|
specification_version: 4
|
157
159
|
summary: Simplifies creating models for rest based resources
|
158
160
|
test_files:
|
161
|
+
- spec/lib/cot/collection_spec.rb
|
159
162
|
- spec/lib/cot/frame_spec.rb
|
160
163
|
- spec/spec_helper.rb
|