oat 0.2.5 → 0.3.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 7d444b3c170713aa0e2ff5c54fec3d55303560de
4
- data.tar.gz: 2b0619de2dc37f28043a0d641f96fbc428145cc1
3
+ metadata.gz: d46e82b85714a233bfeb43fb7fd17484ab5b1bfc
4
+ data.tar.gz: e5d24b98474b575a26e39f0d5b37f32bd24ba51a
5
5
  SHA512:
6
- metadata.gz: 5622ecddbad73ddbf6c390fcca1ac44cdd282ab1efc69bac16ea6962b7eea76008461a47eefc549962fb99f1346b928f7622f6e9e9f3d269e420bc23e5bdb6e7
7
- data.tar.gz: 8f63e0662b6526536d79c4a07d2aadcb0c91b7ca90b25aa183a92c9b5b566d79b6a18c98807e5b816173ccd431f9cb1c9aae6dac7a99b0952e2396e7d412bb94
6
+ metadata.gz: 588c0d3d4f3f9feacafed50afba811aa7972b5922147084bb85431c998d86e40787fadd5d9c49ddd27fa227dfd20e698f82605cee1f2134e87a4b1056b21159e
7
+ data.tar.gz: 8bcace9c58e4c84a973aeaa42b457cdcce1e796562489f978b39c7fa400fe5acd7cfde7b9aa69e0c5213a2cb55bdbff39c37b6065a0dbb4a38bd8b7d96d1976f
data/README.md CHANGED
@@ -113,6 +113,11 @@ class ProductSerializer < Oat::Serializer
113
113
  end
