yaks 0.6.0.alpha.1 → 0.6.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 +4 -4
- data/Rakefile +46 -0
- data/lib/yaks/attributes.rb +45 -0
- data/lib/yaks/collection_resource.rb +1 -45
- data/lib/yaks/config/dsl.rb +15 -6
- data/lib/yaks/config.rb +1 -1
- data/lib/yaks/configurable.rb +20 -0
- data/lib/yaks/default_policy.rb +0 -8
- data/lib/yaks/errors.rb +3 -0
- data/lib/yaks/format/hal.rb +13 -2
- data/lib/yaks/format/halo.rb +29 -0
- data/lib/yaks/mapper/association.rb +18 -13
- data/lib/yaks/mapper/association_mapper.rb +1 -1
- data/lib/yaks/mapper/attribute.rb +1 -3
- data/lib/yaks/mapper/class_methods.rb +24 -16
- data/lib/yaks/mapper/config.rb +13 -28
- data/lib/yaks/mapper/control.rb +38 -0
- data/lib/yaks/mapper/has_many.rb +4 -8
- data/lib/yaks/mapper/link.rb +10 -2
- data/lib/yaks/mapper.rb +11 -2
- data/lib/yaks/resource/control.rb +11 -0
- data/lib/yaks/resource/link.rb +1 -7
- data/lib/yaks/resource.rb +9 -13
- data/lib/yaks/runner.rb +2 -4
- data/lib/yaks/serializer.rb +12 -0
- data/lib/yaks/stateful_builder.rb +54 -0
- data/lib/yaks/version.rb +1 -1
- data/lib/yaks.rb +16 -7
- data/spec/acceptance/acceptance_spec.rb +14 -4
- data/spec/acceptance/models.rb +9 -0
- data/spec/integration/map_to_resource_spec.rb +1 -1
- data/spec/json/confucius.halo.json +80 -0
- data/spec/spec_helper.rb +5 -0
- data/spec/support/shared_contexts.rb +1 -1
- data/spec/unit/yaks/attributes_spec.rb +65 -0
- data/spec/unit/yaks/collection_mapper_spec.rb +1 -1
- data/spec/unit/yaks/collection_resource_spec.rb +7 -25
- data/spec/unit/yaks/config/dsl_spec.rb +5 -0
- data/spec/unit/yaks/config_spec.rb +2 -1
- data/spec/unit/yaks/configurable_spec.rb +25 -0
- data/spec/unit/yaks/default_policy_spec.rb +1 -7
- data/spec/unit/yaks/format/collection_json_spec.rb +1 -1
- data/spec/unit/yaks/format/hal_spec.rb +2 -2
- data/spec/unit/yaks/format/html_spec.rb +5 -0
- data/spec/unit/yaks/format/json_api_spec.rb +1 -1
- data/spec/unit/yaks/format_spec.rb +1 -5
- data/spec/unit/yaks/mapper/association_mapper_spec.rb +2 -2
- data/spec/unit/yaks/mapper/association_spec.rb +27 -3
- data/spec/unit/yaks/mapper/class_methods_spec.rb +17 -1
- data/spec/unit/yaks/mapper/config_spec.rb +16 -8
- data/spec/unit/yaks/mapper/has_many_spec.rb +15 -2
- data/spec/unit/yaks/mapper/has_one_spec.rb +1 -1
- data/spec/unit/yaks/mapper/link_spec.rb +12 -2
- data/spec/unit/yaks/mapper_spec.rb +51 -22
- data/spec/unit/yaks/resource/link_spec.rb +2 -1
- data/spec/unit/yaks/resource_spec.rb +16 -9
- data/spec/unit/yaks/runner_spec.rb +22 -2
- data/spec/unit/yaks/serializer_spec.rb +20 -0
- data/spec/unit/yaks/stateful_builder_spec.rb +41 -0
- data/yaks.gemspec +1 -0
- metadata +39 -11
- data/lib/yaks/fp/hash_updatable.rb +0 -19
- data/lib/yaks/fp/updatable.rb +0 -17
- data/spec/unit/yaks/fp/hash_updatable_spec.rb +0 -22
- data/spec/unit/yaks/fp/updatable_spec.rb +0 -22
data/lib/yaks/runner.rb
CHANGED
@@ -56,7 +56,7 @@ module Yaks
|
|
56
56
|
|
57
57
|
def primitivizer
|
58
58
|
->(input) do
|
59
|
-
if format_class.serializer
|
59
|
+
if format_class.serializer.equal? :json
|
60
60
|
primitivize.call(input)
|
61
61
|
else
|
62
62
|
input
|
@@ -73,9 +73,7 @@ module Yaks
|
|
73
73
|
memoize :format_name
|
74
74
|
|
75
75
|
def serializer
|
76
|
-
serializers.fetch(format_class.serializer)
|
77
|
-
policy.serializer_for_format(format_class)
|
78
|
-
end
|
76
|
+
serializers.fetch(format_class.serializer)
|
79
77
|
end
|
80
78
|
memoize :serializer
|
81
79
|
|
@@ -0,0 +1,12 @@
|
|
1
|
+
module Yaks
|
2
|
+
module Serializer
|
3
|
+
def self.register(format, serializer)
|
4
|
+
raise "Serializer for #{format} already registered" if all.key? format
|
5
|
+
all[format] = serializer
|
6
|
+
end
|
7
|
+
|
8
|
+
def self.all
|
9
|
+
@serializers ||= {json: JSON.method(:pretty_generate)}
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
@@ -0,0 +1,54 @@
|
|
1
|
+
module Yaks
|
2
|
+
# State monad-ish thing.
|
3
|
+
#
|
4
|
+
# Generate a DSL syntax for immutable classes.
|
5
|
+
#
|
6
|
+
# @example
|
7
|
+
#
|
8
|
+
# # This code
|
9
|
+
# Control.create(:search)
|
10
|
+
# .method("POST")
|
11
|
+
# .href("/search")
|
12
|
+
#
|
13
|
+
# # Can be written as
|
14
|
+
# StatefulBuilder.new(Control, [:method, :href]).create(:search) do
|
15
|
+
# method "POST"
|
16
|
+
# href "/search"
|
17
|
+
# end
|
18
|
+
#
|
19
|
+
class StatefulBuilder < BasicObject
|
20
|
+
def create(*args, &block)
|
21
|
+
@state = @klass.create(*args)
|
22
|
+
instance_eval(&block)
|
23
|
+
@state
|
24
|
+
end
|
25
|
+
|
26
|
+
def initialize(klass, methods)
|
27
|
+
@klass = klass
|
28
|
+
StatefulMethods.new(methods).send(:extend_object, self)
|
29
|
+
end
|
30
|
+
|
31
|
+
def validate_state(method_name, args)
|
32
|
+
unless @state.instance_of?(@klass)
|
33
|
+
::Kernel.raise(
|
34
|
+
IllegalState,
|
35
|
+
"#{@klass}##{method_name}(#{args.map(&:inspect).join(', ')}) "\
|
36
|
+
"returned #{@state.inspect}. Expected instance of #{@klass}"
|
37
|
+
)
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
class StatefulMethods < ::Module
|
42
|
+
def initialize(methods)
|
43
|
+
methods.each { |name| define_stateful_method(name) }
|
44
|
+
end
|
45
|
+
|
46
|
+
def define_stateful_method(method_name)
|
47
|
+
define_method method_name do |*args, &block|
|
48
|
+
@state = @state.public_send(method_name, *args, &block)
|
49
|
+
validate_state(method_name, args)
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
data/lib/yaks/version.rb
CHANGED
data/lib/yaks.rb
CHANGED
@@ -3,6 +3,7 @@
|
|
3
3
|
require 'forwardable'
|
4
4
|
require 'set'
|
5
5
|
require 'pathname'
|
6
|
+
require 'json'
|
6
7
|
|
7
8
|
require 'anima'
|
8
9
|
require 'concord'
|
@@ -11,11 +12,13 @@ require 'uri_template'
|
|
11
12
|
require 'rack/accept'
|
12
13
|
|
13
14
|
require 'yaks/util'
|
15
|
+
require 'yaks/configurable'
|
14
16
|
require 'yaks/fp'
|
15
|
-
require 'yaks/fp/updatable'
|
16
|
-
require 'yaks/fp/hash_updatable'
|
17
17
|
require 'yaks/fp/callable'
|
18
18
|
require 'yaks/primitivize'
|
19
|
+
require 'yaks/attributes'
|
20
|
+
require 'yaks/stateful_builder'
|
21
|
+
require 'yaks/errors'
|
19
22
|
|
20
23
|
require 'yaks/default_policy'
|
21
24
|
|
@@ -41,19 +44,25 @@ require 'yaks/null_resource'
|
|
41
44
|
require 'yaks/resource/link'
|
42
45
|
require 'yaks/collection_resource'
|
43
46
|
|
44
|
-
require 'yaks/mapper/class_methods'
|
45
|
-
require 'yaks/mapper'
|
46
|
-
require 'yaks/mapper/attribute'
|
47
|
-
require 'yaks/mapper/link'
|
48
47
|
require 'yaks/mapper/association'
|
49
|
-
require 'yaks/mapper/association_mapper'
|
50
48
|
require 'yaks/mapper/has_one'
|
51
49
|
require 'yaks/mapper/has_many'
|
50
|
+
require 'yaks/mapper/attribute'
|
51
|
+
require 'yaks/mapper/link'
|
52
|
+
require 'yaks/mapper/control'
|
52
53
|
require 'yaks/mapper/config'
|
54
|
+
require 'yaks/mapper/class_methods'
|
55
|
+
require 'yaks/mapper'
|
56
|
+
require 'yaks/mapper/association_mapper'
|
53
57
|
require 'yaks/collection_mapper'
|
54
58
|
|
59
|
+
require 'yaks/resource/control'
|
60
|
+
|
61
|
+
require 'yaks/serializer'
|
62
|
+
|
55
63
|
require 'yaks/format'
|
56
64
|
require 'yaks/format/hal'
|
65
|
+
require 'yaks/format/halo'
|
57
66
|
require 'yaks/format/json_api'
|
58
67
|
require 'yaks/format/collection_json'
|
59
68
|
|
@@ -6,7 +6,7 @@ require 'acceptance/json_shared_examples'
|
|
6
6
|
RSpec.describe Yaks::Format::Hal do
|
7
7
|
yaks_rel_template = Yaks.new do
|
8
8
|
format_options :hal, plural_links: ['http://literature.example.com/rels/quotes']
|
9
|
-
rel_template "http://literature.example.com/rel/{
|
9
|
+
rel_template "http://literature.example.com/rel/{rel}"
|
10
10
|
skip :serialize
|
11
11
|
end
|
12
12
|
|
@@ -18,8 +18,18 @@ RSpec.describe Yaks::Format::Hal do
|
|
18
18
|
skip :serialize
|
19
19
|
end
|
20
20
|
|
21
|
-
include_examples 'JSON output format'
|
22
|
-
include_examples 'JSON output format'
|
21
|
+
include_examples 'JSON output format', yaks_rel_template, :hal, 'confucius'
|
22
|
+
include_examples 'JSON output format', yaks_policy_dsl, :hal, 'confucius'
|
23
|
+
end
|
24
|
+
|
25
|
+
RSpec.describe Yaks::Format::Halo do
|
26
|
+
yaks = Yaks.new do
|
27
|
+
default_format :halo
|
28
|
+
rel_template "http://literature.example.com/rel/{rel}"
|
29
|
+
skip :serialize
|
30
|
+
end
|
31
|
+
|
32
|
+
include_examples 'JSON output format', yaks, :halo, 'confucius'
|
23
33
|
end
|
24
34
|
|
25
35
|
RSpec.describe Yaks::Format::JsonAPI do
|
@@ -28,7 +38,7 @@ RSpec.describe Yaks::Format::JsonAPI do
|
|
28
38
|
skip :serialize
|
29
39
|
end
|
30
40
|
|
31
|
-
include_examples 'JSON output format'
|
41
|
+
include_examples 'JSON output format', config, :json_api, 'confucius'
|
32
42
|
end
|
33
43
|
|
34
44
|
RSpec.describe Yaks::Format::CollectionJson do
|
data/spec/acceptance/models.rb
CHANGED
@@ -28,6 +28,15 @@ class ScholarMapper < LiteratureBaseMapper
|
|
28
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
|
+
control :search do
|
32
|
+
title 'Find a Scholar'
|
33
|
+
method 'POST'
|
34
|
+
media_type 'application/x-www-form-urlencoded'
|
35
|
+
|
36
|
+
field :name, label: 'Scholar Name', type: 'text'
|
37
|
+
field :pinyin, label: 'Hanyu Pinyin', type: 'text'
|
38
|
+
end
|
39
|
+
|
31
40
|
def downcased_pinyin
|
32
41
|
object.pinyin.downcase
|
33
42
|
end
|
@@ -10,7 +10,7 @@ RSpec.describe 'Mapping domain models to Resource objects' do
|
|
10
10
|
it { should be_a Yaks::Resource }
|
11
11
|
its(:type) { should eql 'friend' }
|
12
12
|
its(:attributes) { should eql(id: 1, name: 'john') }
|
13
|
-
its(:links) { should eql [ Yaks::Resource::Link.new(:copyright, '/api/copyright/2024'
|
13
|
+
its(:links) { should eql [ Yaks::Resource::Link.new(rel: :copyright, uri: '/api/copyright/2024') ] }
|
14
14
|
|
15
15
|
its(:subresources) {
|
16
16
|
should eq(
|
@@ -0,0 +1,80 @@
|
|
1
|
+
{
|
2
|
+
"id": 9,
|
3
|
+
"name": "孔子",
|
4
|
+
"pinyin": "Kongzi",
|
5
|
+
"latinized": "Confucius",
|
6
|
+
"_links": {
|
7
|
+
"self": { "href": "http://literature.example.com/authors/kongzi" },
|
8
|
+
"profile": { "href": "http://literature.example.com/profiles/scholar" },
|
9
|
+
"http://literature.example.com/rels/quotes": {
|
10
|
+
"href": "http://literature.example.com/quotes/?author=kongzi&q={query}",
|
11
|
+
"templated": true,
|
12
|
+
"title": "Search for quotes"
|
13
|
+
}
|
14
|
+
},
|
15
|
+
"_embedded": {
|
16
|
+
"http://literature.example.com/rel/works": [
|
17
|
+
{
|
18
|
+
"id": 11,
|
19
|
+
"chinese_name": "論語",
|
20
|
+
"english_name": "Analects",
|
21
|
+
"_links": {
|
22
|
+
"self": { "href": "http://literature.example.com/work/11" },
|
23
|
+
"profile": { "href": "http://literature.example.com/profiles/work" }
|
24
|
+
},
|
25
|
+
"_embedded": {
|
26
|
+
"http://literature.example.com/rel/quotes": [
|
27
|
+
{
|
28
|
+
"id": 17,
|
29
|
+
"chinese": "廄焚。子退朝,曰:“傷人乎?” 不問馬。"
|
30
|
+
},
|
31
|
+
{
|
32
|
+
"id": 18,
|
33
|
+
"chinese": "子曰:“其恕乎!己所不欲、勿施於人。”"
|
34
|
+
}
|
35
|
+
],
|
36
|
+
"http://literature.example.com/rel/era": {
|
37
|
+
"id": 99,
|
38
|
+
"name": "Zhou Dynasty"
|
39
|
+
}
|
40
|
+
}
|
41
|
+
},
|
42
|
+
{
|
43
|
+
"id": 12,
|
44
|
+
"chinese_name": "易經",
|
45
|
+
"english_name": "Commentaries to the Yi-jing",
|
46
|
+
"_links": {
|
47
|
+
"self": { "href": "http://literature.example.com/work/12" },
|
48
|
+
"profile": { "href": "http://literature.example.com/profiles/work" }
|
49
|
+
},
|
50
|
+
"_embedded": {
|
51
|
+
"http://literature.example.com/rel/quotes": [],
|
52
|
+
"http://literature.example.com/rel/era": null
|
53
|
+
}
|
54
|
+
}
|
55
|
+
]
|
56
|
+
},
|
57
|
+
"_controls": {
|
58
|
+
"search": {
|
59
|
+
"name": "search",
|
60
|
+
"href": null,
|
61
|
+
"title": "Find a Scholar",
|
62
|
+
"method": "POST",
|
63
|
+
"media_type": "application/x-www-form-urlencoded",
|
64
|
+
"fields": [
|
65
|
+
{
|
66
|
+
"name": "name",
|
67
|
+
"label": "Scholar Name",
|
68
|
+
"type": "text",
|
69
|
+
"value": null
|
70
|
+
},
|
71
|
+
{
|
72
|
+
"name": "pinyin",
|
73
|
+
"label": "Hanyu Pinyin",
|
74
|
+
"type": "text",
|
75
|
+
"value": null
|
76
|
+
}
|
77
|
+
]
|
78
|
+
}
|
79
|
+
}
|
80
|
+
}
|
data/spec/spec_helper.rb
CHANGED
@@ -1,7 +1,9 @@
|
|
1
1
|
require 'rspec/its'
|
2
2
|
require 'bogus/rspec'
|
3
|
+
require 'timeout'
|
3
4
|
|
4
5
|
require 'yaks'
|
6
|
+
require 'yaks-html'
|
5
7
|
require 'virtus'
|
6
8
|
|
7
9
|
require 'fixture_helpers'
|
@@ -22,6 +24,9 @@ RSpec.configure do |rspec|
|
|
22
24
|
rspec.backtrace_exclusion_patterns = [] if ENV['FULLSTACK']
|
23
25
|
rspec.disable_monkey_patching!
|
24
26
|
rspec.raise_errors_for_deprecations!
|
27
|
+
rspec.around(:each) do |example|
|
28
|
+
Timeout.timeout(1, &example)
|
29
|
+
end
|
25
30
|
end
|
26
31
|
|
27
32
|
Bogus.configure do |bogus|
|
@@ -31,7 +31,7 @@ RSpec.shared_context 'plant collection resource' do
|
|
31
31
|
[ :oak , :self , 'http://api.example.com/plants/15/oak' ],
|
32
32
|
[ :passiflora , :self , 'http://api.example.com/plants/33/passiflora' ],
|
33
33
|
].each do |name, type, uri|
|
34
|
-
let(:"#{name}_#{type}_link") { Yaks::Resource::Link.new(type, uri
|
34
|
+
let(:"#{name}_#{type}_link") { Yaks::Resource::Link.new(rel: type, uri: uri) }
|
35
35
|
end
|
36
36
|
|
37
37
|
let(:plain_grass) do
|
@@ -0,0 +1,65 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
RSpec.describe Yaks::Attributes do
|
4
|
+
subject { Class.new { include Yaks::Attributes.new(:foo, bar: 3) } }
|
5
|
+
|
6
|
+
it 'should have a hash-based constructor' do
|
7
|
+
expect(subject.new(foo: 3, bar: 4).bar).to equal 4
|
8
|
+
end
|
9
|
+
|
10
|
+
it 'should have defaults constructor' do
|
11
|
+
expect(subject.new(foo: 3).bar).to equal 3
|
12
|
+
end
|
13
|
+
|
14
|
+
it 'should allow updating through attribute methods' do
|
15
|
+
expect(subject.new(foo: 3).foo(4).to_h).to eql(foo: 4, bar: 3)
|
16
|
+
end
|
17
|
+
|
18
|
+
it 'should add an #append_to method' do
|
19
|
+
expect(subject.new(foo: [6]).append_to(:foo, 7, 8).foo).to eql [6, 7, 8]
|
20
|
+
end
|
21
|
+
|
22
|
+
context 'with all defaults' do
|
23
|
+
subject { Class.new { include Yaks::Attributes.new(foo: 5, bar: 3) } }
|
24
|
+
|
25
|
+
it 'should be able to construct without arguments' do
|
26
|
+
expect(subject.new.to_h).to eql(foo: 5, bar: 3)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
context 'without any defaults' do
|
31
|
+
subject { Class.new { include Yaks::Attributes.new(:foo, :bar) } }
|
32
|
+
|
33
|
+
it 'should allow setting all attributes' do
|
34
|
+
expect(subject.new(foo: 5, bar: 6).bar).to equal 6
|
35
|
+
end
|
36
|
+
|
37
|
+
it 'should expect all attributes' do
|
38
|
+
expect { subject.new(foo: 5) }.to raise_exception
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
context 'when extending' do
|
43
|
+
subject { Class.new(super()) { include attributes.add(baz: 7) } }
|
44
|
+
|
45
|
+
it 'should make the new attributes available' do
|
46
|
+
expect(subject.new(foo: 3, baz: 6).baz).to equal 6
|
47
|
+
end
|
48
|
+
|
49
|
+
it 'should make the old attributes available' do
|
50
|
+
expect(subject.new(foo: 3, baz: 6).foo).to equal 3
|
51
|
+
end
|
52
|
+
|
53
|
+
context 'without any defaults' do
|
54
|
+
subject { Class.new(super()) { include attributes.add(:bax) } }
|
55
|
+
|
56
|
+
it 'should allow setting all attributes' do
|
57
|
+
expect(subject.new(foo: 5, bar: 6, bax: 7).bax).to equal 7
|
58
|
+
end
|
59
|
+
|
60
|
+
it 'should expect all attributes' do
|
61
|
+
expect { subject.new(foo: 5, bar: 6) }.to raise_exception
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
@@ -108,7 +108,7 @@ RSpec.describe Yaks::CollectionMapper do
|
|
108
108
|
it 'should map the links' do
|
109
109
|
expect(mapper.call(collection)).to eql Yaks::CollectionResource.new(
|
110
110
|
type: 'the_type',
|
111
|
-
links: [ Yaks::Resource::Link.new(:self, 'http://api.example.com/orders'
|
111
|
+
links: [ Yaks::Resource::Link.new(rel: :self, uri: 'http://api.example.com/orders') ],
|
112
112
|
attributes: { },
|
113
113
|
members: [],
|
114
114
|
collection_rel: 'rel:the_types'
|
@@ -21,14 +21,14 @@ RSpec.describe Yaks::CollectionResource do
|
|
21
21
|
{
|
22
22
|
type: 'order',
|
23
23
|
links: [
|
24
|
-
Yaks::Resource::Link.new('http://rels/summary', 'http://order/10/summary'
|
25
|
-
Yaks::Resource::Link.new(:profile, 'http://rels/collection'
|
24
|
+
Yaks::Resource::Link.new(rel: 'http://rels/summary', uri: 'http://order/10/summary'),
|
25
|
+
Yaks::Resource::Link.new(rel: :profile, uri: 'http://rels/collection')
|
26
26
|
],
|
27
27
|
attributes: { total: 10.00 },
|
28
28
|
members: [
|
29
29
|
Yaks::Resource.new(
|
30
30
|
type: 'order',
|
31
|
-
links: [Yaks::Resource::Link.new(:self, 'http://order/10'
|
31
|
+
links: [Yaks::Resource::Link.new(rel: :self, uri: 'http://order/10')],
|
32
32
|
attributes: { customer: 'John Doe', price: 10.00 }
|
33
33
|
)
|
34
34
|
],
|
@@ -38,40 +38,22 @@ RSpec.describe Yaks::CollectionResource do
|
|
38
38
|
|
39
39
|
its(:type) { should eql 'order' }
|
40
40
|
its(:links) { should eql [
|
41
|
-
Yaks::Resource::Link.new('http://rels/summary', 'http://order/10/summary'
|
42
|
-
Yaks::Resource::Link.new(:profile, 'http://rels/collection'
|
41
|
+
Yaks::Resource::Link.new(rel: 'http://rels/summary', uri: 'http://order/10/summary'),
|
42
|
+
Yaks::Resource::Link.new(rel: :profile, uri: 'http://rels/collection')
|
43
43
|
]
|
44
44
|
}
|
45
45
|
its(:attributes) { should eql( total: 10.00 ) }
|
46
46
|
its(:members) { should eql [
|
47
47
|
Yaks::Resource.new(
|
48
48
|
type: 'order',
|
49
|
-
links: [Yaks::Resource::Link.new(:self, 'http://order/10'
|
49
|
+
links: [Yaks::Resource::Link.new(rel: :self, uri: 'http://order/10')],
|
50
50
|
attributes: { customer: 'John Doe', price: 10.00 }
|
51
51
|
)
|
52
52
|
]
|
53
53
|
}
|
54
54
|
its(:collection_rel) { should eq 'http://api.example.org/rels/orders'}
|
55
55
|
|
56
|
-
its(:subresources) { should eql(
|
57
|
-
'http://api.example.org/rels/orders' => Yaks::CollectionResource.new(
|
58
|
-
type: 'order',
|
59
|
-
attributes: { total: 10.00 },
|
60
|
-
links: [
|
61
|
-
Yaks::Resource::Link.new('http://rels/summary', 'http://order/10/summary', {}),
|
62
|
-
Yaks::Resource::Link.new(:profile, 'http://rels/collection', {})
|
63
|
-
],
|
64
|
-
members: [
|
65
|
-
Yaks::Resource.new(
|
66
|
-
type: 'order',
|
67
|
-
links: [Yaks::Resource::Link.new(:self, 'http://order/10', {})],
|
68
|
-
attributes: { customer: 'John Doe', price: 10.00 }
|
69
|
-
)
|
70
|
-
],
|
71
|
-
collection_rel: 'http://api.example.org/rels/orders'
|
72
|
-
)
|
73
|
-
)
|
74
|
-
}
|
56
|
+
its(:subresources) { should eql({}) }
|
75
57
|
|
76
58
|
end
|
77
59
|
end
|
@@ -61,6 +61,11 @@ RSpec.describe Yaks::Config::DSL do
|
|
61
61
|
specify { expect(yaks_config.policy_options[:rel_template]).to eql 'rels:{rel}' }
|
62
62
|
end
|
63
63
|
|
64
|
+
describe '#serializer' do
|
65
|
+
configure { serializer(:json) { |i| "foo #{i}" } }
|
66
|
+
specify { expect(yaks_config.serializers[:json].call(7)).to eql 'foo 7' }
|
67
|
+
end
|
68
|
+
|
64
69
|
describe '#json_serializer' do
|
65
70
|
configure { json_serializer { |i| "foo #{i}" } }
|
66
71
|
specify { expect(yaks_config.serializers[:json].call(7)).to eql 'foo 7' }
|
@@ -14,7 +14,8 @@ RSpec.describe Yaks::Config do
|
|
14
14
|
its(:default_format) { should equal :hal }
|
15
15
|
its(:policy_class) { should < Yaks::DefaultPolicy }
|
16
16
|
its(:primitivize) { should be_a Yaks::Primitivize }
|
17
|
-
its(:serializers) { should eql(
|
17
|
+
its(:serializers) { should eql(Yaks::Serializer.all) }
|
18
|
+
its(:serializers) { should_not equal(Yaks::Serializer.all) }
|
18
19
|
its(:hooks) { should eql([]) }
|
19
20
|
|
20
21
|
it 'should have empty format options' do
|
@@ -0,0 +1,25 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
RSpec.describe Yaks::Configurable do
|
4
|
+
class Creatable
|
5
|
+
def self.create(*args, &block)
|
6
|
+
["->", *args, block.call]
|
7
|
+
end
|
8
|
+
end
|
9
|
+
|
10
|
+
subject do
|
11
|
+
Class.new do
|
12
|
+
include Yaks::Attributes.new(foo: []), Yaks::Configurable
|
13
|
+
|
14
|
+
config_method :bar, append_to: :foo, create: Creatable
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
it 'should generate the config method' do
|
19
|
+
expect(
|
20
|
+
subject.new.bar(1,2,3) { 4 }
|
21
|
+
.bar(:baz) { :booz }
|
22
|
+
.foo
|
23
|
+
).to eql [["->", 1, 2, 3, 4], ["->", :baz, :booz]]
|
24
|
+
end
|
25
|
+
end
|
@@ -4,7 +4,7 @@ RSpec.describe Yaks::DefaultPolicy do
|
|
4
4
|
subject(:policy) { described_class.new( options ) }
|
5
5
|
|
6
6
|
let(:options) { {} }
|
7
|
-
let(:association) { Yaks::Mapper::HasMany.
|
7
|
+
let(:association) { Yaks::Mapper::HasMany.create('shoes') }
|
8
8
|
|
9
9
|
describe '#initialize' do
|
10
10
|
it 'should work without arguments' do
|
@@ -61,10 +61,4 @@ RSpec.describe Yaks::DefaultPolicy do
|
|
61
61
|
end
|
62
62
|
end
|
63
63
|
|
64
|
-
describe '#serializer_for_format' do
|
65
|
-
specify {
|
66
|
-
expect(policy.serializer_for_format(Yaks::Format::JsonAPI).call('foo' => [1,2])).to eql "{\n \"foo\": [\n 1,\n 2\n ]\n}"
|
67
|
-
}
|
68
|
-
end
|
69
|
-
|
70
64
|
end
|
@@ -13,7 +13,7 @@ RSpec.describe Yaks::Format::CollectionJson do
|
|
13
13
|
let(:resource) {
|
14
14
|
Yaks::Resource.new(
|
15
15
|
attributes: {foo: 'fooval', bar: 'barval'},
|
16
|
-
links: [Yaks::Resource::Link.new('the_rel', 'the_uri'
|
16
|
+
links: [Yaks::Resource::Link.new(rel: 'the_rel', uri: 'the_uri')]
|
17
17
|
)
|
18
18
|
}
|
19
19
|
|
@@ -18,8 +18,8 @@ RSpec.describe Yaks::Format::Hal do
|
|
18
18
|
Yaks::Resource.new(
|
19
19
|
attributes: {foo: 'fooval', bar: 'barval'},
|
20
20
|
links: [
|
21
|
-
Yaks::Resource::Link.new('my_plural_rel', 'the_uri1'
|
22
|
-
Yaks::Resource::Link.new('my_plural_rel', 'the_uri2'
|
21
|
+
Yaks::Resource::Link.new(rel: 'my_plural_rel', uri: 'the_uri1'),
|
22
|
+
Yaks::Resource::Link.new(rel: 'my_plural_rel', uri: 'the_uri2')
|
23
23
|
]
|
24
24
|
)
|
25
25
|
}
|
@@ -27,11 +27,7 @@ RSpec.describe Yaks::Format do
|
|
27
27
|
|
28
28
|
describe '.mime_types' do
|
29
29
|
specify do
|
30
|
-
expect(Yaks::Format.mime_types).to eql(
|
31
|
-
collection_json: "application/vnd.collection+json",
|
32
|
-
hal: "application/hal+json",
|
33
|
-
json_api: "application/vnd.api+json"
|
34
|
-
)
|
30
|
+
expect(Yaks::Format.mime_types.values_at(:collection_json, :hal, :json_api)).to eql(["application/vnd.collection+json", "application/hal+json", "application/vnd.api+json"])
|
35
31
|
end
|
36
32
|
end
|
37
33
|
end
|
@@ -26,8 +26,8 @@ RSpec.describe Yaks::Mapper::AssociationMapper do
|
|
26
26
|
expect(association_mapper.call(Yaks::Resource.new)).to eql Yaks::Resource.new(
|
27
27
|
links: [
|
28
28
|
Yaks::Resource::Link.new(
|
29
|
-
'rels:the_rel',
|
30
|
-
'http://this/is_where_the_associated_thing_can_be_found'
|
29
|
+
rel: 'rels:the_rel',
|
30
|
+
uri: 'http://this/is_where_the_associated_thing_can_be_found'
|
31
31
|
)
|
32
32
|
]
|
33
33
|
)
|
@@ -6,7 +6,7 @@ RSpec.describe Yaks::Mapper::Association do
|
|
6
6
|
subject(:association) do
|
7
7
|
described_class.new(
|
8
8
|
name: name,
|
9
|
-
|
9
|
+
item_mapper: mapper,
|
10
10
|
rel: rel,
|
11
11
|
href: href,
|
12
12
|
link_if: link_if
|
@@ -20,13 +20,13 @@ RSpec.describe Yaks::Mapper::Association do
|
|
20
20
|
let(:link_if) { Yaks::Undefined }
|
21
21
|
|
22
22
|
its(:name) { should equal :shoes }
|
23
|
-
its(:
|
23
|
+
its(:item_mapper) { should equal Yaks::Mapper }
|
24
24
|
|
25
25
|
context 'with a minimal constructor' do
|
26
26
|
subject(:association) { described_class.new(name: :foo) }
|
27
27
|
|
28
28
|
its(:name) { should be :foo }
|
29
|
-
its(:
|
29
|
+
its(:item_mapper) { should be Yaks::Undefined }
|
30
30
|
its(:rel) { should be Yaks::Undefined }
|
31
31
|
its(:href) { should be Yaks::Undefined }
|
32
32
|
its(:link_if) { should be Yaks::Undefined }
|
@@ -132,4 +132,28 @@ RSpec.describe Yaks::Mapper::Association do
|
|
132
132
|
end
|
133
133
|
end
|
134
134
|
end
|
135
|
+
|
136
|
+
describe '.create' do
|
137
|
+
it 'should take a name' do
|
138
|
+
expect(described_class.create(:foo).name).to be :foo
|
139
|
+
end
|
140
|
+
|
141
|
+
it 'should optionally take a mapper' do
|
142
|
+
expect(described_class.create(:foo, mapper: :bar).item_mapper).to be :bar
|
143
|
+
end
|
144
|
+
|
145
|
+
it 'should take other options' do
|
146
|
+
expect(described_class.create(:foo, mapper: :bar, href: 'xxx').href).to eql 'xxx'
|
147
|
+
end
|
148
|
+
|
149
|
+
it 'should respect attribute defaults' do
|
150
|
+
expect(described_class.create(:foo, href: 'xxx').item_mapper).to be Yaks::Undefined
|
151
|
+
end
|
152
|
+
|
153
|
+
it 'should not munge the options hash' do
|
154
|
+
opts = {mapper: :foo}
|
155
|
+
described_class.create(:foo, opts)
|
156
|
+
expect(opts).to eql(mapper: :foo)
|
157
|
+
end
|
158
|
+
end
|
135
159
|
end
|