yaks 0.4.2 → 0.4.3
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitignore +1 -0
- data/CHANGELOG.md +65 -5
- data/README.md +38 -8
- data/Rakefile +33 -0
- data/lib/yaks/breaking_changes.rb +22 -0
- data/lib/yaks/collection_mapper.rb +18 -21
- data/lib/yaks/collection_resource.rb +19 -5
- data/lib/yaks/config/dsl.rb +78 -0
- data/lib/yaks/config.rb +37 -63
- data/lib/yaks/default_policy.rb +27 -9
- data/lib/yaks/{serializer → format}/collection_json.rb +7 -3
- data/lib/yaks/{serializer → format}/hal.rb +14 -4
- data/lib/yaks/{serializer → format}/json_api.rb +22 -4
- data/lib/yaks/{serializer.rb → format.rb} +5 -5
- data/lib/yaks/fp/hash_updatable.rb +17 -0
- data/lib/yaks/fp/updatable.rb +15 -0
- data/lib/yaks/mapper/association.rb +24 -21
- data/lib/yaks/mapper/association_mapper.rb +42 -0
- data/lib/yaks/mapper/attribute.rb +17 -0
- data/lib/yaks/mapper/class_methods.rb +0 -1
- data/lib/yaks/mapper/config.rb +8 -28
- data/lib/yaks/mapper/has_many.rb +8 -3
- data/lib/yaks/mapper/has_one.rb +1 -1
- data/lib/yaks/mapper/link.rb +13 -13
- data/lib/yaks/mapper.rb +28 -32
- data/lib/yaks/null_resource.rb +1 -0
- data/lib/yaks/resource.rb +15 -5
- data/lib/yaks/version.rb +1 -1
- data/lib/yaks.rb +16 -10
- data/spec/acceptance/acceptance_spec.rb +16 -17
- data/spec/acceptance/json_shared_examples.rb +8 -0
- data/spec/acceptance/models.rb +2 -2
- data/spec/integration/map_to_resource_spec.rb +3 -3
- data/spec/json/confucius.collection.json +39 -0
- data/spec/json/confucius.hal.json +7 -4
- data/spec/json/confucius.json_api.json +1 -1
- data/spec/spec_helper.rb +6 -0
- data/spec/support/classes_for_policy_testing.rb +36 -0
- data/spec/support/shared_contexts.rb +1 -1
- data/spec/unit/yaks/collection_mapper_spec.rb +34 -9
- data/spec/unit/yaks/collection_resource_spec.rb +4 -4
- data/spec/unit/yaks/config/dsl_spec.rb +91 -0
- data/spec/unit/yaks/config_spec.rb +10 -6
- data/spec/unit/yaks/default_policy/derive_mapper_from_object_spec.rb +80 -0
- data/spec/unit/yaks/default_policy_spec.rb +50 -0
- data/spec/unit/yaks/{serializer → format}/hal_spec.rb +1 -1
- data/spec/unit/yaks/format/json_api_spec.rb +42 -0
- data/spec/unit/yaks/format_spec.rb +12 -0
- data/spec/unit/yaks/fp/hash_updatable_spec.rb +22 -0
- data/spec/unit/yaks/fp/updatable_spec.rb +22 -0
- data/spec/unit/yaks/mapper/association_mapper_spec.rb +60 -0
- data/spec/unit/yaks/mapper/association_spec.rb +96 -41
- data/spec/unit/yaks/mapper/attribute_spec.rb +20 -0
- data/spec/unit/yaks/mapper/class_methods_spec.rb +49 -10
- data/spec/unit/yaks/mapper/config_spec.rb +25 -50
- data/spec/unit/yaks/mapper/has_many_spec.rb +33 -5
- data/spec/unit/yaks/mapper/has_one_spec.rb +32 -17
- data/spec/unit/yaks/mapper/link_spec.rb +44 -12
- data/spec/unit/yaks/mapper_spec.rb +45 -17
- data/spec/unit/yaks/resource_spec.rb +41 -7
- data/yaks.gemspec +7 -1
- metadata +72 -21
- data/examples/hal01.rb +0 -126
- data/examples/jsonapi01.rb +0 -68
- data/examples/jsonapi02.rb +0 -62
- data/examples/jsonapi03.rb +0 -86
- data/spec/support/serializers.rb +0 -14
- data/spec/unit/yaks/serializer_spec.rb +0 -12
data/lib/yaks/resource.rb
CHANGED
@@ -1,11 +1,12 @@
|
|
1
1
|
module Yaks
|
2
2
|
class Resource
|
3
3
|
include Equalizer.new(:type, :links, :attributes, :subresources)
|
4
|
+
include FP::HashUpdatable.new(:type, :links, :attributes, :subresources)
|
4
5
|
include Enumerable
|
5
6
|
|
6
7
|
attr_reader :type, :attributes, :links, :subresources
|
7
8
|
|
8
|
-
def initialize(options)
|
9
|
+
def initialize(options = {})
|
9
10
|
@type = options.fetch(:type, nil)
|
10
11
|
@attributes = options.fetch(:attributes, {})
|
11
12
|
@links = options.fetch(:links, [])
|
@@ -16,16 +17,13 @@ module Yaks
|
|
16
17
|
attributes[attr]
|
17
18
|
end
|
18
19
|
|
19
|
-
# def type
|
20
|
-
# end
|
21
|
-
|
22
20
|
def each
|
23
21
|
return to_enum unless block_given?
|
24
22
|
yield self
|
25
23
|
end
|
26
24
|
|
27
25
|
def self_link
|
28
|
-
links.find do |link|
|
26
|
+
links.reverse.find do |link|
|
29
27
|
link.rel.equal? :self
|
30
28
|
end
|
31
29
|
end
|
@@ -37,5 +35,17 @@ module Yaks
|
|
37
35
|
def null_resource?
|
38
36
|
false
|
39
37
|
end
|
38
|
+
|
39
|
+
def update_attributes(new_attrs)
|
40
|
+
update(attributes: @attributes.merge(new_attrs))
|
41
|
+
end
|
42
|
+
|
43
|
+
def add_link(link)
|
44
|
+
update(links: @links + [link])
|
45
|
+
end
|
46
|
+
|
47
|
+
def add_subresource(rel, subresource)
|
48
|
+
update(subresources: @subresources.merge(rel => subresource))
|
49
|
+
end
|
40
50
|
end
|
41
51
|
end
|
data/lib/yaks/version.rb
CHANGED
data/lib/yaks.rb
CHANGED
@@ -11,19 +11,21 @@ require 'rack/accept'
|
|
11
11
|
|
12
12
|
require 'yaks/util'
|
13
13
|
require 'yaks/fp'
|
14
|
+
require 'yaks/fp/updatable'
|
15
|
+
require 'yaks/fp/hash_updatable'
|
14
16
|
require 'yaks/primitivize'
|
15
17
|
|
16
18
|
require 'yaks/default_policy'
|
17
19
|
|
18
20
|
module Yaks
|
21
|
+
# A PORO
|
19
22
|
Undefined = Object.new
|
23
|
+
# Set the Root constant as the gems root path
|
20
24
|
Root = Pathname(__FILE__).join('../..')
|
21
25
|
|
22
|
-
YAKS_DEFAULT_OPTIONS = {
|
23
|
-
singular_links: [:self, :profile]
|
24
|
-
}
|
25
|
-
|
26
26
|
class << self
|
27
|
+
# @param [Proc] blk
|
28
|
+
# @return [Yaks::Config]
|
27
29
|
def new(&blk)
|
28
30
|
Yaks::Config.new(&blk)
|
29
31
|
end
|
@@ -37,17 +39,21 @@ require 'yaks/null_resource'
|
|
37
39
|
require 'yaks/resource/link'
|
38
40
|
require 'yaks/collection_resource'
|
39
41
|
|
42
|
+
require 'yaks/mapper/class_methods'
|
43
|
+
require 'yaks/mapper'
|
44
|
+
require 'yaks/mapper/attribute'
|
40
45
|
require 'yaks/mapper/link'
|
41
46
|
require 'yaks/mapper/association'
|
47
|
+
require 'yaks/mapper/association_mapper'
|
42
48
|
require 'yaks/mapper/has_one'
|
43
49
|
require 'yaks/mapper/has_many'
|
44
50
|
require 'yaks/mapper/config'
|
45
|
-
require 'yaks/mapper/class_methods'
|
46
|
-
require 'yaks/mapper'
|
47
51
|
require 'yaks/collection_mapper'
|
48
52
|
|
49
|
-
require 'yaks/
|
50
|
-
require 'yaks/
|
51
|
-
require 'yaks/
|
52
|
-
require 'yaks/
|
53
|
+
require 'yaks/format'
|
54
|
+
require 'yaks/format/hal'
|
55
|
+
require 'yaks/format/json_api'
|
56
|
+
require 'yaks/format/collection_json'
|
57
|
+
|
58
|
+
require 'yaks/config/dsl'
|
53
59
|
require 'yaks/config'
|
@@ -1,23 +1,17 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
|
-
|
3
|
+
require 'acceptance/models'
|
4
|
+
require 'acceptance/json_shared_examples'
|
4
5
|
|
5
|
-
RSpec.
|
6
|
-
let(:input) { load_yaml_fixture(name) }
|
7
|
-
let(:output) { load_json_fixture("#{name}.#{format}") }
|
8
|
-
|
9
|
-
subject { yaks.serialize(input) }
|
10
|
-
|
11
|
-
it { should deep_eql output }
|
12
|
-
end
|
13
|
-
|
14
|
-
RSpec.describe Yaks::Serializer::Hal do
|
6
|
+
RSpec.describe Yaks::Format::Hal do
|
15
7
|
yaks_rel_template = Yaks.new do
|
8
|
+
format_options :hal, plural_links: ['http://literature.example.com/rels/quotes']
|
16
9
|
rel_template "http://literature.example.com/rel/{association_name}"
|
17
10
|
end
|
18
11
|
|
19
12
|
yaks_policy_dsl = Yaks.new do
|
20
|
-
|
13
|
+
format_options :hal, plural_links: ['http://literature.example.com/rels/quotes']
|
14
|
+
derive_rel_from_association do |association|
|
21
15
|
"http://literature.example.com/rel/#{association.name}"
|
22
16
|
end
|
23
17
|
end
|
@@ -26,7 +20,7 @@ RSpec.describe Yaks::Serializer::Hal do
|
|
26
20
|
include_examples 'JSON output format' , yaks_policy_dsl , :hal , 'confucius'
|
27
21
|
end
|
28
22
|
|
29
|
-
RSpec.describe Yaks::
|
23
|
+
RSpec.describe Yaks::Format::JsonApi do
|
30
24
|
config = Yaks.new do
|
31
25
|
default_format :json_api
|
32
26
|
end
|
@@ -34,11 +28,16 @@ RSpec.describe Yaks::Serializer::JsonApi do
|
|
34
28
|
include_examples 'JSON output format' , config , :json_api , 'confucius'
|
35
29
|
end
|
36
30
|
|
37
|
-
RSpec.describe Yaks::
|
38
|
-
|
31
|
+
RSpec.describe Yaks::Format::CollectionJson do
|
32
|
+
youtypeit_yaks = Yaks.new do
|
33
|
+
default_format :collection_json
|
34
|
+
namespace Youtypeitwepostit
|
35
|
+
end
|
36
|
+
|
37
|
+
confucius_yaks = Yaks.new do
|
39
38
|
default_format :collection_json
|
40
|
-
mapper_namespace Youtypeitwepostit
|
41
39
|
end
|
42
40
|
|
43
|
-
include_examples 'JSON output format'
|
41
|
+
include_examples 'JSON output format', youtypeit_yaks, :collection, 'youtypeitwepostit'
|
42
|
+
include_examples 'JSON output format', confucius_yaks, :collection, 'confucius'
|
44
43
|
end
|
data/spec/acceptance/models.rb
CHANGED
@@ -17,7 +17,7 @@ class Era
|
|
17
17
|
end
|
18
18
|
|
19
19
|
class LiteratureBaseMapper < Yaks::Mapper
|
20
|
-
link :profile, 'http://literature.example.com/profiles/{mapper_name}'
|
20
|
+
link :profile, 'http://literature.example.com/profiles/{mapper_name}', expand: true
|
21
21
|
link :self, 'http://literature.example.com/{mapper_name}/{id}'
|
22
22
|
end
|
23
23
|
|
@@ -25,7 +25,7 @@ class ScholarMapper < LiteratureBaseMapper
|
|
25
25
|
attributes :id, :name, :pinyin, :latinized
|
26
26
|
has_many :works
|
27
27
|
|
28
|
-
link 'http://literature.example.com/rels/quotes', 'http://literature.example.com/quotes/?author={downcased_pinyin}&q={query}', expand: [:downcased_pinyin]
|
28
|
+
link 'http://literature.example.com/rels/quotes', 'http://literature.example.com/quotes/?author={downcased_pinyin}&q={query}', expand: [:downcased_pinyin], title: 'Search for quotes'
|
29
29
|
link :self, 'http://literature.example.com/authors/{downcased_pinyin}'
|
30
30
|
|
31
31
|
def downcased_pinyin
|
@@ -14,14 +14,14 @@ RSpec.describe 'Mapping domain models to Resource objects' do
|
|
14
14
|
|
15
15
|
its(:subresources) {
|
16
16
|
should eq(
|
17
|
-
"rel:
|
18
|
-
"rel:
|
17
|
+
"rel:pet_peeve" => Yaks::Resource.new(type:'pet_peeve', attributes: {id: 4, type: 'parsing with regexps'}),
|
18
|
+
"rel:pets" => Yaks::CollectionResource.new(
|
19
19
|
type: 'pet',
|
20
20
|
members: [
|
21
21
|
Yaks::Resource.new(type: 'pet', attributes: {:id => 2, :species => "dog", :name => "boingboing"}),
|
22
22
|
Yaks::Resource.new(type: 'pet', attributes: {:id => 3, :species => "cat", :name => "wassup"})
|
23
23
|
],
|
24
|
-
|
24
|
+
collection_rel: 'rel:pets'
|
25
25
|
)
|
26
26
|
)
|
27
27
|
}
|
@@ -0,0 +1,39 @@
|
|
1
|
+
{
|
2
|
+
"collection": {
|
3
|
+
"version": "1.0",
|
4
|
+
"href": "http://literature.example.com/authors/kongzi",
|
5
|
+
"items": [
|
6
|
+
{
|
7
|
+
"href": "http://literature.example.com/authors/kongzi",
|
8
|
+
"data": [
|
9
|
+
{
|
10
|
+
"name": "id",
|
11
|
+
"value": 9
|
12
|
+
},
|
13
|
+
{
|
14
|
+
"name": "name",
|
15
|
+
"value": "孔子"
|
16
|
+
},
|
17
|
+
{
|
18
|
+
"name": "pinyin",
|
19
|
+
"value": "Kongzi"
|
20
|
+
},
|
21
|
+
{
|
22
|
+
"name": "latinized",
|
23
|
+
"value": "Confucius"
|
24
|
+
}
|
25
|
+
],
|
26
|
+
"links": [
|
27
|
+
{
|
28
|
+
"rel": "profile",
|
29
|
+
"href": "http://literature.example.com/profiles/scholar"
|
30
|
+
},
|
31
|
+
{
|
32
|
+
"rel": "http://literature.example.com/rels/quotes",
|
33
|
+
"href": "http://literature.example.com/quotes/?author=kongzi&q={query}"
|
34
|
+
}
|
35
|
+
]
|
36
|
+
}
|
37
|
+
]
|
38
|
+
}
|
39
|
+
}
|
@@ -6,10 +6,13 @@
|
|
6
6
|
"_links": {
|
7
7
|
"self": { "href": "http://literature.example.com/authors/kongzi" },
|
8
8
|
"profile": { "href": "http://literature.example.com/profiles/scholar" },
|
9
|
-
"http://literature.example.com/rels/quotes":
|
10
|
-
|
11
|
-
|
12
|
-
|
9
|
+
"http://literature.example.com/rels/quotes": [
|
10
|
+
{
|
11
|
+
"href": "http://literature.example.com/quotes/?author=kongzi&q={query}",
|
12
|
+
"templated": true,
|
13
|
+
"title": "Search for quotes"
|
14
|
+
}
|
15
|
+
]
|
13
16
|
},
|
14
17
|
"_embedded": {
|
15
18
|
"http://literature.example.com/rel/works": [
|
data/spec/spec_helper.rb
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
require 'rspec/its'
|
2
|
+
require 'bogus/rspec'
|
2
3
|
|
3
4
|
require 'yaks'
|
4
5
|
require 'virtus'
|
@@ -13,6 +14,7 @@ require_relative 'support/fixtures'
|
|
13
14
|
require_relative 'support/shared_contexts'
|
14
15
|
require_relative 'support/youtypeit_models_mappers'
|
15
16
|
require_relative 'support/deep_eql'
|
17
|
+
require_relative 'support/classes_for_policy_testing'
|
16
18
|
|
17
19
|
|
18
20
|
RSpec.configure do |rspec|
|
@@ -21,3 +23,7 @@ RSpec.configure do |rspec|
|
|
21
23
|
#rspec.disable_monkey_patching!
|
22
24
|
rspec.raise_errors_for_deprecations!
|
23
25
|
end
|
26
|
+
|
27
|
+
Bogus.configure do |bogus|
|
28
|
+
bogus.search_modules << Yaks
|
29
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
# Used by Yaks::DefaultPolicy* tests to test various name inference schemes
|
2
|
+
|
3
|
+
class SoyMapper ; end
|
4
|
+
class Soy ; end
|
5
|
+
class Wheat ; end
|
6
|
+
|
7
|
+
module MyMappers
|
8
|
+
class SoyMapper ; end
|
9
|
+
end
|
10
|
+
|
11
|
+
class SoyCollectionMapper ; end
|
12
|
+
|
13
|
+
module Namespace
|
14
|
+
module Nested
|
15
|
+
class Rye ; end
|
16
|
+
end
|
17
|
+
|
18
|
+
class RyeMapper ; end
|
19
|
+
class RyeCollectionMapper ; end
|
20
|
+
|
21
|
+
class CollectionMapper ; end
|
22
|
+
|
23
|
+
class ShoeMapper ; end
|
24
|
+
end
|
25
|
+
|
26
|
+
module DislikesCollectionMapper
|
27
|
+
def self.const_get(const)
|
28
|
+
raise "not a NameError" if const.to_s == 'CollectionMapper'
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
module DislikesOtherMappers
|
33
|
+
def self.const_get(const)
|
34
|
+
raise "not a NameError" if const.to_s != 'CollectionMapper'
|
35
|
+
end
|
36
|
+
end
|
@@ -7,14 +7,15 @@ RSpec.describe Yaks::CollectionMapper do
|
|
7
7
|
let(:mapper_class) { described_class }
|
8
8
|
|
9
9
|
let(:context) {
|
10
|
-
{
|
10
|
+
{ item_mapper: item_mapper,
|
11
11
|
policy: policy,
|
12
12
|
env: {},
|
13
13
|
mapper_stack: []
|
14
14
|
}
|
15
15
|
}
|
16
|
+
|
16
17
|
let(:collection) { [] }
|
17
|
-
let(:
|
18
|
+
let(:item_mapper) { Class.new(Yaks::Mapper) { type 'the_type' } }
|
18
19
|
let(:policy) { Yaks::DefaultPolicy.new }
|
19
20
|
|
20
21
|
it 'should map the collection' do
|
@@ -23,13 +24,13 @@ RSpec.describe Yaks::CollectionMapper do
|
|
23
24
|
links: [],
|
24
25
|
attributes: {},
|
25
26
|
members: [],
|
26
|
-
|
27
|
+
collection_rel: 'rel:the_types'
|
27
28
|
)
|
28
29
|
end
|
29
30
|
|
30
31
|
context 'with members' do
|
31
32
|
let(:collection) { [boingboing, wassup]}
|
32
|
-
let(:
|
33
|
+
let(:item_mapper) { PetMapper }
|
33
34
|
|
34
35
|
it 'should map the members' do
|
35
36
|
expect(mapper.call(collection)).to eql Yaks::CollectionResource.new(
|
@@ -40,7 +41,31 @@ RSpec.describe Yaks::CollectionMapper do
|
|
40
41
|
Yaks::Resource.new(type: 'pet', attributes: {:id => 2, :species => "dog", :name => "boingboing"}),
|
41
42
|
Yaks::Resource.new(type: 'pet', attributes: {:id => 3, :species => "cat", :name => "wassup"})
|
42
43
|
],
|
43
|
-
|
44
|
+
collection_rel: 'rel:pets'
|
45
|
+
)
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
context 'without an item_mapper in the context' do
|
50
|
+
let(:context) {
|
51
|
+
{
|
52
|
+
policy: policy,
|
53
|
+
env: {},
|
54
|
+
mapper_stack: []
|
55
|
+
}
|
56
|
+
}
|
57
|
+
let(:collection) { [boingboing, wassup]}
|
58
|
+
|
59
|
+
it 'should infer the item mapper' do
|
60
|
+
expect(mapper.call(collection)).to eql Yaks::CollectionResource.new(
|
61
|
+
type: nil,
|
62
|
+
links: [],
|
63
|
+
attributes: {},
|
64
|
+
members: [
|
65
|
+
Yaks::Resource.new(type: 'pet', attributes: {:id => 2, :species => "dog", :name => "boingboing"}),
|
66
|
+
Yaks::Resource.new(type: 'pet', attributes: {:id => 3, :species => "cat", :name => "wassup"})
|
67
|
+
],
|
68
|
+
collection_rel: 'collection'
|
44
69
|
)
|
45
70
|
end
|
46
71
|
end
|
@@ -65,7 +90,7 @@ RSpec.describe Yaks::CollectionMapper do
|
|
65
90
|
links: [],
|
66
91
|
attributes: { foo: 123, bar: 'pi la~~~' },
|
67
92
|
members: [],
|
68
|
-
|
93
|
+
collection_rel: 'rel:the_types'
|
69
94
|
)
|
70
95
|
end
|
71
96
|
end
|
@@ -83,7 +108,7 @@ RSpec.describe Yaks::CollectionMapper do
|
|
83
108
|
links: [ Yaks::Resource::Link.new(:self, 'http://api.example.com/orders', {}) ],
|
84
109
|
attributes: { },
|
85
110
|
members: [],
|
86
|
-
|
111
|
+
collection_rel: 'rel:the_types'
|
87
112
|
)
|
88
113
|
end
|
89
114
|
end
|
@@ -100,7 +125,7 @@ RSpec.describe Yaks::CollectionMapper do
|
|
100
125
|
end
|
101
126
|
|
102
127
|
let(:collection) { [boingboing, wassup]}
|
103
|
-
let(:
|
128
|
+
let(:item_mapper) { PetMapper }
|
104
129
|
|
105
130
|
it 'should use the redefined collection method' do
|
106
131
|
expect(mapper.call(collection)).to eql Yaks::CollectionResource.new(
|
@@ -110,7 +135,7 @@ RSpec.describe Yaks::CollectionMapper do
|
|
110
135
|
members: [
|
111
136
|
Yaks::Resource.new(type: 'pet', attributes: {:id => 3, :species => "cat", :name => "wassup"})
|
112
137
|
],
|
113
|
-
|
138
|
+
collection_rel: 'rel:pets'
|
114
139
|
)
|
115
140
|
end
|
116
141
|
end
|
@@ -13,7 +13,7 @@ RSpec.describe Yaks::CollectionResource do
|
|
13
13
|
its(:attributes) { should eql({}) }
|
14
14
|
its(:members) { should eql [] }
|
15
15
|
its(:subresources) { should eql({}) }
|
16
|
-
its(:
|
16
|
+
its(:collection_rel) { should eql('members') }
|
17
17
|
end
|
18
18
|
|
19
19
|
context 'with a full constructor' do
|
@@ -32,7 +32,7 @@ RSpec.describe Yaks::CollectionResource do
|
|
32
32
|
attributes: { customer: 'John Doe', price: 10.00 }
|
33
33
|
)
|
34
34
|
],
|
35
|
-
|
35
|
+
collection_rel: 'http://api.example.org/rels/orders'
|
36
36
|
}
|
37
37
|
}
|
38
38
|
|
@@ -51,7 +51,7 @@ RSpec.describe Yaks::CollectionResource do
|
|
51
51
|
)
|
52
52
|
]
|
53
53
|
}
|
54
|
-
its(:
|
54
|
+
its(:collection_rel) { should eq 'http://api.example.org/rels/orders'}
|
55
55
|
|
56
56
|
its(:subresources) { should eql(
|
57
57
|
'http://api.example.org/rels/orders' => Yaks::CollectionResource.new(
|
@@ -68,7 +68,7 @@ RSpec.describe Yaks::CollectionResource do
|
|
68
68
|
attributes: { customer: 'John Doe', price: 10.00 }
|
69
69
|
)
|
70
70
|
],
|
71
|
-
|
71
|
+
collection_rel: 'http://api.example.org/rels/orders'
|
72
72
|
)
|
73
73
|
)
|
74
74
|
}
|
@@ -0,0 +1,91 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
RSpec.describe Yaks::Config::DSL do
|
4
|
+
subject!(:dsl) { described_class.new(yaks_config, &config_block) }
|
5
|
+
|
6
|
+
let(:yaks_config) { Yaks::Config.new }
|
7
|
+
let(:config_block) { nil }
|
8
|
+
|
9
|
+
def self.configure(&blk)
|
10
|
+
let(:config_block) { blk }
|
11
|
+
end
|
12
|
+
|
13
|
+
describe '#initialize' do
|
14
|
+
its(:config) { should equal yaks_config }
|
15
|
+
|
16
|
+
it 'should set a default policy' do
|
17
|
+
expect(yaks_config.policy_class.new).to be_a_kind_of Yaks::DefaultPolicy
|
18
|
+
end
|
19
|
+
|
20
|
+
it 'should execute the given block in instance scope' do
|
21
|
+
dsl = described_class.new(yaks_config) do
|
22
|
+
@config = :foo
|
23
|
+
end
|
24
|
+
expect(dsl.config).to be :foo
|
25
|
+
end
|
26
|
+
|
27
|
+
describe 'policy redefinitions' do
|
28
|
+
configure do
|
29
|
+
derive_type_from_mapper_class do |mapper_class|
|
30
|
+
:inside_redefined_policy_method
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
it 'should delegate and redefine' do
|
35
|
+
expect(yaks_config.policy.derive_type_from_mapper_class(nil)).to be :inside_redefined_policy_method
|
36
|
+
end
|
37
|
+
|
38
|
+
it 'should not change the original class definition' do
|
39
|
+
expect(Yaks::DefaultPolicy.new.derive_type_from_mapper_class(fake(name: 'FooMapper'))).to eql 'foo'
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
describe '#format_options' do
|
45
|
+
configure { format_options :hal, singular_link: [:self] }
|
46
|
+
specify { expect(yaks_config.format_options[:hal].should eq(singular_link: [:self])) }
|
47
|
+
end
|
48
|
+
|
49
|
+
describe '#default_format' do
|
50
|
+
configure { default_format :json_api }
|
51
|
+
specify { expect(yaks_config.default_format).to be :json_api }
|
52
|
+
end
|
53
|
+
|
54
|
+
describe '#policy' do
|
55
|
+
configure { policy 'MyPolicyClass' }
|
56
|
+
specify { expect(yaks_config.policy_class).to eql 'MyPolicyClass' }
|
57
|
+
end
|
58
|
+
|
59
|
+
describe '#rel_template' do
|
60
|
+
configure { rel_template 'rels:{rel}' }
|
61
|
+
specify { expect(yaks_config.policy_options[:rel_template]).to eql 'rels:{rel}' }
|
62
|
+
end
|
63
|
+
|
64
|
+
describe '#mapper_namespace' do
|
65
|
+
configure { mapper_namespace RSpec }
|
66
|
+
specify { expect(yaks_config.policy_options[:namespace]).to eql RSpec }
|
67
|
+
end
|
68
|
+
|
69
|
+
describe '#map_to_primitive' do
|
70
|
+
Foo = Class.new do
|
71
|
+
attr_reader :foo
|
72
|
+
|
73
|
+
def initialize(foo)
|
74
|
+
@foo = foo
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
configure { map_to_primitive(Foo) {|c| c.foo } }
|
79
|
+
specify { expect(yaks_config.primitivize.call({:abc => Foo.new('hello')})).to eql 'abc' => 'hello' }
|
80
|
+
end
|
81
|
+
|
82
|
+
describe '#after' do
|
83
|
+
configure do
|
84
|
+
after {|x| x + 1}
|
85
|
+
after {|x| x + 10}
|
86
|
+
end
|
87
|
+
it 'should register the block' do
|
88
|
+
expect(yaks_config.steps.inject(0) {|memo, step| step.call(memo)}).to be 11
|
89
|
+
end
|
90
|
+
end
|
91
|
+
end
|
@@ -56,7 +56,7 @@ RSpec.describe Yaks::Config do
|
|
56
56
|
|
57
57
|
describe '#serialize' do
|
58
58
|
configure do
|
59
|
-
rel_template 'http://api.mysuperfriends.com/{
|
59
|
+
rel_template 'http://api.mysuperfriends.com/{rel}'
|
60
60
|
format_options :hal, plural_links: [:copyright]
|
61
61
|
end
|
62
62
|
|
@@ -102,7 +102,7 @@ RSpec.describe Yaks::Config do
|
|
102
102
|
end
|
103
103
|
end
|
104
104
|
|
105
|
-
|
105
|
+
describe '#format_class' do
|
106
106
|
configure do
|
107
107
|
default_format :collection_json
|
108
108
|
end
|
@@ -111,19 +111,23 @@ RSpec.describe Yaks::Config do
|
|
111
111
|
{ 'HTTP_ACCEPT' => 'application/hal+json;q=0.8, application/vnd.api+json' }
|
112
112
|
}
|
113
113
|
|
114
|
-
it 'should
|
114
|
+
it 'should fall back to the default when no HTTP_ACCEPT key is present' do
|
115
|
+
expect(config.format_class({}, {})).to equal Yaks::Format::CollectionJson
|
116
|
+
end
|
117
|
+
|
118
|
+
it 'should detect format based on accept header' do
|
115
119
|
rack_env = { 'HTTP_ACCEPT' => 'application/hal+json;q=0.8, application/vnd.api+json' }
|
116
|
-
expect(config.
|
120
|
+
expect(config.format_class({}, rack_env)).to equal Yaks::Format::JsonApi
|
117
121
|
end
|
118
122
|
|
119
123
|
it 'should know to pick the best match' do
|
120
124
|
rack_env = { 'HTTP_ACCEPT' => 'application/hal+json;q=0.8, application/vnd.api+json;q=0.7' }
|
121
|
-
expect(config.
|
125
|
+
expect(config.format_class({}, rack_env)).to equal Yaks::Format::Hal
|
122
126
|
end
|
123
127
|
|
124
128
|
it 'should fall back to the default when no mime type is recognized' do
|
125
129
|
rack_env = { 'HTTP_ACCEPT' => 'text/html, application/json' }
|
126
|
-
expect(config.
|
130
|
+
expect(config.format_class({}, rack_env)).to equal Yaks::Format::CollectionJson
|
127
131
|
end
|
128
132
|
end
|
129
133
|
end
|