yaks 0.3.1 → 0.4.0.rc1

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.
Files changed (79) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +1 -0
  3. data/CHANGELOG.md +11 -0
  4. data/Gemfile +0 -2
  5. data/LICENSE +7 -0
  6. data/README.md +160 -35
  7. data/Rakefile +2 -1
  8. data/lib/yaks/collection_mapper.rb +25 -18
  9. data/lib/yaks/collection_resource.rb +11 -17
  10. data/lib/yaks/config.rb +96 -0
  11. data/lib/yaks/default_policy.rb +34 -4
  12. data/lib/yaks/fp.rb +18 -0
  13. data/lib/yaks/mapper/association.rb +19 -27
  14. data/lib/yaks/mapper/class_methods.rb +4 -2
  15. data/lib/yaks/mapper/config.rb +24 -39
  16. data/lib/yaks/mapper/has_many.rb +7 -6
  17. data/lib/yaks/mapper/has_one.rb +4 -3
  18. data/lib/yaks/mapper/link.rb +52 -55
  19. data/lib/yaks/mapper.rb +38 -26
  20. data/lib/yaks/null_resource.rb +3 -3
  21. data/lib/yaks/primitivize.rb +29 -27
  22. data/lib/yaks/resource/link.rb +4 -0
  23. data/lib/yaks/resource.rb +18 -7
  24. data/lib/yaks/serializer/collection_json.rb +38 -0
  25. data/lib/yaks/serializer/hal.rb +55 -0
  26. data/lib/yaks/serializer/json_api.rb +61 -0
  27. data/lib/yaks/serializer.rb +25 -4
  28. data/lib/yaks/util.rb +2 -42
  29. data/lib/yaks/version.rb +1 -1
  30. data/lib/yaks.rb +10 -32
  31. data/notes.org +72 -0
  32. data/shaved_yak.gif +0 -0
  33. data/spec/acceptance/acceptance_spec.rb +46 -0
  34. data/spec/acceptance/models.rb +28 -0
  35. data/spec/integration/map_to_resource_spec.rb +11 -15
  36. data/spec/json/confucius.hal.json +23 -0
  37. data/spec/json/confucius.json_api.json +22 -0
  38. data/spec/json/john.hal.json +29 -0
  39. data/spec/json/youtypeitwepostit.collection.json +45 -0
  40. data/spec/spec_helper.rb +12 -1
  41. data/spec/support/shared_contexts.rb +7 -10
  42. data/spec/support/youtypeit_models_mappers.rb +20 -0
  43. data/spec/unit/yaks/collection_mapper_spec.rb +84 -0
  44. data/spec/unit/yaks/collection_resource_spec.rb +72 -0
  45. data/spec/unit/yaks/config_spec.rb +129 -0
  46. data/spec/unit/yaks/fp_spec.rb +31 -0
  47. data/spec/unit/yaks/mapper/association_spec.rb +80 -0
  48. data/spec/{yaks → unit/yaks}/mapper/class_methods_spec.rb +4 -4
  49. data/spec/unit/yaks/mapper/config_spec.rb +191 -0
  50. data/spec/unit/yaks/mapper/has_many_spec.rb +46 -0
  51. data/spec/unit/yaks/mapper/has_one_spec.rb +34 -0
  52. data/spec/unit/yaks/mapper/link_spec.rb +152 -0
  53. data/spec/unit/yaks/mapper_spec.rb +177 -0
  54. data/spec/unit/yaks/resource_spec.rb +40 -0
  55. data/spec/{yaks/hal_serializer_spec.rb → unit/yaks/serializer/hal_spec.rb} +2 -2
  56. data/spec/unit/yaks/serializer_spec.rb +12 -0
  57. data/spec/unit/yaks/util_spec.rb +43 -0
  58. data/spec/yaml/confucius.yaml +10 -0
  59. data/spec/yaml/youtypeitwepostit.yaml +9 -0
  60. data/yaks.gemspec +7 -8
  61. metadata +92 -53
  62. data/Gemfile.lock +0 -111
  63. data/lib/yaks/hal_serializer.rb +0 -59
  64. data/lib/yaks/json_api_serializer.rb +0 -59
  65. data/lib/yaks/link_lookup.rb +0 -23
  66. data/lib/yaks/mapper/lookup.rb +0 -19
  67. data/lib/yaks/mapper/map_links.rb +0 -17
  68. data/lib/yaks/profile_registry.rb +0 -60
  69. data/lib/yaks/rel_registry.rb +0 -20
  70. data/lib/yaks/shared_options.rb +0 -15
  71. data/spec/support/shorthands.rb +0 -22
  72. data/spec/yaks/collection_resource_spec.rb +0 -9
  73. data/spec/yaks/mapper/association_spec.rb +0 -21
  74. data/spec/yaks/mapper/config_spec.rb +0 -77
  75. data/spec/yaks/mapper/has_one_spec.rb +0 -16
  76. data/spec/yaks/mapper/link_spec.rb +0 -38
  77. data/spec/yaks/mapper/map_links_spec.rb +0 -46
  78. data/spec/yaks/mapper_spec.rb +0 -65
  79. data/spec/yaks/resource_spec.rb +0 -23
