cot 0.3.0 → 0.4.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/LICENSE +1 -1
- data/README.md +34 -5
- data/cot.gemspec +1 -0
- data/lib/cot.rb +3 -0
- data/lib/cot/enum.rb +23 -0
- data/lib/cot/frame.rb +12 -39
- data/lib/cot/frame_class_methods.rb +63 -0
- data/lib/cot/property.rb +20 -0
- data/lib/cot/version.rb +1 -1
- data/spec/lib/cot/frame_spec.rb +65 -3
- metadata +7 -3
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA1:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: bce57021ecbcd6f8ea2c6952a36d4ea28b38bf99
|
|
4
|
+
data.tar.gz: 26f2711ae9016dda7b0c633bae9e9f3a04821e44
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 9b38415ebef6aec060d976c7f235ecb20db19d823ec131a3367d600a37484e69b4525a6ebd3f0b0f37b7745893ec78e4de6cdd1095517caf664d8f08b68a550c
|
|
7
|
+
data.tar.gz: ef4bc4c2b3129929629ae8ec2ff582eba6ac915b51d83d1008cc90f5367ba8ed5d4ce5759200a3d7632ae0b255e74c02a7ad7ba0a7f886b501c94832fcc00f60
|
data/LICENSE
CHANGED
data/README.md
CHANGED
|
@@ -9,9 +9,22 @@ Using cot is pretty simple. There are two main classes: Collection and Frame. Co
|
|
|
9
9
|
|
|
10
10
|
Frame provides some helpful methods:
|
|
11
11
|
- Class Methods
|
|
12
|
-
- property
|
|
12
|
+
- property
|
|
13
|
+
- The first parameter is the name of the property and it is added as a method to the object.
|
|
14
|
+
- You can pass additional options in two ways, first you can pass a hash of options to property and secondly you can pass a block to property.
|
|
15
|
+
- There are three optional arguments, value, from and searchable.
|
|
16
|
+
- From indicates that the property has an alternate key in the incoming/outgoing data.
|
|
17
|
+
- Searchable adds the property to the search mappings.
|
|
18
|
+
- Value takes a block and overwrites the value of the property to be the result of the block
|
|
19
|
+
- This is useful for nested objects.
|
|
20
|
+
- The block is executed as part of the instance of the object, so you have access to other properties.
|
|
21
|
+
- The block takes one parameter, which is the value of the hash for that key (what the value would have been if there was no value block).
|
|
13
22
|
- 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
|
|
23
|
+
- enum takes a name and a block
|
|
24
|
+
- The block expects a series of entries to be declared
|
|
25
|
+
- enum starts counting at 1 by default
|
|
26
|
+
- Each entry will have the value of 1 higher than the previous by default
|
|
27
|
+
- An optional value parameter can be passed which sets the entries value to that number. This lets you skip a numer, start higher or lower or even be non-sequential.
|
|
15
28
|
- Instance Methods
|
|
16
29
|
- defined\_properties returns a list of the defined properties
|
|
17
30
|
- 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.
|
|
@@ -24,6 +37,10 @@ Frame provides some helpful methods:
|
|
|
24
37
|
- errors used to store any errors associated with the object
|
|
25
38
|
|
|
26
39
|
Collection provides the following methods:
|
|
40
|
+
- Initialization
|
|
41
|
+
- You can pass options to the collection when you initialize
|
|
42
|
+
- sub\_key: Uses the contents inside the sub\_key
|
|
43
|
+
- default_attributes: Will add the keys/values to the object
|
|
27
44
|
- Instance Methods
|
|
28
45
|
- The following methods collate the results from members
|
|
29
46
|
- serializable\_hash
|
|
@@ -38,12 +55,23 @@ class ExampleObject < Cot::Frame
|
|
|
38
55
|
property :id
|
|
39
56
|
property :name, :searchable => true
|
|
40
57
|
property :company_name, :from => :companyName
|
|
58
|
+
property :item do
|
|
59
|
+
from :place
|
|
60
|
+
value do |params|
|
|
61
|
+
MyClass.new params.merge parent_id: id
|
|
62
|
+
end
|
|
63
|
+
end
|
|
64
|
+
enum :types do
|
|
65
|
+
entry :first
|
|
66
|
+
entry :third, value: 3
|
|
67
|
+
entry :fourth
|
|
68
|
+
end
|
|
41
69
|
search_property :created_at, :from => :createdOn
|
|
42
70
|
end
|
|
43
71
|
|
|
44
72
|
class ExampleCollection < Cot::Collection
|
|
45
|
-
def initialize(
|
|
46
|
-
super ExampleObject,
|
|
73
|
+
def initialize(objects, options = {})
|
|
74
|
+
super ExampleObject, objects, options
|
|
47
75
|
end
|
|
48
76
|
end
|
|
49
77
|
|
|
@@ -53,8 +81,9 @@ thingy.name # awesome name
|
|
|
53
81
|
thingy.created_at # what time it is now
|
|
54
82
|
thingy.defined\_properties # [:id, :name, :created_at]
|
|
55
83
|
|
|
56
|
-
collection = ExampleCollection.new [{ id: :my_id, name: 'awesome name', createdOn: Time.now }, { id: :my_id, name: 'awesome name', createdOn: Time.now }]
|
|
84
|
+
collection = ExampleCollection.new [{ id: :my_id, name: 'awesome name', createdOn: Time.now }, { id: :my_id, name: 'awesome name', createdOn: Time.now }], { default_attributes: { default: :attribute }
|
|
57
85
|
collection.first.name # 'awesome name'
|
|
86
|
+
collection.first.default # :attribute
|
|
58
87
|
collection.exists? # Do all of the entries exist?
|
|
59
88
|
collection.update_members [{ id: 1, name: 'new awesome name', createdOn: Time.now }, { id: 2, name: 'new awesome name', createdOn: Time.now }]
|
|
60
89
|
collection.first.name # 'new awesome name'
|
data/cot.gemspec
CHANGED
|
@@ -11,6 +11,7 @@ Gem::Specification.new do |s|
|
|
|
11
11
|
s.homepage = 'http://github.com/crimsonknave/cot'
|
|
12
12
|
s.summary = 'Simplifies creating models for rest based resources'
|
|
13
13
|
s.description = 'Simplifies creating models for rest based resources'
|
|
14
|
+
s.license = 'MIT'
|
|
14
15
|
|
|
15
16
|
s.files = `git ls-files`.split("\n")
|
|
16
17
|
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
data/lib/cot.rb
CHANGED
|
@@ -2,8 +2,11 @@ require 'active_model'
|
|
|
2
2
|
require 'active_support/core_ext/hash/indifferent_access'
|
|
3
3
|
|
|
4
4
|
require 'cot/version'
|
|
5
|
+
require 'cot/frame_class_methods'
|
|
5
6
|
require 'cot/frame'
|
|
6
7
|
require 'cot/collection'
|
|
8
|
+
require 'cot/property'
|
|
9
|
+
require 'cot/enum'
|
|
7
10
|
require 'json'
|
|
8
11
|
|
|
9
12
|
module Cot
|
data/lib/cot/enum.rb
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
module Cot
|
|
2
|
+
class Enum
|
|
3
|
+
attr_accessor :num, :used
|
|
4
|
+
def initialize
|
|
5
|
+
@used = {}
|
|
6
|
+
@num = 1
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
def entry(name, options = {})
|
|
10
|
+
value = options[:value] || num
|
|
11
|
+
if used.key? value
|
|
12
|
+
fail "#{name} tried to set value #{value}, which is already used by #{used[value]}. Enum values are unique."
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
self.class.send :define_method, name do
|
|
16
|
+
value
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
@num = value + 1
|
|
20
|
+
used[value] = name
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
end
|
data/lib/cot/frame.rb
CHANGED
|
@@ -1,13 +1,22 @@
|
|
|
1
1
|
module Cot
|
|
2
2
|
class Frame
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
3
|
+
attr_accessor :errors
|
|
4
|
+
|
|
5
|
+
extend FrameClassMethods
|
|
6
|
+
|
|
6
7
|
include ActiveModel::Dirty
|
|
7
8
|
|
|
8
9
|
def initialize(payload = {})
|
|
9
10
|
@errors = {}
|
|
11
|
+
|
|
10
12
|
@data = convert_keys payload
|
|
13
|
+
|
|
14
|
+
@data.each do |k, v|
|
|
15
|
+
if self.class.value_blocks[k]
|
|
16
|
+
block = self.class.value_blocks[k]
|
|
17
|
+
@data[k] = instance_exec(v, &block)
|
|
18
|
+
end
|
|
19
|
+
end
|
|
11
20
|
end
|
|
12
21
|
|
|
13
22
|
def exists?
|
|
@@ -35,42 +44,6 @@ module Cot
|
|
|
35
44
|
self.class.inverted_search_mappings ||= search_mappings.invert
|
|
36
45
|
end
|
|
37
46
|
|
|
38
|
-
def self.search_property(name, args = {})
|
|
39
|
-
@search_mappings ||= {}
|
|
40
|
-
|
|
41
|
-
key = args[:from] ? args[:from] : name
|
|
42
|
-
@search_mappings[name] = key
|
|
43
|
-
end
|
|
44
|
-
|
|
45
|
-
# TODO: Create an enum declaration that will automagically map a symbol to
|
|
46
|
-
# another value (such as an int) so that the user of the library doesn't need
|
|
47
|
-
# to know what number scheduled status is (for example)
|
|
48
|
-
def self.enum(_name, _args = {})
|
|
49
|
-
fail 'enum is not yet implemented'
|
|
50
|
-
end
|
|
51
|
-
|
|
52
|
-
def self.property(name, args = {})
|
|
53
|
-
@mappings ||= {}
|
|
54
|
-
@attr_methods ||= []
|
|
55
|
-
@search_mappings ||= {}
|
|
56
|
-
key = args[:from]
|
|
57
|
-
@mappings[key.to_sym] = name if key
|
|
58
|
-
@search_mappings[name] = key ? key : name if args[:searchable]
|
|
59
|
-
attr_methods << name.to_sym
|
|
60
|
-
|
|
61
|
-
define_method name do
|
|
62
|
-
self[name]
|
|
63
|
-
end
|
|
64
|
-
|
|
65
|
-
define_method "#{name}=" do |value|
|
|
66
|
-
send("#{name}_will_change!") unless value == self[name]
|
|
67
|
-
self[name] = value
|
|
68
|
-
end
|
|
69
|
-
define_attribute_method name
|
|
70
|
-
end
|
|
71
|
-
|
|
72
|
-
attr_accessor :errors
|
|
73
|
-
|
|
74
47
|
def [](key)
|
|
75
48
|
@data[convert_key key]
|
|
76
49
|
end
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
module Cot
|
|
2
|
+
module FrameClassMethods
|
|
3
|
+
attr_accessor :attr_methods,
|
|
4
|
+
:inverted_mappings,
|
|
5
|
+
:inverted_search_mappings,
|
|
6
|
+
:search_mappings,
|
|
7
|
+
:value_blocks,
|
|
8
|
+
:mappings
|
|
9
|
+
|
|
10
|
+
def search_property(name, args = {})
|
|
11
|
+
@search_mappings ||= {}
|
|
12
|
+
|
|
13
|
+
key = args[:from] ? args[:from] : name
|
|
14
|
+
@search_mappings[name] = key
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def enum(name, &block)
|
|
18
|
+
obj = Enum.new
|
|
19
|
+
obj.instance_eval(&block)
|
|
20
|
+
define_method name do
|
|
21
|
+
obj
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def property(name, args = {}, &block)
|
|
26
|
+
set_default_values
|
|
27
|
+
prop = Property.new args
|
|
28
|
+
prop.instance_eval(&block) if block
|
|
29
|
+
|
|
30
|
+
@value_blocks[name] = prop.value if prop.value
|
|
31
|
+
|
|
32
|
+
key = prop.from
|
|
33
|
+
@mappings[key.to_sym] = name if key
|
|
34
|
+
@search_mappings[name] = key ? key : name if prop.searchable
|
|
35
|
+
attr_methods << name.to_sym
|
|
36
|
+
|
|
37
|
+
define_property_methods name
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
private
|
|
41
|
+
|
|
42
|
+
# Can't seem to get an intialize in for the class, so we need to set these
|
|
43
|
+
# before we do stuff for property
|
|
44
|
+
def set_default_values
|
|
45
|
+
@mappings ||= {}
|
|
46
|
+
@attr_methods ||= []
|
|
47
|
+
@search_mappings ||= {}
|
|
48
|
+
@value_blocks ||= {}
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
def define_property_methods(name)
|
|
52
|
+
define_method name do
|
|
53
|
+
self[name]
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
define_method "#{name}=" do |value|
|
|
57
|
+
send("#{name}_will_change!") unless value == self[name]
|
|
58
|
+
self[name] = value
|
|
59
|
+
end
|
|
60
|
+
define_attribute_method name
|
|
61
|
+
end
|
|
62
|
+
end
|
|
63
|
+
end
|
data/lib/cot/property.rb
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
module Cot
|
|
2
|
+
class Property
|
|
3
|
+
attr_accessor :args
|
|
4
|
+
def initialize(params = {})
|
|
5
|
+
@args = params
|
|
6
|
+
end
|
|
7
|
+
|
|
8
|
+
def value(&block)
|
|
9
|
+
return args[:value] unless block
|
|
10
|
+
args[:value] = block
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
[:from, :searchable].each do |method_name|
|
|
14
|
+
define_method method_name do |value = nil|
|
|
15
|
+
return args[method_name] if value.nil?
|
|
16
|
+
args[method_name] = value
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
end
|
data/lib/cot/version.rb
CHANGED
data/spec/lib/cot/frame_spec.rb
CHANGED
|
@@ -118,6 +118,43 @@ describe Cot::Frame do
|
|
|
118
118
|
expect(foo).to receive('[]').once.and_return 'this is foo'
|
|
119
119
|
expect(foo.foo).to eq 'this is foo'
|
|
120
120
|
end
|
|
121
|
+
|
|
122
|
+
context 'passing a block' do
|
|
123
|
+
before :each do
|
|
124
|
+
class Foo
|
|
125
|
+
attr_reader :params
|
|
126
|
+
def initialize(params)
|
|
127
|
+
@params = params
|
|
128
|
+
end
|
|
129
|
+
end
|
|
130
|
+
class TestObject < Cot::Frame
|
|
131
|
+
property :my_id, from: :id
|
|
132
|
+
property :thing do
|
|
133
|
+
from :stuff
|
|
134
|
+
searchable true
|
|
135
|
+
value do |params|
|
|
136
|
+
Foo.new params.merge passed: my_id
|
|
137
|
+
end
|
|
138
|
+
end
|
|
139
|
+
end
|
|
140
|
+
@foo = TestObject.new(stuff: { key: 'this will be in foo' }, id: 42)
|
|
141
|
+
end
|
|
142
|
+
|
|
143
|
+
it 'adds to mappings' do
|
|
144
|
+
expect(TestObject.mappings).to have_key :stuff
|
|
145
|
+
expect(TestObject.mappings[:stuff]).to be :thing
|
|
146
|
+
end
|
|
147
|
+
|
|
148
|
+
it 'stores searchable' do
|
|
149
|
+
expect(TestObject.search_mappings).to have_key :thing
|
|
150
|
+
expect(TestObject.search_mappings[:thing]).to be :stuff
|
|
151
|
+
end
|
|
152
|
+
|
|
153
|
+
it 'assigns sets the value' do
|
|
154
|
+
expect(@foo.thing).to be_kind_of Foo
|
|
155
|
+
expect(@foo.thing.params[:passed]).to eq 42
|
|
156
|
+
end
|
|
157
|
+
end
|
|
121
158
|
end
|
|
122
159
|
|
|
123
160
|
context 'errors' do
|
|
@@ -134,12 +171,37 @@ describe Cot::Frame do
|
|
|
134
171
|
end
|
|
135
172
|
end
|
|
136
173
|
context 'enum' do
|
|
137
|
-
|
|
174
|
+
before :each do
|
|
175
|
+
class TestObject < Cot::Frame
|
|
176
|
+
enum :types do
|
|
177
|
+
entry :first
|
|
178
|
+
entry :third, value: 3
|
|
179
|
+
entry :fourth
|
|
180
|
+
end
|
|
181
|
+
end
|
|
182
|
+
@foo = TestObject.new
|
|
183
|
+
end
|
|
184
|
+
it 'sets the value starting at 1' do
|
|
185
|
+
expect(@foo.types.first).to eq 1
|
|
186
|
+
end
|
|
187
|
+
|
|
188
|
+
it 'allows the value to be set' do
|
|
189
|
+
expect(@foo.types.third).to eq 3
|
|
190
|
+
end
|
|
191
|
+
|
|
192
|
+
it 'increments after the next value' do
|
|
193
|
+
expect(@foo.types.fourth).to eq 4
|
|
194
|
+
end
|
|
195
|
+
|
|
196
|
+
it 'does not allow duplicates' do
|
|
138
197
|
expect do
|
|
139
198
|
class TestObject < Cot::Frame
|
|
140
|
-
enum
|
|
199
|
+
enum :types do
|
|
200
|
+
entry :first
|
|
201
|
+
entry :first_again, value: 1
|
|
202
|
+
end
|
|
141
203
|
end
|
|
142
|
-
end.to
|
|
204
|
+
end.to raise_error StandardError
|
|
143
205
|
end
|
|
144
206
|
end
|
|
145
207
|
end
|
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.4.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-09-
|
|
11
|
+
date: 2014-09-30 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: activemodel
|
|
@@ -129,14 +129,18 @@ files:
|
|
|
129
129
|
- cot.gemspec
|
|
130
130
|
- lib/cot.rb
|
|
131
131
|
- lib/cot/collection.rb
|
|
132
|
+
- lib/cot/enum.rb
|
|
132
133
|
- lib/cot/frame.rb
|
|
134
|
+
- lib/cot/frame_class_methods.rb
|
|
135
|
+
- lib/cot/property.rb
|
|
133
136
|
- lib/cot/rspec/matchers.rb
|
|
134
137
|
- lib/cot/version.rb
|
|
135
138
|
- spec/lib/cot/collection_spec.rb
|
|
136
139
|
- spec/lib/cot/frame_spec.rb
|
|
137
140
|
- spec/spec_helper.rb
|
|
138
141
|
homepage: http://github.com/crimsonknave/cot
|
|
139
|
-
licenses:
|
|
142
|
+
licenses:
|
|
143
|
+
- MIT
|
|
140
144
|
metadata: {}
|
|
141
145
|
post_install_message:
|
|
142
146
|
rdoc_options: []
|