grape 0.9.0 → 0.10.0

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of grape might be problematic. Click here for more details.

Files changed (144) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +1 -66
  3. data/.rubocop_todo.yml +78 -17
  4. data/.travis.yml +7 -3
  5. data/Appraisals +7 -0
  6. data/CHANGELOG.md +24 -0
  7. data/CONTRIBUTING.md +7 -0
  8. data/Gemfile +1 -7
  9. data/Guardfile +1 -1
  10. data/README.md +560 -94
  11. data/RELEASING.md +1 -1
  12. data/Rakefile +10 -11
  13. data/UPGRADING.md +211 -3
  14. data/gemfiles/rails_3.gemfile +14 -0
  15. data/gemfiles/rails_4.gemfile +14 -0
  16. data/grape.gemspec +10 -9
  17. data/lib/backports/active_support/deep_dup.rb +49 -0
  18. data/lib/backports/active_support/duplicable.rb +88 -0
  19. data/lib/grape.rb +29 -2
  20. data/lib/grape/api.rb +59 -65
  21. data/lib/grape/dsl/api.rb +19 -0
  22. data/lib/grape/dsl/callbacks.rb +6 -4
  23. data/lib/grape/dsl/configuration.rb +49 -5
  24. data/lib/grape/dsl/helpers.rb +7 -8
  25. data/lib/grape/dsl/inside_route.rb +22 -10
  26. data/lib/grape/dsl/middleware.rb +5 -5
  27. data/lib/grape/dsl/parameters.rb +6 -2
  28. data/lib/grape/dsl/request_response.rb +23 -20
  29. data/lib/grape/dsl/routing.rb +52 -49
  30. data/lib/grape/dsl/settings.rb +110 -0
  31. data/lib/grape/dsl/validations.rb +14 -6
  32. data/lib/grape/endpoint.rb +104 -88
  33. data/lib/grape/exceptions/base.rb +2 -2
  34. data/lib/grape/exceptions/incompatible_option_values.rb +1 -1
  35. data/lib/grape/exceptions/invalid_formatter.rb +1 -1
  36. data/lib/grape/exceptions/invalid_versioner_option.rb +1 -1
  37. data/lib/grape/exceptions/invalid_with_option_for_represent.rb +1 -1
  38. data/lib/grape/exceptions/missing_mime_type.rb +1 -1
  39. data/lib/grape/exceptions/missing_option.rb +1 -1
  40. data/lib/grape/exceptions/missing_vendor_option.rb +1 -1
  41. data/lib/grape/exceptions/unknown_options.rb +1 -1
  42. data/lib/grape/exceptions/unknown_validator.rb +1 -1
  43. data/lib/grape/exceptions/validation.rb +1 -1
  44. data/lib/grape/exceptions/validation_errors.rb +2 -2
  45. data/lib/grape/formatter/serializable_hash.rb +1 -1
  46. data/lib/grape/formatter/xml.rb +1 -1
  47. data/lib/grape/locale/en.yml +2 -0
  48. data/lib/grape/middleware/auth/dsl.rb +26 -21
  49. data/lib/grape/middleware/auth/strategies.rb +1 -1
  50. data/lib/grape/middleware/auth/strategy_info.rb +0 -2
  51. data/lib/grape/middleware/base.rb +2 -2
  52. data/lib/grape/middleware/error.rb +1 -1
  53. data/lib/grape/middleware/formatter.rb +5 -5
  54. data/lib/grape/middleware/versioner.rb +1 -1
  55. data/lib/grape/middleware/versioner/header.rb +3 -3
  56. data/lib/grape/middleware/versioner/param.rb +2 -2
  57. data/lib/grape/middleware/versioner/path.rb +1 -1
  58. data/lib/grape/namespace.rb +1 -1
  59. data/lib/grape/path.rb +9 -3
  60. data/lib/grape/util/content_types.rb +16 -8
  61. data/lib/grape/util/inheritable_setting.rb +74 -0
  62. data/lib/grape/util/inheritable_values.rb +51 -0
  63. data/lib/grape/util/stackable_values.rb +52 -0
  64. data/lib/grape/util/strict_hash_configuration.rb +106 -0
  65. data/lib/grape/validations.rb +0 -220
  66. data/lib/grape/validations/attributes_iterator.rb +21 -0
  67. data/lib/grape/validations/params_scope.rb +176 -0
  68. data/lib/grape/validations/validators/all_or_none.rb +20 -0
  69. data/lib/grape/validations/validators/allow_blank.rb +30 -0
  70. data/lib/grape/validations/validators/at_least_one_of.rb +20 -0
  71. data/lib/grape/validations/validators/base.rb +37 -0
  72. data/lib/grape/validations/{coerce.rb → validators/coerce.rb} +3 -3
  73. data/lib/grape/validations/{default.rb → validators/default.rb} +1 -1
  74. data/lib/grape/validations/validators/exactly_one_of.rb +20 -0
  75. data/lib/grape/validations/validators/multiple_params_base.rb +26 -0
  76. data/lib/grape/validations/validators/mutual_exclusion.rb +25 -0
  77. data/lib/grape/validations/{presence.rb → validators/presence.rb} +2 -2
  78. data/lib/grape/validations/validators/regexp.rb +12 -0
  79. data/lib/grape/validations/validators/values.rb +26 -0
  80. data/lib/grape/version.rb +1 -1
  81. data/spec/grape/api_spec.rb +522 -343
  82. data/spec/grape/dsl/callbacks_spec.rb +4 -4
  83. data/spec/grape/dsl/configuration_spec.rb +48 -9
  84. data/spec/grape/dsl/helpers_spec.rb +6 -13
  85. data/spec/grape/dsl/inside_route_spec.rb +43 -4
  86. data/spec/grape/dsl/middleware_spec.rb +1 -10
  87. data/spec/grape/dsl/parameters_spec.rb +8 -1
  88. data/spec/grape/dsl/request_response_spec.rb +16 -22
  89. data/spec/grape/dsl/routing_spec.rb +21 -5
  90. data/spec/grape/dsl/settings_spec.rb +219 -0
  91. data/spec/grape/dsl/validations_spec.rb +8 -11
  92. data/spec/grape/endpoint_spec.rb +115 -86
  93. data/spec/grape/entity_spec.rb +33 -33
  94. data/spec/grape/exceptions/invalid_formatter_spec.rb +3 -5
  95. data/spec/grape/exceptions/invalid_versioner_option_spec.rb +4 -6
  96. data/spec/grape/exceptions/missing_mime_type_spec.rb +5 -6
  97. data/spec/grape/exceptions/missing_option_spec.rb +3 -5
  98. data/spec/grape/exceptions/unknown_options_spec.rb +3 -5
  99. data/spec/grape/exceptions/unknown_validator_spec.rb +3 -5
  100. data/spec/grape/exceptions/validation_errors_spec.rb +5 -5
  101. data/spec/grape/loading_spec.rb +44 -0
  102. data/spec/grape/middleware/auth/base_spec.rb +0 -4
  103. data/spec/grape/middleware/auth/dsl_spec.rb +2 -4
  104. data/spec/grape/middleware/auth/strategies_spec.rb +5 -6
  105. data/spec/grape/middleware/exception_spec.rb +8 -10
  106. data/spec/grape/middleware/formatter_spec.rb +13 -15
  107. data/spec/grape/middleware/versioner/accept_version_header_spec.rb +10 -10
  108. data/spec/grape/middleware/versioner/header_spec.rb +25 -25
  109. data/spec/grape/middleware/versioner/param_spec.rb +15 -17
  110. data/spec/grape/middleware/versioner/path_spec.rb +1 -2
  111. data/spec/grape/middleware/versioner_spec.rb +0 -1
  112. data/spec/grape/path_spec.rb +66 -45
  113. data/spec/grape/util/inheritable_setting_spec.rb +217 -0
  114. data/spec/grape/util/inheritable_values_spec.rb +63 -0
  115. data/spec/grape/util/stackable_values_spec.rb +115 -0
  116. data/spec/grape/util/strict_hash_configuration_spec.rb +38 -0
  117. data/spec/grape/validations/attributes_iterator_spec.rb +4 -0
  118. data/spec/grape/validations/params_scope_spec.rb +57 -0
  119. data/spec/grape/validations/validators/all_or_none_spec.rb +60 -0
  120. data/spec/grape/validations/validators/allow_blank_spec.rb +170 -0
  121. data/spec/grape/validations/{at_least_one_of_spec.rb → validators/at_least_one_of_spec.rb} +7 -3
  122. data/spec/grape/validations/{coerce_spec.rb → validators/coerce_spec.rb} +8 -11
  123. data/spec/grape/validations/{default_spec.rb → validators/default_spec.rb} +7 -9
  124. data/spec/grape/validations/{exactly_one_of_spec.rb → validators/exactly_one_of_spec.rb} +15 -11
  125. data/spec/grape/validations/{mutual_exclusion_spec.rb → validators/mutual_exclusion_spec.rb} +11 -9
  126. data/spec/grape/validations/{presence_spec.rb → validators/presence_spec.rb} +30 -30
  127. data/spec/grape/validations/{regexp_spec.rb → validators/regexp_spec.rb} +2 -4
  128. data/spec/grape/validations/{values_spec.rb → validators/values_spec.rb} +95 -23
  129. data/spec/grape/validations/{zh-CN.yml → validators/zh-CN.yml} +0 -0
  130. data/spec/grape/validations_spec.rb +335 -70
  131. data/spec/shared/versioning_examples.rb +7 -8
  132. data/spec/spec_helper.rb +2 -0
  133. data/spec/support/basic_auth_encode_helpers.rb +1 -1
  134. data/spec/support/content_type_helpers.rb +1 -1
  135. data/spec/support/versioned_helpers.rb +3 -3
  136. metadata +80 -33
  137. data/lib/grape/util/deep_merge.rb +0 -23
  138. data/lib/grape/util/hash_stack.rb +0 -120
  139. data/lib/grape/validations/at_least_one_of.rb +0 -25
  140. data/lib/grape/validations/exactly_one_of.rb +0 -26
  141. data/lib/grape/validations/mutual_exclusion.rb +0 -25
  142. data/lib/grape/validations/regexp.rb +0 -12
  143. data/lib/grape/validations/values.rb +0 -23
  144. data/spec/grape/util/hash_stack_spec.rb +0 -132