@@ -1,9 +0,0 @@
1
- require 'spec_helper'
2
-
3
- describe Yaks::CollectionResource do
4
- it 'should normalize its arguments' do
5
- expect(described_class.new(nil, nil)).to eq(
6
- described_class.new(Yaks::List(), Yaks::List())
7
- )
8
- end
9
- end
@@ -1,21 +0,0 @@
1
- require 'spec_helper'
2
-
3
- describe Yaks::Mapper::Association do
4
- describe 'self_link' do
5
- context 'without a :self link' do
6
- subject { described_class.new(nil, nil, nil, Yaks::List(Yaks::Mapper::Link.new(:alternate, '/foo')), {}) }
7
-
8
- it 'should be nil' do
9
- expect(subject.self_link).to be_nil
10
- end
11
- end
12
- end
13
-
14
- context 'with a self link' do
15
- subject { described_class.new(nil, nil, nil, Yaks::List(Yaks::Mapper::Link.new(:self, '/self')), {}) }
16
-
17
- it 'should resolve to the self link' do
18
- expect(subject.self_link).to eq Yaks::Mapper::Link.new(:self, '/self')
19
- end
20
- end
21
- end
@@ -1,77 +0,0 @@
1
- require 'spec_helper'
2
-
3
- describe Yaks::Mapper::Config do
4
- subject(:config) { described_class.new }
5
-
6
- describe 'attributes' do
7
- context 'an empty config' do
8
- it 'should return an empty attributes list' do
9
- expect(config.attributes).to eq Yaks::List()
10
- end
11
- end
12
-
13
- it 'should add attributes' do
14
- expect(config.attributes(:foo, :bar, :baz).attributes)
15
- .to eq Hamster.list(:foo, :bar, :baz)
16
- end
17
-
18
- it 'should be chainable' do
19
- expect(
20
- config
21
- .attributes(:foo, :bar)
22
- .attributes(:baz)
23
- .attributes
24
- ).to eq Hamster.list(:foo, :bar, :baz)
25
- end
26
- end
27
-
28
- describe 'links' do
29
- context 'an empty config' do
30
- it 'should have an empty link list' do
31
- expect(config.links).to eq Yaks::List()
32
- end
33
- end
34
-
35
- describe 'adding a link' do
36
- let(:config) { subject.link(:self, '/foo/bar/{id}') }
37
-
38
- it 'should have it in the link list' do
39
- expect(config.links).to eq Yaks::List(Yaks::Mapper::Link.new(:self, '/foo/bar/{id}'))
40
- end
41
- end
42
-
43
- describe 'setting a profile' do
44
- let(:config) { subject.profile :post }
45
-
46
- it 'should set the profile name' do
47
- expect(config.profile).to eq :post
48
- end
49
- end
50
- end
51
-
52
- describe 'associations' do
53
- describe 'has_one' do
54
- let(:config) { subject.has_one :mother, mapper: Yaks::Mapper }
55
-
56
- it 'should have the association configured' do
57
- expect(config.associations).to eq Yaks::List(Yaks::Mapper::HasOne.new(:mother, :mother, Yaks::Mapper, Yaks::List(), {}))
58
- end
59
- end
60
-
61
- describe 'has_many' do
62
- let(:config) { subject.has_many :shoes, mapper: Yaks::Mapper }
63
-
64
- it 'should have the association configured' do
65
- expect(config.associations).to eq Yaks::List(Yaks::Mapper::HasMany.new(:shoes, :shoes, Yaks::Mapper, Yaks::List(), {}))
66
- end
67
- end
68
-
69
- context 'with an :as alternate key' do
70
- let(:config) { subject.has_many :shoes, as: :footwear, mapper: Yaks::Mapper }
71
-
72
- it 'should have the given value as its "key"' do
73
- expect(config.associations.first.key).to eq :footwear
74
- end
75
- end
76
- end
77
- end
@@ -1,16 +0,0 @@
1
- require 'spec_helper'
2
-
3
- describe Yaks::Mapper::HasOne do
4
- include_context 'shorthands'
5
-
6
- AuthorMapper = Class.new(Yaks::Mapper) { attributes :name }
7
-
8
- let(:name) { 'William S. Burroughs' }
9
- let(:mapper) { AuthorMapper }
10
- let(:has_one) { described_class.new(:author, :author, mapper, [], {}) }
11
- let(:author) { Struct.new(:name).new(name) }
12
-
13
- it 'should map to a single Resource' do
14
- expect(has_one.map_resource(author, {})).to eq resource[{name: name}, [resource_link[:profile, 'author']]]
15
- end
16
- end
@@ -1,38 +0,0 @@
1
- require 'spec_helper'
2
-
3
- describe Yaks::Mapper::Link do
4
- include_context 'shorthands'
5
-
6
- subject(:link) { described_class.new(rel, template, options) }
7
-
8
- let(:rel) { :next }
9
- let(:template) { '/foo/bar/{x}/{y}' }
10
- let(:options) { {} }
11
- its(:template_variables) { should eq ['x', 'y'] }
12
- its(:uri_template) { should eq URITemplate.new(template) }
13
-
14
- describe 'expand_with' do
15
- it 'should look up expansion values through the provided callable' do
16
- expect(link.expand_with(->(var){ var.upcase })).to eq '/foo/bar/X/Y'
17
- end
18
-
19
- context 'with expansion turned off' do
20
- let(:options) { {expand: false} }
21
-
22
- it 'should keep the template in the response' do
23
- expect(link.expand_with(->{ })).to eq '/foo/bar/{x}/{y}'
24
- end
25
-
26
- its(:expand?) { should be_false }
27
- end
28
-
29
- context 'with a URI without expansion variables' do
30
- let(:template) { '/orders' }
31
-
32
- it 'should return the link as is' do
33
- expect(link.expand_with(->{ })).to eq '/orders'
34
- end
35
- end
36
- end
37
-
38
- end
@@ -1,46 +0,0 @@
1
- require 'spec_helper'
2
-
3
- describe Yaks::Mapper::MapLinks do
4
- let(:policy) { Class.new(Yaks::DefaultPolicy) { def derive_profile_from_mapper(*); :the_profile ; end }.new }
5
- let(:mapper_class) do
6
- Class.new(Yaks::Mapper) do
7
- def get_title
8
- "The Title"
9
- end
10
- end
11
- end
12
-
13
- subject(:mapper) do
14
- mapper_class.new(Object.new, policy: policy)
15
- end
16
-
17
- context 'with a title proc' do
18
- before do
19
- mapper_class.link :the_link_rel, '/foo/bar', title: ->{ get_title }
20
- end
21
-
22
- it 'should resolve the title' do
23
- expect(mapper.map_links).to include Yaks::Resource::Link.new(:the_link_rel, '/foo/bar', title: 'The Title')
24
- end
25
- end
26
-
27
- context 'with a title string' do
28
- before do
29
- mapper_class.link :the_link_rel, '/foo/bar', title: 'fixed string'
30
- end
31
-
32
- it 'should resolve the title' do
33
- expect(mapper.map_links).to include Yaks::Resource::Link.new(:the_link_rel, '/foo/bar', title: 'fixed string')
34
- end
35
- end
36
-
37
- context 'with no title set' do
38
- before do
39
- mapper_class.link :the_link_rel, '/foo/bar'
40
- end
41
-
42
- it 'should resolve the title' do
43
- expect(mapper.map_links).to include Yaks::Resource::Link.new(:the_link_rel, '/foo/bar', {})
44
- end
45
- end
46
- end
@@ -1,65 +0,0 @@
1
- require 'spec_helper'
2
-
3
- describe Yaks::Mapper do
4
- include_context 'shorthands'
5
-
6
- let(:mapper_class) { Class.new(Yaks::Mapper) }
7
- let(:model) { Struct.new(:foo, :bar) }
8
- let(:instance) { model.new('hello', 'world') }
9
-
10
- context 'with attributes' do
11
- before do
12
- mapper_class.attributes :foo, :bar
13
- end
14
-
15
- it 'should make the configured attributes available on the instance' do
16
- expect(mapper_class.new(Object.new).attributes).to eq Yaks::List(:foo, :bar)
17
- end
18
-
19
- describe 'mapping attributes' do
20
- it 'should load them from the model' do
21
- expect(mapper_class.new(instance).map_attributes).to eq Yaks::List([:foo, 'hello'], [:bar, 'world'])
22
- end
23
- end
24
- end
25
-
26
- describe 'profile links' do
27
- before do
28
- mapper_class.profile :show
29
- end
30
-
31
- context 'with a dummy registry' do
32
- it 'should create a link with the profile name as the uri' do
33
- expect(mapper_class.new(instance).map_links).to eq Yaks::List(resource_link[:profile, 'show'])
34
- end
35
- end
36
-
37
- context 'with a registered profile' do
38
- let(:registry) { Yaks::ProfileRegistry.create { profile :show, 'http://my.api/docs/show' } }
39
-
40
- let(:mapper) { mapper_class.new(instance, profile_registry:registry) }
41
-
42
- it 'should look up and use the correct uri' do
43
- expect(mapper.map_links).to eq Yaks::List(resource_link[:profile, 'http://my.api/docs/show'])
44
- end
45
- end
46
- end
47
-
48
- describe 'links' do
49
- context 'multiple of the same rel' do
50
- before do
51
- mapper_class.class_eval do
52
- link :self, '/foo/me'
53
- link :self, '/foo/this'
54
- end
55
-
56
- it 'should map them both' do
57
- expect(mapper_class.new(instance).to_resource.links).to eql [
58
- Yaks::Resource::Link.new(:self, '/foo/me', {}),
59
- Yaks::Resource::Link.new(:self, '/foo/this', {})
60
- ]
61
- end
62
- end
63
- end
64
- end
65
- end
@@ -1,23 +0,0 @@
1
- require 'spec_helper'
2
-
3
- describe Yaks::Resource do
4
- include_context 'shorthands'
5
-
6
- let(:object) { described_class.new(attributes, links, subresources) }
7
- let(:attributes) { {} }
8
- let(:links) { [] }
9
- let(:subresources) { {} }
10
-
11
- describe '#uri' do
12
- subject { object.uri }
13
-
14
- context 'without a self link' do
15
- it { should be_nil }
16
- end
17
-
18
- context 'with a self link' do
19
- let(:links) { [ resource_link[:self, '/foo/this_is_me/7'] ] }
20
- it { should eq '/foo/this_is_me/7' }
21
- end
22
- end
23
- end