cot 0.3.0 → 0.4.0
Sign up to get free protection for your applications and to get access to all the features.
- 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: []
|