@@ -27,7 +27,7 @@ describe Grape::Middleware::Versioner::Path do
27
27
  end
28
28
  end
29
29
 
30
- [['v1', 'v2'], [:v1, :v2], [:v1, 'v2'], ['v1', :v2]].each do |versions|
30
+ [%w(v1 v2), [:v1, :v2], [:v1, 'v2'], ['v1', :v2]].each do |versions|
31
31
  context 'with specified versions as #{versions}' do
32
32
  before { @options = { versions: versions } }
33
33
 
@@ -40,5 +40,4 @@ describe Grape::Middleware::Versioner::Path do
40
40
  end
41
41
  end
42
42
  end
43
-
44
43
  end
@@ -1,7 +1,6 @@
1
1
  require 'spec_helper'
2
2
 
3
3
  describe Grape::Middleware::Versioner do
4
-
5
4
  let(:klass) { Grape::Middleware::Versioner }
6
5
 
7
6
  it 'recognizes :path' do
@@ -2,65 +2,64 @@ require 'spec_helper'
2
2
 
3
3
  module Grape
4
4
  describe Path do
5
-
6
- describe "#initialize" do
7
- it "remembers the path" do
5
+ describe '#initialize' do
6
+ it 'remembers the path' do
8
7
  path = Path.new('/:id', anything, anything)
