yaks 0.4.2 → 0.4.3
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 +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
|