yaks-html 0.6.0.alpha → 0.6.0.alpha.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (107) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +2 -525
  3. data/Rakefile +1 -41
  4. data/{yaks-html/lib → lib}/yaks-html.rb +0 -0
  5. data/{yaks-html/lib → lib}/yaks/format/html.rb +0 -0
  6. data/{yaks-html/lib → lib}/yaks/format/template.html +0 -0
  7. data/{yaks-html/spec → spec}/spec_helper.rb +0 -0
  8. data/{yaks-html/yaks-html.gemspec → yaks-html.gemspec} +1 -1
  9. metadata +11 -108
  10. data/.gitignore +0 -7
  11. data/.travis.yml +0 -36
  12. data/ADDING_FORMATS.md +0 -13
  13. data/CHANGELOG.md +0 -149
  14. data/Gemfile +0 -4
  15. data/IDENTIFIERS.md +0 -113
  16. data/LICENSE +0 -7
  17. data/bench/bench.rb +0 -16
  18. data/bench/bench_1000.rb +0 -60
  19. data/notes.org +0 -72
  20. data/shaved_yak.gif +0 -0
  21. data/yaks-html/README.md +0 -3
  22. data/yaks/README.md +0 -526
  23. data/yaks/lib/yaks.rb +0 -62
  24. data/yaks/lib/yaks/breaking_changes.rb +0 -49
  25. data/yaks/lib/yaks/collection_mapper.rb +0 -52
  26. data/yaks/lib/yaks/collection_resource.rb +0 -73
  27. data/yaks/lib/yaks/config.rb +0 -65
  28. data/yaks/lib/yaks/config/dsl.rb +0 -165
  29. data/yaks/lib/yaks/default_policy.rb +0 -100
  30. data/yaks/lib/yaks/format.rb +0 -87
  31. data/yaks/lib/yaks/format/collection_json.rb +0 -42
  32. data/yaks/lib/yaks/format/hal.rb +0 -82
  33. data/yaks/lib/yaks/format/json_api.rb +0 -86
  34. data/yaks/lib/yaks/fp.rb +0 -26
  35. data/yaks/lib/yaks/fp/callable.rb +0 -9
  36. data/yaks/lib/yaks/fp/hash_updatable.rb +0 -19
  37. data/yaks/lib/yaks/fp/updatable.rb +0 -17
  38. data/yaks/lib/yaks/mapper.rb +0 -75
  39. data/yaks/lib/yaks/mapper/association.rb +0 -43
  40. data/yaks/lib/yaks/mapper/association_mapper.rb +0 -42
  41. data/yaks/lib/yaks/mapper/attribute.rb +0 -17
  42. data/yaks/lib/yaks/mapper/class_methods.rb +0 -37
  43. data/yaks/lib/yaks/mapper/config.rb +0 -44
  44. data/yaks/lib/yaks/mapper/has_many.rb +0 -29
  45. data/yaks/lib/yaks/mapper/has_one.rb +0 -15
  46. data/yaks/lib/yaks/mapper/link.rb +0 -91
  47. data/yaks/lib/yaks/null_resource.rb +0 -40
  48. data/yaks/lib/yaks/primitivize.rb +0 -45
  49. data/yaks/lib/yaks/resource.rb +0 -51
  50. data/yaks/lib/yaks/resource/link.rb +0 -21
  51. data/yaks/lib/yaks/runner.rb +0 -101
  52. data/yaks/lib/yaks/util.rb +0 -56
  53. data/yaks/lib/yaks/version.rb +0 -3
  54. data/yaks/spec/acceptance/acceptance_spec.rb +0 -48
  55. data/yaks/spec/acceptance/json_shared_examples.rb +0 -8
  56. data/yaks/spec/acceptance/models.rb +0 -48
  57. data/yaks/spec/fixture_helpers.rb +0 -14
  58. data/yaks/spec/integration/map_to_resource_spec.rb +0 -28
  59. data/yaks/spec/json/confucius.collection.json +0 -28
  60. data/yaks/spec/json/confucius.hal.json +0 -59
  61. data/yaks/spec/json/confucius.json_api.json +0 -51
  62. data/yaks/spec/json/john.hal.json +0 -29
  63. data/yaks/spec/json/plant_collection.collection.json +0 -32
  64. data/yaks/spec/json/plant_collection.hal.json +0 -34
  65. data/yaks/spec/json/youtypeitwepostit.collection.json +0 -45
  66. data/yaks/spec/spec_helper.rb +0 -30
  67. data/yaks/spec/support/classes_for_policy_testing.rb +0 -36
  68. data/yaks/spec/support/deep_eql.rb +0 -123
  69. data/yaks/spec/support/fixtures.rb +0 -6
  70. data/yaks/spec/support/friends_mapper.rb +0 -29
  71. data/yaks/spec/support/models.rb +0 -23
  72. data/yaks/spec/support/pet_mapper.rb +0 -3
  73. data/yaks/spec/support/pet_peeve_mapper.rb +0 -3
  74. data/yaks/spec/support/shared_contexts.rb +0 -57
  75. data/yaks/spec/support/youtypeit_models_mappers.rb +0 -20
  76. data/yaks/spec/unit/yaks/collection_mapper_spec.rb +0 -165
  77. data/yaks/spec/unit/yaks/collection_resource_spec.rb +0 -77
  78. data/yaks/spec/unit/yaks/config/dsl_spec.rb +0 -87
  79. data/yaks/spec/unit/yaks/config_spec.rb +0 -74
  80. data/yaks/spec/unit/yaks/default_policy/derive_mapper_from_object_spec.rb +0 -80
  81. data/yaks/spec/unit/yaks/default_policy_spec.rb +0 -70
  82. data/yaks/spec/unit/yaks/format/collection_json_spec.rb +0 -41
  83. data/yaks/spec/unit/yaks/format/hal_spec.rb +0 -44
  84. data/yaks/spec/unit/yaks/format/json_api_spec.rb +0 -42
  85. data/yaks/spec/unit/yaks/format_spec.rb +0 -37
  86. data/yaks/spec/unit/yaks/fp/callable_spec.rb +0 -13
  87. data/yaks/spec/unit/yaks/fp/hash_updatable_spec.rb +0 -22
  88. data/yaks/spec/unit/yaks/fp/updatable_spec.rb +0 -22
  89. data/yaks/spec/unit/yaks/fp_spec.rb +0 -31
  90. data/yaks/spec/unit/yaks/mapper/association_mapper_spec.rb +0 -60
  91. data/yaks/spec/unit/yaks/mapper/association_spec.rb +0 -135
  92. data/yaks/spec/unit/yaks/mapper/attribute_spec.rb +0 -20
  93. data/yaks/spec/unit/yaks/mapper/class_methods_spec.rb +0 -67
  94. data/yaks/spec/unit/yaks/mapper/config_spec.rb +0 -166
  95. data/yaks/spec/unit/yaks/mapper/has_many_spec.rb +0 -89
  96. data/yaks/spec/unit/yaks/mapper/has_one_spec.rb +0 -51
  97. data/yaks/spec/unit/yaks/mapper/link_spec.rb +0 -196
  98. data/yaks/spec/unit/yaks/mapper_spec.rb +0 -303
  99. data/yaks/spec/unit/yaks/null_resource_spec.rb +0 -32
  100. data/yaks/spec/unit/yaks/primitivize_spec.rb +0 -77
  101. data/yaks/spec/unit/yaks/resource/link_spec.rb +0 -20
  102. data/yaks/spec/unit/yaks/resource_spec.rb +0 -108
  103. data/yaks/spec/unit/yaks/runner_spec.rb +0 -260
  104. data/yaks/spec/unit/yaks/util_spec.rb +0 -49
  105. data/yaks/spec/yaml/confucius.yaml +0 -28
  106. data/yaks/spec/yaml/youtypeitwepostit.yaml +0 -9
  107. data/yaks/yaks.gemspec +0 -41