9
8
  expect(path.raw_path).to eql('/:id')
10
9
  end
11
10
 
12
- it "remembers the namespace" do
11
+ it 'remembers the namespace' do
13
12
  path = Path.new(anything, '/users', anything)
14
13
  expect(path.namespace).to eql('/users')
15
14
  end
16
15
 
17
- it "remebers the settings" do
16
+ it 'remebers the settings' do
18
17
  path = Path.new(anything, anything, foo: 'bar')
19
18
  expect(path.settings).to eql(foo: 'bar')
20
19
  end
21
20
  end
22
21
 
23
- describe "#mount_path" do
24
- it "is nil when no mount path setting exists" do
22
+ describe '#mount_path' do
23
+ it 'is nil when no mount path setting exists' do
25
24
  path = Path.new(anything, anything, {})
26
25
  expect(path.mount_path).to be_nil
27
26
  end
28
27
 
29
- it "is nil when the mount path is nil" do
28
+ it 'is nil when the mount path is nil' do
30
29
  path = Path.new(anything, anything, mount_path: nil)
31
30
  expect(path.mount_path).to be_nil
32
31
  end
33
32
 
34
- it "splits the mount path" do
35
- path = Path.new(anything, anything, mount_path: 'foo/bar')
36
- expect(path.mount_path).to eql(['foo', 'bar'])
33
+ it 'splits the mount path' do
34
+ path = Path.new(anything, anything, mount_path: %w(foo bar))
35
+ expect(path.mount_path).to eql(%w(foo bar))
37
36
  end
