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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: b54755a09317578c48c93d680043d3e6bcf1caab
4
- data.tar.gz: a264c498df609509981b8c5afb837a211ad84d36
3
+ metadata.gz: bce57021ecbcd6f8ea2c6952a36d4ea28b38bf99
4
+ data.tar.gz: 26f2711ae9016dda7b0c633bae9e9f3a04821e44
5
5
  SHA512:
6
- metadata.gz: 5f71356f473c1de0f94513b553dd8222977744489434808c90de5fa9f130019cb710278b7df826f37b6365d532712886148a28e027cd88c8bda0c5729dfc7cf3
7
- data.tar.gz: d25fc72929dd6e80b7ece0d5ccbd02854a8bb49df4376a17d188ae11b1ec8209187a2c9d2717f10fcc8602e7fdad1489b443568e86950231d33b2837fbed54de
6
+ metadata.gz: 9b38415ebef6aec060d976c7f235ecb20db19d823ec131a3367d600a37484e69b4525a6ebd3f0b0f37b7745893ec78e4de6cdd1095517caf664d8f08b68a550c
7
+ data.tar.gz: ef4bc4c2b3129929629ae8ec2ff582eba6ac915b51d83d1008cc90f5367ba8ed5d4ce5759200a3d7632ae0b255e74c02a7ad7ba0a7f886b501c94832fcc00f60
data/LICENSE CHANGED
@@ -1,6 +1,6 @@
1
1
  The MIT License (MIT)
2
2
 
3
- Copyright (c) 2013 Joseph Henrich
3
+ Copyright (c) 2014 Joseph Henrich
4
4
 
5
5
  Permission is hereby granted, free of charge, to any person obtaining a copy of
6
6
  this software and associated documentation files (the "Software"), to deal in
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 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.
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 *NOT SUPPORTED* If you'd like to see this let me know. Also let me know what you'd want it to look like.
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(params)
46
- super ExampleObject, params
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'
@@ -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
@@ -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
@@ -1,13 +1,22 @@
1
1
  module Cot
2
2
  class Frame
3
- class << self
4
- attr_accessor :mappings, :inverted_mappings, :attr_methods, :search_mappings, :inverted_search_mappings
5
- end
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
@@ -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
@@ -1,3 +1,3 @@
1
1
  module Cot
2
- VERSION = '0.3.0'
2
+ VERSION = '0.4.0'
3
3
  end
@@ -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
- it 'is not implemented' do
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 'asdf'
199
+ enum :types do
200
+ entry :first
201
+ entry :first_again, value: 1
202
+ end
141
203
  end
142
- end.to raise_exception StandardError
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.3.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-15 00:00:00.000000000 Z
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: []