@@ -1,6 +0,0 @@
1
- shared_context 'fixtures' do
2
- let(:john) { Friend.new(id: 1, name: 'john', pets: [boingboing, wassup], pet_peeve: regexps) }
3
- let(:boingboing) { Pet.new(id: 2, name: 'boingboing', species: 'dog') }
4
- let(:wassup) { Pet.new(id: 3, name: 'wassup', species: 'cat') }
5
- let(:regexps) { PetPeeve.new(id: 4, type: 'parsing with regexps') }
6
- end
@@ -1,29 +0,0 @@
1
- class FriendMapper < Yaks::Mapper
2
- attributes :id, :name
3
-
4
- link :copyright, '/api/copyright/{year}'
5
-
6
- def year
7
- 2024
8
- end
9
-
10
- has_one :pet_peeve, mapper: PetPeeveMapper
11
- has_many :pets, mapper: PetMapper
12
-
13
- # has_one :production_company, # retrieve as `show.production_company`
14
- # profile: :company, # use the company profile link from the registry, e.g. 'http://foo.api/profiles/company'
15
- # as: :producer, # serialize as {"producers" => []} in JSON-API or [{class: ["producer"]}] in Siren
16
- # embed: :link, # don't embed the whole data, link to it, could also be embed: :resource
17
- # mapper: CompanyMapper, # use this to find the resource URL, or to map the embedded resource
18
- # rel: :show_production_company # find the relation in the relation registry, e.g. http://foo.apo/rels/show_production_company
19
-
20
- # # Full derived defaults
21
- # has_one :production_company
22
- # # profile: :production_company, # same as the 'name'
23
- # # as: :production_company, # same as the 'name'
24
- # # embed: :links # depends on what is configured as default
25
- # # mapper: CompanyMapper # found by matching the profile
26
- # # rel: :show_production_company # "#{context.profile_name}_#{relation.profile_name}"
27
-
28
- # # has_many :pets
29
- end
@@ -1,23 +0,0 @@
1
- class Pet
2
- include Virtus.model
3
-
4
- attribute :id, Integer
5
- attribute :name, String
6
- attribute :species, String
7
- end
8
-
9
- class PetPeeve
10
- include Virtus.model
11
-
12
- attribute :id, Integer
13
- attribute :type, String
14
- end
15
-
16
- class Friend
17
- include Virtus.model
18
-
19
- attribute :id, Integer
20
- attribute :name, String
21
- attribute :pets, Array[Pet]
22
- attribute :pet_peeve, PetPeeve
23
- end
@@ -1,3 +0,0 @@
1
- class PetMapper < Yaks::Mapper
2
- attributes :id, :name, :species
3
- end
@@ -1,3 +0,0 @@
1
- class PetPeeveMapper < Yaks::Mapper
2
- attributes :id, :type
3
- end
@@ -1,57 +0,0 @@
1
- RSpec.shared_context 'collection resource' do
2
- let(:resource) do
3
- Yaks::CollectionResource.new(
4
- links: links,
5
- members: members,
6
- collection_rel: 'http://api.example.com/rels/plants'
7
- )
8
- end
9
- let(:links) { [] }
10
- let(:members) { [] }
11
- end
12
-
13
- RSpec.shared_context 'yaks context' do
14
- let(:policy) { Yaks::DefaultPolicy.new }
15
- let(:rack_env) { {} }
16
- let(:mapper_stack) { [] }
17
- let(:yaks_context) { { policy: policy, env: rack_env, mapper_stack: mapper_stack } }
18
- end
19
-
20
- RSpec.shared_context 'plant collection resource' do
21
- include_context 'collection resource'
22
-
23
- let(:links) { [ plants_self_link, plants_profile_link ] }
24
- let(:members) { [ plain_grass, oak, passiflora ] }
25
-
26
- [
27
- [ :plant , :profile , 'http://api.example.com/doc/plant' ],
28
- [ :plants , :profile , 'http://api.example.com/doc/plant_collection' ],
29
- [ :plants , :self , 'http://api.example.com/plants' ],
30
- [ :plain_grass , :self , 'http://api.example.com/plants/7/plain_grass' ],
31
- [ :oak , :self , 'http://api.example.com/plants/15/oak' ],
32
- [ :passiflora , :self , 'http://api.example.com/plants/33/passiflora' ],
33
- ].each do |name, type, uri|
34
- let(:"#{name}_#{type}_link") { Yaks::Resource::Link.new(type, uri, {}) }
35
- end
36
-
37
- let(:plain_grass) do
38
- Yaks::Resource.new(
39
- attributes: {name: "Plain grass", type: "grass"},
40
- links: [plain_grass_self_link, plant_profile_link]
41
- )
42
- end
43
-
44
- let(:oak) do
45
- Yaks::Resource.new(
46
- attributes: {name: "Oak", type: "tree"},
47
- links: [oak_self_link, plant_profile_link],
48
- )
49
- end
50
-
51
- let(:passiflora) do
52
- Yaks::Resource.new(
53
- attributes: {name: "Passiflora", type: "flower"},
54
- links: [passiflora_self_link, plant_profile_link],
55
- )
56
- end
57
- end
@@ -1,20 +0,0 @@
1
- module Youtypeitwepostit
2
- class Message
3
- include Virtus.model
4
-
5
- attribute :id, Integer
6
- attribute :text, String
7
- attribute :date_posted, String
8
- end
9
-
10
- class MessageMapper < Yaks::Mapper
11
- link :self, 'http://www.youtypeitwepostit.com/api/{id}'
12
- link :profile, 'http://www.youtypeitwepostit.com/profiles/message'
13
-
14
- attributes :text, :date_posted
15
- end
16
-
17
- class CollectionMapper < Yaks::CollectionMapper
18
- link :self, 'http://www.youtypeitwepostit.com/api/'
19
- end
20
- end
@@ -1,165 +0,0 @@
1
- require 'spec_helper'
2
-
3
- RSpec.describe Yaks::CollectionMapper do
4
- include_context 'fixtures'
5
-
6
- subject(:mapper) { mapper_class.new(context) }
7
- let(:mapper_class) { described_class }
8
-
9
- let(:context) {
10
- { item_mapper: item_mapper,
11
- policy: policy,
12
- env: {},
13
- mapper_stack: [] }
14
- }
15
-
16
- let(:collection) { [] }
17
- let(:item_mapper) { Class.new(Yaks::Mapper) { type 'the_type' } }
18
- let(:policy) { Yaks::DefaultPolicy.new }
19
-
20
- it 'should map the collection' do
21
- expect(mapper.call(collection)).to eql Yaks::CollectionResource.new(
22
- type: 'the_type',
23
- links: [],
24
- attributes: {},
25
- members: [],
26
- collection_rel: 'rel:the_types'
27
- )
28
- end
29
-
30
- context 'with members' do
31
- let(:collection) { [boingboing, wassup]}
32
- let(:item_mapper) { PetMapper }
33
-
34
- it 'should map the members' do
35
- stub(policy).derive_mapper_from_object(any_args) do
36
- raise ":item_mapper was specified explicitly, should not be derived from object"
37
- end
38
-
39
- expect(mapper.call(collection)).to eql Yaks::CollectionResource.new(
40
- type: 'pet',
41
- links: [],
42
- attributes: {},
43
- members: [
44
- Yaks::Resource.new(type: 'pet', attributes: {:id => 2, :species => "dog", :name => "boingboing"}),
45
- Yaks::Resource.new(type: 'pet', attributes: {:id => 3, :species => "cat", :name => "wassup"})
46
- ],
47
- collection_rel: 'rel:pets'
48
- )
49
- end
50
- end
51
-
52
- context 'without an item_mapper in the context' do
53
- let(:context) {
54
- {
55
- policy: policy,
56
- env: {},
57
- mapper_stack: []
58
- }
59
- }
60
- let(:collection) { [boingboing, wassup]}
61
-
62
- it 'should infer the item mapper' do
63
- expect(mapper.call(collection)).to eql Yaks::CollectionResource.new(
64
- type: 'pet',
65
- links: [],
66
- attributes: {},
67
- members: [
68
- Yaks::Resource.new(type: 'pet', attributes: {:id => 2, :species => "dog", :name => "boingboing"}),
69
- Yaks::Resource.new(type: 'pet', attributes: {:id => 3, :species => "cat", :name => "wassup"})
70
- ],
71
- collection_rel: 'rel:pets'
72
- )
73
- end
74
- end
75
-
76
- context 'with collection attributes' do
77
- subject(:mapper) {
78
- Class.new(Yaks::CollectionMapper) do
79
- attributes :foo, :bar
80
- end.new(context)
81
- }
82
-
83
- let(:collection) {
84
- Class.new(SimpleDelegator) do
85
- def foo ; 123 ; end
86
- def bar ; 'pi la~~~' ; end
87
- end.new([])
88
- }
89
-
90
- it 'should map the attributes' do
91
- expect(mapper.call(collection)).to eql Yaks::CollectionResource.new(
92
- type: 'the_type',
93
- links: [],
94
- attributes: { foo: 123, bar: 'pi la~~~' },
95
- members: [],
96
- collection_rel: 'rel:the_types'
97
- )
98
- end
99
- end
100
-
101
- context 'with collection links' do
102
- subject(:mapper) {
103
- Class.new(Yaks::CollectionMapper) do
104
- link :self, 'http://api.example.com/orders'
105
- end.new(context)
106
- }
107
-
108
- it 'should map the links' do
109
- expect(mapper.call(collection)).to eql Yaks::CollectionResource.new(
110
- type: 'the_type',
111
- links: [ Yaks::Resource::Link.new(:self, 'http://api.example.com/orders', {}) ],
112
- attributes: { },
113
- members: [],
114
- collection_rel: 'rel:the_types'
115
- )
116
- end
117
- end
118
-
119
- describe 'overriding #collection' do
120
- let(:mapper_class) do
121
- Class.new(described_class) do
122
- type 'pet'
123
-
124
- def collection
125
- super.drop(1)
126
- end
127
- end
128
- end
129
-
130
- let(:collection) { [boingboing, wassup]}
131
- let(:item_mapper) { PetMapper }
132
-
133
- it 'should use the redefined collection method' do
134
- expect(mapper.call(collection)).to eql Yaks::CollectionResource.new(
135
- type: 'pet',
136
- links: [],
137
- attributes: {},
138
- members: [
139
- Yaks::Resource.new(type: 'pet', attributes: {:id => 3, :species => "cat", :name => "wassup"})
140
- ],
141
- collection_rel: 'rel:pets'
142
- )
143
- end
144
- end
145
-
146
- context 'with an empty collection' do
147
-
148
- context 'without an item_mapper specified' do
149
- let(:context) { Yaks::Util.slice_hash(super(), :policy, :env) }
150
-
151
- it 'should use a rel of "collection"' do
152
- expect(mapper.([]).collection_rel).to eq 'collection'
153
- end
154
- end
155
-
156
- context 'with an item_mapper specified' do
157
- let(:context) { Yaks::Util.slice_hash(super(), :policy, :env, :item_mapper) }
158
-
159
- it 'should derive the collection rel from the item mapper' do
160
- expect(mapper.([]).collection_rel).to eq 'rel:the_types'
161
- end
162
- end
163
-
164
- end
165
- end
@@ -1,77 +0,0 @@
1
- require 'spec_helper'
2
-
3
- RSpec.describe Yaks::CollectionResource do
4
- subject(:collection) { described_class.new(init_opts) }
5
- let(:init_opts) { {} }
6
-
7
- its(:collection?) { should be true }
8
- its(:null_resource?) { should be false }
9
-
10
- context 'with nothing passed in the contstructor' do
11
- its(:type) { should be_nil }
12
- its(:links) { should eql [] }
13
- its(:attributes) { should eql({}) }
14
- its(:members) { should eql [] }
15
- its(:subresources) { should eql({}) }
16
- its(:collection_rel) { should eql('members') }
17
- end
18
-
19
- context 'with a full constructor' do
20
- let(:init_opts) {
21
- {
22
- type: 'order',
23
- links: [
24
- Yaks::Resource::Link.new('http://rels/summary', 'http://order/10/summary', {}),
25
- Yaks::Resource::Link.new(:profile, 'http://rels/collection', {})
26
- ],
27
- attributes: { total: 10.00 },
28
- members: [
29
- Yaks::Resource.new(
30
- type: 'order',
31
- links: [Yaks::Resource::Link.new(:self, 'http://order/10', {})],
32
- attributes: { customer: 'John Doe', price: 10.00 }
33
- )
34
- ],
35
- collection_rel: 'http://api.example.org/rels/orders'
36
- }
37
- }
38
-
39
- its(:type) { should eql 'order' }
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', {})
43
- ]
44
- }
45
- its(:attributes) { should eql( total: 10.00 ) }
46
- its(:members) { should eql [
47
- Yaks::Resource.new(
48
- type: 'order',
49
- links: [Yaks::Resource::Link.new(:self, 'http://order/10', {})],
50
- attributes: { customer: 'John Doe', price: 10.00 }
51
- )
52
- ]
53
- }
54
- its(:collection_rel) { should eq 'http://api.example.org/rels/orders'}
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
- }
75
-
76
- end
77
- end
@@ -1,87 +0,0 @@
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]).to 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 '#json_serializer' do
65
- configure { json_serializer { |i| "foo #{i}" } }
66
- specify { expect(yaks_config.serializers[:json].call(7)).to eql 'foo 7' }
67
- end
68
-
69
- describe '#mapper_namespace' do
70
- configure { mapper_namespace RSpec }
71
- specify { expect(yaks_config.policy_options[:namespace]).to eql RSpec }
72
- end
73
-
74
- describe '#map_to_primitive' do
75
- Foo = Class.new do
76
- attr_reader :foo
77
-
78
- def initialize(foo)
79
- @foo = foo
80
- end
81
- end
82
-
83
- configure { map_to_primitive(Foo) {|c| c.foo } }
84
- specify { expect(yaks_config.primitivize.call({:abc => Foo.new('hello')})).to eql 'abc' => 'hello' }
85
- end
86
-
87
- end