38
37
  end
39
38
 
40
- describe "#root_prefix" do
41
- it "is nil when no root prefix setting exists" do
39
+ describe '#root_prefix' do
40
+ it 'is nil when no root prefix setting exists' do
42
41
  path = Path.new(anything, anything, {})
43
42
  expect(path.root_prefix).to be_nil
44
43
  end
45
44
 
46
- it "is nil when the mount path is nil" do
45
+ it 'is nil when the mount path is nil' do
47
46
  path = Path.new(anything, anything, root_prefix: nil)
48
47
  expect(path.root_prefix).to be_nil
49
48
  end
50
49
 
51
- it "splits the mount path" do
50
+ it 'splits the mount path' do
52
51
  path = Path.new(anything, anything, root_prefix: 'hello/world')
53
- expect(path.root_prefix).to eql(['hello', 'world'])
52
+ expect(path.root_prefix).to eql(%w(hello world))
54
53
  end
55
54
  end
56
55
 
57
- describe "#uses_path_versioning?" do
58
- it "is false when the version setting is nil" do
56
+ describe '#uses_path_versioning?' do
57
+ it 'is false when the version setting is nil' do
59
58
  path = Path.new(anything, anything, version: nil)
60
59
  expect(path.uses_path_versioning?).to be false
61
60
  end
62
61
 
