oat 0.2.5 → 0.3.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: 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