114
114
  ```
115
115
 
116
+ ### Defining Links
117
+
118
+ Links to other resources can be added by using `link` with a name and an options hash. Most adapters expect just an href in the options hash, but some might support additional properties.
119
+ Some adapters also suport passing `templated: true` in the options hash to indicate special treatment of a link template.
120
+
116
121
  ## Adapters
117
122
 
118
123
  Using the included [HAL](http://stateless.co/hal_specification.html) adapter, the `ProductSerializer` above would render the following JSON:
@@ -464,7 +469,7 @@ class CustomAdapter < Oat::Adapter
464
469
  end
465
470
 
466
471
  def entity(name, obj, serializer_class = nil, &block)
467
- data[:nested_documents] = serializer_from_block_or_class(obj, serializer_class, &block)
472
+ data[:nested_documents] = serializer_from_block_or_class(obj, serializer_class, &block).to_hash
468
473
  end
469
474
 
470
475
  ... etc
@@ -524,7 +529,7 @@ class SocialAdapter < Oat::Adapter
524
529
 
525
530
  def friends(friend_list, serializer_class = nil, &block)
526
531
  data[:friends] = friend_list.map do |obj|
527
- serializer_from_block_or_class(obj, serializer_class, &block)
532
+ serializer_from_block_or_class(obj, serializer_class, &block).to_hash
528
533
  end
529
534
  end
530
535
  end
@@ -582,7 +587,7 @@ Or install it yourself as:
582
587
 
583
588
  ## TODO / contributions welcome
584
589
 
585
- * JsonAPI URL and ID modes, top-level links
590
+ * JsonAPI top-level meta
586
591
  * testing module that can be used for testing spec-compliance in user apps?
587
592
 
588
593
  ## Contributing
@@ -2,4 +2,5 @@ source 'https://rubygems.org'
2
2
 
3
3
  # Specify your gem's dependencies in oat.gemspec
4
4
  gem 'activesupport', '1.4.4'
5
+ gem 'rake', '< 10.2'
5
6
  gemspec :path => "../"
@@ -2,4 +2,5 @@ source 'https://rubygems.org'
2
2
 
3
3
  # Specify your gem's dependencies in oat.gemspec
4
4
  gem 'activesupport', '~>2.3.18'
5
+ gem 'rake', '< 10.2'
5
6
  gemspec :path => "../"
@@ -3,4 +3,5 @@ source 'https://rubygems.org'
3
3
  # Specify your gem's dependencies in oat.gemspec
4
4
  gem 'activesupport', '~>3.0.20'
5
5
  gem 'i18n'
6
+ gem 'rake', '< 10.2'
6
7
  gemspec :path => "../"
@@ -3,4 +3,5 @@ source 'https://rubygems.org'
3
3
  # Specify your gem's dependencies in oat.gemspec
4
4
  gem 'activesupport', '~>3.1.12'
5
5
  gem 'i18n'
6
+ gem 'rake', '< 10.2'
6
7
  gemspec :path => "../"
@@ -2,4 +2,5 @@ source 'https://rubygems.org'
2
2
 
3
3
  # Specify your gem's dependencies in oat.gemspec
4
4
  gem 'activesupport', '~>3.2.16'
5
+ gem 'rake', '< 10.2'
5
6
  gemspec :path => "../"
data/lib/oat/adapter.rb CHANGED
@@ -29,9 +29,9 @@ module Oat
29
29
  serializer_class.adapter self.class
30
30
  s = serializer_class.new(obj, serializer.context.merge(context_options), serializer.adapter_class, serializer.top)
31
31
  serializer.instance_exec(obj, s, &block)
32
- s.to_hash
32
+ s
33
33
  else
34
- serializer_class.new(obj, serializer.context.merge(context_options), serializer.adapter_class, serializer.top).to_hash
34
+ serializer_class.new(obj, serializer.context.merge(context_options), serializer.adapter_class, serializer.top)
35
35
  end
36
36
  end
37
37
  end
@@ -15,12 +15,14 @@ module Oat
15
15
  end
16
16
 
17
17
  def entity(name, obj, serializer_class = nil, context_options = {}, &block)
18
- data[:_embedded][name] = serializer_from_block_or_class(obj, serializer_class, context_options, &block)
18
+ entity_serializer = serializer_from_block_or_class(obj, serializer_class, context_options, &block)
19
+ data[:_embedded][name] = entity_serializer ? entity_serializer.to_hash : nil
19
20
  end
20
21
 
21
22
  def entities(name, collection, serializer_class = nil, context_options = {}, &block)
22
23
  data[:_embedded][name] = collection.map do |obj|
23
- serializer_from_block_or_class(obj, serializer_class, context_options, &block)
24
+ entity_serializer = serializer_from_block_or_class(obj, serializer_class, context_options, &block)
25
+ entity_serializer ? entity_serializer.to_hash : nil
24
26
  end
25
27
  end
26
28
  alias_method :collection, :entities
@@ -9,11 +9,13 @@ end
9
9
 
10
10
  module Oat
11
11
  module Adapters
12
+
12
13
  class JsonAPI < Oat::Adapter
13
14
 
14
15
  def initialize(*args)
15
16
  super
16
17
  @entities = {}
18
+ @link_templates = {}
17
19
  end
18
20
 
19
21
  def type(*types)
@@ -21,9 +23,34 @@ module Oat
21
23
  end
22
24
 
23
25
  def link(rel, opts = {})
24
- data[:links][rel] = opts[:href]
26
+ if opts.is_a?(Hash)
27
+ templated = opts.delete(:templated)
28
+ if templated
29
+ link_template(rel, opts[:href])
30
+ else
31
+ check_link_keys(opts)
32
+ end
33
+ end
34
+ data[:links][rel] = opts
25
35
  end
26
36
 
37
+ def check_link_keys(opts)
38
+ unsupported_opts = opts.keys - [:href, :id, :ids, :type]
39
+
40
+ unless unsupported_opts.empty?
41
+ raise ArgumentError, "Unsupported opts: #{unsupported_opts.join(", ")}"
42
+ end
43
+ if opts.has_key?(:id) && opts.has_key?(:ids)
44
+ raise ArgumentError, "ops canot contain both :id and :ids"
45
+ end
46
+ end
47
+ private :check_link_keys
48
+
49
+ def link_template(key, value)
50
+ @link_templates[key] = value
51
+ end
52
+ private :link_template
53
+
27
54
  def properties(&block)
28
55
  data.merge! yield_props(&block)
29
56
  end
@@ -35,9 +62,10 @@ module Oat
35
62
  def entity(name, obj, serializer_class = nil, context_options = {}, &block)
36
63
  ent = serializer_from_block_or_class(obj, serializer_class, context_options, &block)
37
64
  if ent
65
+ ent_hash = ent.to_hash
38
66
  entity_hash[name.to_s.pluralize.to_sym] ||= []
39
- link name, :href => ent[:id]
40
- entity_hash[name.to_s.pluralize.to_sym] << ent
67
+ data[:links][name] = ent_hash[:id]
68
+ entity_hash[name.to_s.pluralize.to_sym] << ent_hash
41
69
  end
42
70
  end
43
71
 
@@ -50,8 +78,9 @@ module Oat
50
78
  entity_hash[link_name] ||= []
51
79
  ent = serializer_from_block_or_class(obj, serializer_class, context_options, &block)
52
80
  if ent
53
- data[:links][link_name] << ent[:id]
54
- entity_hash[link_name] << ent
81
+ ent_hash = ent.to_hash
82
+ data[:links][link_name] << ent_hash[:id]
83
+ entity_hash[link_name] << ent_hash
55
84
  end
56
85
  end
57
86
  end
@@ -62,7 +91,7 @@ module Oat
62
91
 
63
92
  collection.each do |obj|
64
93
  ent = serializer_from_block_or_class(obj, serializer_class, context_options, &block)
65
- data[:resource_collection] << ent if ent
94
+ data[:resource_collection] << ent.to_hash if ent
66
95
  end
67
96
  end
68
97
 
@@ -78,6 +107,7 @@ module Oat
78
107
  h[root_name] = [data]
79
108
  end
80
109
  h[:linked] = @entities if @entities.keys.any?
110
+ h[:links] = @link_templates if @link_templates.keys.any?
81
111
  return h
82
112
  end
83
113
  end
@@ -94,6 +124,11 @@ module Oat
94
124
  end
95
125
  end
96
126
 
127
+ def entity_without_root(obj, serializer_class = nil, &block)
128
+ ent = serializer_from_block_or_class(obj, serializer_class, &block)
129
+ ent.to_hash.values.first.first if ent
130
+ end
131
+
97
132
  end
98
133
  end
99
134
  end
@@ -28,7 +28,7 @@ module Oat
28
28
 
29
29
  def entity(name, obj, serializer_class = nil, context_options = {}, &block)
30
30
  ent = serializer_from_block_or_class(obj, serializer_class, context_options, &block)
31
- data[:entities] << ent if ent
31
+ data[:entities] << ent.to_hash if ent
32
32
  end
33
33
 
34
34
  def entities(name, collection, serializer_class = nil, context_options = {}, &block)
data/lib/oat/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Oat
2
- VERSION = "0.2.5"
2
+ VERSION = "0.3.0"
3
3
  end
@@ -25,7 +25,9 @@ describe Oat::Adapters::JsonAPI do
25
25
 
26
26
  it 'contains the correct user links' do
27
27
  expect(users.first.fetch(:links)).to include(
28
- :self => "http://foo.bar.com/#{user.id}",
28
+ :self => {
29
+ :href => "http://foo.bar.com/#{user.id}"
30
+ },
29
31
  # these links are added by embedding entities
30
32
  :manager => manager.id,
31
33
  :friends => [friend.id]
@@ -51,8 +53,9 @@ describe Oat::Adapters::JsonAPI do
51
53
 
52
54
  it 'contains the correct links' do
53
55
  expect(linked_friends.first.fetch(:links)).to include(
54
- :self => "http://foo.bar.com/#{friend.id}",
55
- :empty => nil
56
+ :self => {
57
+ :href => "http://foo.bar.com/#{friend.id}"
58
+ }
56
59
  )
57
60
  end
58
61
  end
@@ -66,7 +69,7 @@ describe Oat::Adapters::JsonAPI do
66
69
  :id => manager.id,
67
70
  :name => manager.name,
68
71
  :age => manager.age,
69
- :links => { :self => "http://foo.bar.com/#{manager.id}" }
72
+ :links => { :self => { :href => "http://foo.bar.com/#{manager.id}"} }
70
73
  )
71
74
  end
72
75
  end
@@ -84,6 +87,116 @@ describe Oat::Adapters::JsonAPI do
84
87
  end
85
88
  end
86
89
 
90
+ context 'object links' do
91
+ context "as string" do
92
+ let(:serializer_class) do
93
+ Class.new(Oat::Serializer) do
94
+ schema do
95
+ type 'users'
96
+ link :self, "45"
97
+ end
98
+ end
99
+ end
100
+
101
+ it 'renders just the string' do
102
+ expect(hash.fetch(:users).first.fetch(:links)).to eq({
103
+ :self => "45"
104
+ })
105
+ end
106
+ end
107
+
108
+ context 'as array' do
109
+ let(:serializer_class) do
110
+ Class.new(Oat::Serializer) do
111
+ schema do
112
+ type 'users'
113
+ link :self, ["45", "46", "47"]
114
+ end
115
+ end
116
+ end
117
+
118
+ it 'renders the array' do
119
+ expect(hash.fetch(:users).first.fetch(:links)).to eq({
120
+ :self => ["45", "46", "47"]
121
+ })
122
+ end
123
+ end
124
+
125
+ context 'as hash' do
126
+ context 'with single id' do
127
+ let(:serializer_class) do
128
+ Class.new(Oat::Serializer) do
129
+ schema do
130
+ type 'users'
131
+ link :self, :href => "http://foo.bar.com/#{item.id}", :id => item.id.to_s, :type => 'user'
132
+ end
133
+ end
134
+ end
135
+
136
+ it 'renders all the keys' do
137
+ expect(hash.fetch(:users).first.fetch(:links)).to eq({
138
+ :self => {
139
+ :href => "http://foo.bar.com/#{user.id}",
140
+ :id => user.id.to_s,
141
+ :type => 'user'
142
+ }
143
+ })
144
+ end
145
+ end
146
+
147
+ context 'with ids' do
148
+ let(:serializer_class) do
149
+ Class.new(Oat::Serializer) do
150
+ schema do
151
+ type 'users'
152
+ link :self, :href => "http://foo.bar.com/1,2,3", :ids => ["1", "2", "3"], :type => 'user'
153
+ end
154
+ end
155
+ end
156
+
157
+ it 'renders all the keys' do
158
+ expect(hash.fetch(:users).first.fetch(:links)).to eq({
159
+ :self => {
160
+ :href => "http://foo.bar.com/1,2,3",
161
+ :ids => ["1", "2", "3"],
162
+ :type => 'user'
163
+ }
164
+ })
165
+ end
166
+ end
167
+
168
+ context 'with id and ids' do
169
+ let(:serializer_class) do
170
+ Class.new(Oat::Serializer) do
171
+ schema do
172
+ type 'users'
173
+ link :self, :id => "45", :ids => ["1", "2", "3"]
174
+ end
175
+ end
176
+ end
177
+
178
+ it "errs" do
179
+ expect{hash}.to raise_error(ArgumentError)
180
+ end
181
+ end
182
+
183
+ context 'with invalid keys' do
184
+ let(:serializer_class) do
185
+ Class.new(Oat::Serializer) do
186
+ schema do
187
+ type 'users'
188
+ link :self, :not_a_valid_key => "value"
189
+ end
190
+ end
191
+ end
192
+
193
+ it "errs" do
194
+ expect{hash}.to raise_error(ArgumentError)
195
+ end
196
+ end
197
+ end
198
+ end
199
+
87
200
  context 'with a nil entity relationship' do
88
201
  let(:manager) { nil }
89
202
  let(:users) { hash.fetch(:users) }
@@ -169,7 +282,7 @@ describe Oat::Adapters::JsonAPI do
169
282
 
170
283
  it 'contains the correct user links' do
171
284
  expect(users.first.fetch(:links)).to include(
172
- :self => "http://foo.bar.com/#{user.id}",
285
+ :self => {:href => "http://foo.bar.com/#{user.id}"},
173
286
  # these links are added by embedding entities
174
287
  :manager => manager.id,
175
288
  :friends => [friend.id]
@@ -185,12 +298,30 @@ describe Oat::Adapters::JsonAPI do
185
298
  :id => manager.id,
186
299
  :name => manager.name,
187
300
  :age => manager.age,
188
- :links => { :self => "http://foo.bar.com/#{manager.id}" }
301
+ :links => { :self => {:href =>"http://foo.bar.com/#{manager.id}"} }
189
302
  )
190
303
  end
191
304
  end
192
305
  end
306
+ end
307
+
308
+ context 'link_template' do
309
+ let(:serializer_class) do
310
+ Class.new(Oat::Serializer) do
311
+ schema do
312
+ type 'users'
313
+ link "user.managers", :href => "http://foo.bar.com/{user.id}/managers", :templated => true
314
+ link "user.friends", :href => "http://foo.bar.com/{user.id}/friends", :templated => true
315
+ end
316
+ end
317
+ end
193
318
 
319
+ it 'renders them top level' do
320
+ expect(hash.fetch(:links)).to eq({
321
+ "user.managers" => "http://foo.bar.com/{user.id}/managers",
322
+ "user.friends" => "http://foo.bar.com/{user.id}/friends"
323
+ })
324
+ end
194
325
  end
195
326
  end
196
327
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: oat
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.5
4
+ version: 0.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ismael Celis
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-03-20 00:00:00.000000000 Z
11
+ date: 2014-03-25 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activesupport