63
- it "is false when the version option is header" do
62
+ it 'is false when the version option is header' do
64
63
  path = Path.new(
65
64
  anything,
66
65
  anything,
@@ -71,7 +70,7 @@ module Grape
71
70
  expect(path.uses_path_versioning?).to be false
72
71
  end
73
72
 
74
- it "is true when the version option is path" do
73
+ it 'is true when the version option is path' do
75
74
  path = Path.new(
76
75
  anything,
77
76
  anything,
@@ -83,70 +82,70 @@ module Grape
83
82
  end
84
83
  end
85
84
 
86
- describe "#has_namespace?" do
87
- it "is false when the namespace is nil" do
85
+ describe '#has_namespace?' do
86
+ it 'is false when the namespace is nil' do
88
87
  path = Path.new(anything, nil, anything)
89
88
  expect(path).not_to have_namespace
90
89
  end
91
90
 
92
- it "is false when the namespace starts with whitespace" do
91
+ it 'is false when the namespace starts with whitespace' do
93
92
  path = Path.new(anything, ' /foo', anything)
94
93
  expect(path).not_to have_namespace
95
94
  end
96
95
 
97
- it "is false when the namespace is the root path" do
96
+ it 'is false when the namespace is the root path' do
98
97
  path = Path.new(anything, '/', anything)
99
98
  expect(path).not_to have_namespace
100
99
  end
101
100
 
102
- it "is true otherwise" do
101
+ it 'is true otherwise' do
103
102
  path = Path.new(anything, '/world', anything)
104
103
  expect(path).to have_namespace
105
104
  end
106
105
  end
107
106
 
108
- describe "#has_path?" do
109
- it "is false when the path is nil" do
107
+ describe '#has_path?' do
108
+ it 'is false when the path is nil' do
110
109
  path = Path.new(nil, anything, anything)
111
110
  expect(path).not_to have_path
112
111
  end
113
112
 
114
- it "is false when the path starts with whitespace" do
113
+ it 'is false when the path starts with whitespace' do
115
114
  path = Path.new(' /foo', anything, anything)
116
115
  expect(path).not_to have_path
117
116
  end
118
117
 
119
- it "is false when the path is the root path" do
118
+ it 'is false when the path is the root path' do
120
119
  path = Path.new('/', anything, anything)
121
120
  expect(path).not_to have_path
122
121
  end
123
122
 
124
- it "is true otherwise" do
123
+ it 'is true otherwise' do
125
124
  path = Path.new('/hello', anything, anything)
126
125
  expect(path).to have_path
127
126
  end
128
127
  end
129
128
 
130
- describe "#path" do
131
- context "mount_path" do
132
- it "is not included when it is nil" do
129
+ describe '#path' do
130
+ context 'mount_path' do
131
+ it 'is not included when it is nil' do
133
132
  path = Path.new(nil, nil, mount_path: '/foo/bar')
134
133
  expect(path.path).to eql '/foo/bar'
135
134
  end
136
135
 
137
- it "is included when it is not nil" do
136
+ it 'is included when it is not nil' do
138
137
  path = Path.new(nil, nil, {})
139
138
  expect(path.path).to eql('/')
140
139
  end
141
140
  end
142
141
 
143
- context "root_prefix" do
144
- it "is not included when it is nil" do
142
+ context 'root_prefix' do
143
+ it 'is not included when it is nil' do
145
144
  path = Path.new(nil, nil, {})
146
145
  expect(path.path).to eql('/')
147
146
  end
148
147
 
149
- it "is included after the mount path" do
148
+ it 'is included after the mount path' do
150
149
  path = Path.new(
151
150
  nil,
152
151
  nil,
@@ -158,7 +157,7 @@ module Grape
158
157
  end
159
158
  end
160
159
 
161
- it "uses the namespace after the mount path and root prefix" do
160
+ it 'uses the namespace after the mount path and root prefix' do
162
161
  path = Path.new(
163
162
  nil,
164
163
  'namespace',
@@ -169,7 +168,7 @@ module Grape
169
168
  expect(path.path).to eql('/foo/hello/namespace')
170
169
  end
171
170
 
172
- it "uses the raw path after the namespace" do
171
+ it 'uses the raw path after the namespace' do
173
172
  path = Path.new(
174
173
  'raw_path',
175
174
  'namespace',
@@ -181,19 +180,30 @@ module Grape
181
180
  end
182
181
  end
183
182
 
184
- describe "#suffix" do
185
- context "when path versioning is used" do
183
+ describe '#suffix' do
184
+ context 'when using a specific format' do
185
+ it 'is empty' do
186
+ path = Path.new(nil, nil, {})
187
+ allow(path).to receive(:uses_specific_format?) { true }
188
+
189
+ expect(path.suffix).to eql('')
190
+ end
191
+ end
192
+
193
+ context 'when path versioning is used' do
186
194
  it "includes a '/'" do
187
195
  path = Path.new(nil, nil, {})
196
+ allow(path).to receive(:uses_specific_format?) { false }
188
197
  allow(path).to receive(:uses_path_versioning?) { true }
189
198
 
190
199
  expect(path.suffix).to eql('(/.:format)')
191
200
  end
192
201
  end
193
202
 
194
- context "when path versioning is not used" do
203
+ context 'when path versioning is not used' do
195
204
  it "does not include a '/' when the path has a namespace" do
196
205
  path = Path.new(nil, 'namespace', {})
206
+ allow(path).to receive(:uses_specific_format?) { false }
197
207
  allow(path).to receive(:uses_path_versioning?) { true }
198
208
 
199
209
  expect(path.suffix).to eql('(.:format)')
@@ -201,6 +211,7 @@ module Grape
201
211
 
202
212
  it "does not include a '/' when the path has a path" do
203
213
  path = Path.new('/path', nil, {})
214
+ allow(path).to receive(:uses_specific_format?) { false }
204
215
  allow(path).to receive(:uses_path_versioning?) { true }
205
216
 
206
217
  expect(path.suffix).to eql('(.:format)')
@@ -208,6 +219,7 @@ module Grape
208
219
 
209
220
  it "includes a '/' otherwise" do
210
221
  path = Path.new(nil, nil, {})
222
+ allow(path).to receive(:uses_specific_format?) { false }
211
223
  allow(path).to receive(:uses_path_versioning?) { true }
212
224
 
213
225
  expect(path.suffix).to eql('(/.:format)')
@@ -215,15 +227,24 @@ module Grape
215
227
  end
216
228
  end
217
229
 
218
- describe "#path_with_suffix" do
219
- it "combines the path and suffix" do
230
+ describe '#path_with_suffix' do
231
+ it 'combines the path and suffix' do
220
232
  path = Path.new(nil, nil, {})
221
233
  allow(path).to receive(:path) { '/the/path' }
222
234
  allow(path).to receive(:suffix) { 'suffix' }
223
235
 
224
236
  expect(path.path_with_suffix).to eql('/the/pathsuffix')
225
237
  end
226
- end
227
238
 
239
+ context 'when using a specific format' do
240
+ it 'does not have a suffix' do
241
+ path = Path.new(nil, nil, {})
242
+ allow(path).to receive(:path) { '/the/path' }
243
+ allow(path).to receive(:uses_specific_format?) { true }
244
+
245
+ expect(path.path_with_suffix).to eql('/the/path')
246
+ end
247
+ end
248
+ end
228
249
  end
229
250
  end
@@ -0,0 +1,217 @@
1
+ require 'spec_helper'
2
+ module Grape
3
+ module Util
4
+ describe InheritableSetting do
5
+ before :each do
6
+ InheritableSetting.reset_global!
7
+ end
8
+
9
+ let(:parent) do
10
+ Grape::Util::InheritableSetting.new.tap do |settings|
11
+ settings.global[:global_thing] = :global_foo_bar
12
+ settings.namespace[:namespace_thing] = :namespace_foo_bar
13
+ settings.namespace_inheritable[:namespace_inheritable_thing] = :namespace_inheritable_foo_bar
14
+ settings.namespace_stackable[:namespace_stackable_thing] = :namespace_stackable_foo_bar
15
+ settings.route[:route_thing] = :route_foo_bar
16
+ end
17
+ end
18
+
19
+ let(:other_parent) do
20
+ Grape::Util::InheritableSetting.new.tap do |settings|
21
+ settings.namespace[:namespace_thing] = :namespace_foo_bar_other
22
+ settings.namespace_inheritable[:namespace_inheritable_thing] = :namespace_inheritable_foo_bar_other
23
+ settings.namespace_stackable[:namespace_stackable_thing] = :namespace_stackable_foo_bar_other
24
+ settings.route[:route_thing] = :route_foo_bar_other
25
+ end
26
+ end
27
+
28
+ before :each do
29
+ subject.inherit_from parent
30
+ end
31
+
32
+ describe '#global' do
33
+ it 'sets a global value' do
34
+ subject.global[:some_thing] = :foo_bar
35
+ expect(subject.global[:some_thing]).to eq :foo_bar
36
+ subject.global[:some_thing] = :foo_bar_next
37
+ expect(subject.global[:some_thing]).to eq :foo_bar_next
38
+ end
39
+
40
+ it 'sets the global inherited values' do
41
+ expect(subject.global[:global_thing]).to eq :global_foo_bar
42
+ end
43
+
44
+ it 'overrides global values' do
45
+ subject.global[:global_thing] = :global_new_foo_bar
46
+ expect(parent.global[:global_thing]).to eq :global_new_foo_bar
47
+ end
48
+
49
+ it 'should handle different parents' do
50
+ subject.global[:global_thing] = :global_new_foo_bar
51
+
52
+ subject.inherit_from other_parent
53
+
54
+ expect(parent.global[:global_thing]).to eq :global_new_foo_bar
55
+ expect(other_parent.global[:global_thing]).to eq :global_new_foo_bar
56
+ end
57
+ end
58
+
59
+ describe '#api_class' do
60
+ it 'is specific to the class' do
61
+ subject.api_class[:some_thing] = :foo_bar
62
+ parent.api_class[:some_thing] = :some_thing
63
+
64
+ expect(subject.api_class[:some_thing]).to eq :foo_bar
65
+ expect(parent.api_class[:some_thing]).to eq :some_thing
66
+ end
67
+ end
68
+
69
+ describe '#namespace' do
70
+ it 'sets a value until the end of a namespace' do
71
+ subject.namespace[:some_thing] = :foo_bar
72
+ expect(subject.namespace[:some_thing]).to eq :foo_bar
73
+ end
74
+
75
+ it 'uses new values when a new namespace starts' do
76
+ subject.namespace[:namespace_thing] = :new_namespace_foo_bar
77
+ expect(subject.namespace[:namespace_thing]).to eq :new_namespace_foo_bar
78
+
79
+ expect(parent.namespace[:namespace_thing]).to eq :namespace_foo_bar
80
+ end
81
+ end
82
+
83
+ describe '#namespace_inheritable' do
84
+ it 'works with inheritable values' do
85
+ expect(subject.namespace_inheritable[:namespace_inheritable_thing]).to eq :namespace_inheritable_foo_bar
86
+ end
87
+
88
+ it 'should handle different parents' do
89
+ expect(subject.namespace_inheritable[:namespace_inheritable_thing]).to eq :namespace_inheritable_foo_bar
90
+
91
+ subject.inherit_from other_parent
92
+
93
+ expect(subject.namespace_inheritable[:namespace_inheritable_thing]).to eq :namespace_inheritable_foo_bar_other
94
+
95
+ subject.inherit_from parent
96
+
97
+ expect(subject.namespace_inheritable[:namespace_inheritable_thing]).to eq :namespace_inheritable_foo_bar
98
+
99
+ subject.inherit_from other_parent
100
+
101
+ subject.namespace_inheritable[:namespace_inheritable_thing] = :my_thing
102
+
103
+ expect(subject.namespace_inheritable[:namespace_inheritable_thing]).to eq :my_thing
104
+
105
+ subject.inherit_from parent
106
+
107
+ expect(subject.namespace_inheritable[:namespace_inheritable_thing]).to eq :my_thing
108
+ end
109
+ end
110
+
111
+ describe '#namespace_stackable' do
112
+ it 'works with stackable values' do
113
+ expect(subject.namespace_stackable[:namespace_stackable_thing]).to eq [:namespace_stackable_foo_bar]
114
+
115
+ subject.inherit_from other_parent
116
+
117
+ expect(subject.namespace_stackable[:namespace_stackable_thing]).to eq [:namespace_stackable_foo_bar_other]
118
+ end
119
+ end
120
+
121
+ describe '#route' do
122
+ it 'sets a value until the next route' do
123
+ subject.route[:some_thing] = :foo_bar
124
+ expect(subject.route[:some_thing]).to eq :foo_bar
125
+
126
+ subject.route_end
127
+
128
+ expect(subject.route[:some_thing]).to be_nil
129
+ end
130
+
131
+ it 'works with route values' do
132
+ expect(subject.route[:route_thing]).to eq :route_foo_bar
133
+ end
134
+ end
135
+
136
+ describe '#api_class' do
137
+ it 'is specific to the class' do
138
+ subject.api_class[:some_thing] = :foo_bar
139
+ expect(subject.api_class[:some_thing]).to eq :foo_bar
140
+ end
141
+ end
142
+
143
+ describe '#inherit_from' do
144
+ it 'notifies clones' do
145
+ new_settings = subject.point_in_time_copy
146
+ expect(new_settings).to receive(:inherit_from).with(other_parent)
147
+
148
+ subject.inherit_from other_parent
149
+ end
150
+ end
151
+
152
+ describe '#point_in_time_copy' do
153
+ let!(:cloned_obj) { subject.point_in_time_copy }
154
+
155
+ it 'resets point_in_time_copies' do
156
+ expect(cloned_obj.point_in_time_copies).to be_empty
157
+ end
158
+
159
+ it 'decouples namespace values' do
160
+ subject.namespace[:namespace_thing] = :namespace_foo_bar
161
+
162
+ cloned_obj.namespace[:namespace_thing] = :new_namespace_foo_bar
163
+ expect(subject.namespace[:namespace_thing]).to eq :namespace_foo_bar
164
+ end
165
+
166
+ it 'decouples namespace inheritable values' do
167
+ expect(cloned_obj.namespace_inheritable[:namespace_inheritable_thing]).to eq :namespace_inheritable_foo_bar
168
+
169
+ subject.namespace_inheritable[:namespace_inheritable_thing] = :my_thing
170
+ expect(subject.namespace_inheritable[:namespace_inheritable_thing]).to eq :my_thing
171
+
172
+ expect(cloned_obj.namespace_inheritable[:namespace_inheritable_thing]).to eq :namespace_inheritable_foo_bar
173
+
174
+ cloned_obj.namespace_inheritable[:namespace_inheritable_thing] = :my_cloned_thing
175
+ expect(cloned_obj.namespace_inheritable[:namespace_inheritable_thing]).to eq :my_cloned_thing
176
+ expect(subject.namespace_inheritable[:namespace_inheritable_thing]).to eq :my_thing
177
+ end
178
+
179
+ it 'decouples namespace stackable values' do
180
+ expect(cloned_obj.namespace_stackable[:namespace_stackable_thing]).to eq [:namespace_stackable_foo_bar]
181
+
182
+ subject.namespace_stackable[:namespace_stackable_thing] = :other_thing
183
+ expect(subject.namespace_stackable[:namespace_stackable_thing]).to eq [:namespace_stackable_foo_bar, :other_thing]
184
+ expect(cloned_obj.namespace_stackable[:namespace_stackable_thing]).to eq [:namespace_stackable_foo_bar]
185
+ end
186
+
187
+ it 'decouples route values' do
188
+ expect(cloned_obj.route[:route_thing]).to eq :route_foo_bar
189
+
190
+ subject.route[:route_thing] = :new_route_foo_bar
191
+ expect(cloned_obj.route[:route_thing]).to eq :route_foo_bar
192
+ end
193
+
194
+ it 'adds itself to original as clone' do
195
+ expect(subject.point_in_time_copies).to include(cloned_obj)
196
+ end
197
+ end
198
+
199
+ describe '#to_hash' do
200
+ it 'return all settings as a hash' do
201
+ subject.global[:global_thing] = :global_foo_bar
202
+ subject.namespace[:namespace_thing] = :namespace_foo_bar
203
+ subject.namespace_inheritable[:namespace_inheritable_thing] = :namespace_inheritable_foo_bar
204
+ subject.namespace_stackable[:namespace_stackable_thing] = [:namespace_stackable_foo_bar]
205
+ subject.route[:route_thing] = :route_foo_bar
206
+
207
+ expect(subject.to_hash).to include(global: { global_thing: :global_foo_bar })
208
+ expect(subject.to_hash).to include(namespace: { namespace_thing: :namespace_foo_bar })
209
+ expect(subject.to_hash).to include(namespace_inheritable: {
210
+ namespace_inheritable_thing: :namespace_inheritable_foo_bar })
211
+ expect(subject.to_hash).to include(namespace_stackable: { namespace_stackable_thing: [:namespace_stackable_foo_bar, [:namespace_stackable_foo_bar]] })
212
+ expect(subject.to_hash).to include(route: { route_thing: :route_foo_bar })
213
+ end
214
+ end
215
+ end
216
+ end
217
+ end