tram-validators 0.0.1

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.
@@ -0,0 +1,14 @@
1
+ # Checks that a model instance can be found by id
2
+ #
3
+ # @example Checks that AdminPolicy.new(user).valid?
4
+ # validates :user_key, reference: { model: User, find_by: :key }
5
+ #
6
+ class ReferenceValidator < ActiveModel::EachValidator
7
+ def validate_each(record, attribute, value)
8
+ model = options.fetch(:model) { raise "You should define :model option" }
9
+ key = options.fetch(:find_by, :id)
10
+
11
+ return if model.find_by(key => value)
12
+ record.errors.add attribute, :not_found
13
+ end
14
+ end
@@ -0,0 +1,37 @@
1
+ # Compares size of array to given value or another attribute
2
+ #
3
+ # @example
4
+ # validates :names, size: { less_than: 6 }
5
+ # validates :values, size: { equal_to: :names }
6
+ #
7
+ class SizeValidator < ActiveModel::EachValidator
8
+ def validate_each(record, attribute, value)
9
+ size = value.size if value.is_a? Array
10
+ Tram::Validators::CONDITIONS.each do |key, block|
11
+ check(key, record, attribute, size, &block)
12
+ end
13
+ end
14
+
15
+ private
16
+
17
+ def check(condition, record, attribute, size)
18
+ return unless options.key? condition
19
+
20
+ limit = extract_limit(record, condition)
21
+ return if size && limit && yield(size, limit.to_i)
22
+
23
+ record.errors.add attribute, error_key(condition), size: size, limit: limit
24
+ end
25
+
26
+ def extract_limit(record, condition)
27
+ value = options[condition]
28
+ return value.to_s.to_i if value.to_s.to_i == value
29
+ value.to_s.split(".").inject(record) { |obj, meth| obj&.send(meth) }
30
+ end
31
+
32
+ def error_key(condition)
33
+ value = options[condition]
34
+ name = value.to_s.underscore.gsub(".", "_") unless value.to_s.to_i == value
35
+ ["size", condition, name].compact.join("_").to_sym
36
+ end
37
+ end
@@ -0,0 +1,27 @@
1
+ # Checks that value of some attribute is valid per se
2
+ # Otherwise populates the record with the attribute's validation errors
3
+ #
4
+ # With option `original_keys: true` it copies value's errors to the record
5
+ # under their original keys, as if the [#record] had attributes of the [#value].
6
+ # Otherwise the errors are copied under the [#attribute] key.
7
+ #
8
+ # This is necessary for validation of the form models, as well as
9
+ # other decorated objects.
10
+ #
11
+ # @example Checks that user.valid? returns true
12
+ # validates :user, validity: { nested_keys: true }
13
+ #
14
+ class ValidityValidator < ActiveModel::EachValidator
15
+ def validate_each(record, attribute, value)
16
+ if !value.respond_to? :invalid?
17
+ record.errors.add attribute, :invalidable, record: record,
18
+ attribute: attribute,
19
+ value: value
20
+ elsif value.invalid?
21
+ value.errors.messages.each do |key, messages|
22
+ error_key = Tram::Validators.error_key(key, attribute, options)
23
+ messages.each { |message| record.errors.add error_key, message }
24
+ end
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,17 @@
1
+ require "pry"
2
+ require "tram-validators"
3
+
4
+ require_relative "support/invalid_with_error"
5
+
6
+ RSpec.configure do |config|
7
+ config.order = :random
8
+ config.filter_run focus: true
9
+ config.run_all_when_everything_filtered = true
10
+
11
+ # Prepare the Test namespace for constants defined in specs
12
+ config.around(:each) do |example|
13
+ Test = Class.new(Module)
14
+ example.run
15
+ Object.send :remove_const, :Test
16
+ end
17
+ end
@@ -0,0 +1,10 @@
1
+ RSpec::Matchers.define :be_invalid_with_error do |key, name = nil|
2
+ match do |object|
3
+ expect(object).not_to be_valid
4
+
5
+ error = object.errors.messages[key.to_sym].to_a.first
6
+ satisfy_condition = name ? match(/\.#{name}\z/) : be_present
7
+
8
+ expect(error).to satisfy_condition
9
+ end
10
+ end
@@ -0,0 +1,131 @@
1
+ RSpec.describe ConsistencyValidator do
2
+ before do
3
+ Test::Subject = Struct.new(:foo, :bar) do
4
+ include ActiveModel::Validations
5
+ end
6
+
7
+ Test::Subject.validates :foo, consistency: options
8
+ end
9
+
10
+ subject { Test::Subject.new(foo, double(baz: 2)) }
11
+
12
+ context "equal_to attribute" do
13
+ let(:options) { { equal_to: "bar.baz" } }
14
+
15
+ context "when attribute equals to limit" do
16
+ let(:foo) { 2 }
17
+ it { is_expected.to be_valid }
18
+ end
19
+
20
+ context "when attribute is less than limit" do
21
+ let(:foo) { 1 }
22
+ it { is_expected.to be_invalid_with_error :foo, :equal_to_bar_baz }
23
+ end
24
+
25
+ context "when attribute is greater than limit" do
26
+ let(:foo) { 3 }
27
+ it { is_expected.to be_invalid_with_error :foo, :equal_to_bar_baz }
28
+ end
29
+ end
30
+
31
+ context "other_than attribute" do
32
+ let(:options) { { other_than: "bar.baz" } }
33
+
34
+ context "when attribute equals to limit" do
35
+ let(:foo) { 2 }
36
+ it { is_expected.to be_invalid_with_error :foo, :other_than_bar_baz }
37
+ end
38
+
39
+ context "when attribute is less than limit" do
40
+ let(:foo) { 1 }
41
+ it { is_expected.to be_valid }
42
+ end
43
+
44
+ context "when attribute is greater than limit" do
45
+ let(:foo) { 3 }
46
+ it { is_expected.to be_valid }
47
+ end
48
+ end
49
+
50
+ context "greater_than attribute" do
51
+ let(:options) { { greater_than: "bar.baz" } }
52
+
53
+ context "when attribute equals to limit" do
54
+ let(:foo) { 2 }
55
+ it { is_expected.to be_invalid_with_error :foo, :greater_than_bar_baz }
56
+ end
57
+
58
+ context "when attribute is less than limit" do
59
+ let(:foo) { 1 }
60
+ it { is_expected.to be_invalid_with_error :foo, :greater_than_bar_baz }
61
+ end
62
+
63
+ context "when attribute is greater than limit" do
64
+ let(:foo) { 3 }
65
+ it { is_expected.to be_valid }
66
+ end
67
+ end
68
+
69
+ context "greater_than_or_equal_to attribute" do
70
+ let(:options) { { greater_than_or_equal_to: "bar.baz" } }
71
+
72
+ context "when attribute equals to limit" do
73
+ let(:foo) { 2 }
74
+ it { is_expected.to be_valid }
75
+ end
76
+
77
+ context "when attribute is less than limit" do
78
+ let(:foo) { 1 }
79
+ it do
80
+ is_expected.to be_invalid_with_error \
81
+ :foo, :greater_than_or_equal_to_bar_baz
82
+ end
83
+ end
84
+
85
+ context "when attribute is greater than limit" do
86
+ let(:foo) { 3 }
87
+ it { is_expected.to be_valid }
88
+ end
89
+ end
90
+
91
+ context "less_than attribute" do
92
+ let(:options) { { less_than: "bar.baz" } }
93
+
94
+ context "when attribute equals to limit" do
95
+ let(:foo) { 2 }
96
+ it { is_expected.to be_invalid_with_error :foo, :less_than_bar_baz }
97
+ end
98
+
99
+ context "when attribute is less than limit" do
100
+ let(:foo) { 1 }
101
+ it { is_expected.to be_valid }
102
+ end
103
+
104
+ context "when attribute is greater than limit" do
105
+ let(:foo) { 3 }
106
+ it { is_expected.to be_invalid_with_error :foo, :less_than_bar_baz }
107
+ end
108
+ end
109
+
110
+ context "less_than_or_equal_to attribute" do
111
+ let(:options) { { less_than_or_equal_to: "bar.baz" } }
112
+
113
+ context "when attribute equals to limit" do
114
+ let(:foo) { 2 }
115
+ it { is_expected.to be_valid }
116
+ end
117
+
118
+ context "when attribute is less than limit" do
119
+ let(:foo) { 1 }
120
+ it { is_expected.to be_valid }
121
+ end
122
+
123
+ context "when attribute is greater than limit" do
124
+ let(:foo) { 3 }
125
+ it do
126
+ is_expected.to be_invalid_with_error \
127
+ :foo, :less_than_or_equal_to_bar_baz
128
+ end
129
+ end
130
+ end
131
+ end
@@ -0,0 +1,58 @@
1
+ RSpec.describe ContractValidator do
2
+ before do
3
+ class Test::Contract < SimpleDelegator
4
+ include ActiveModel::Validations
5
+ validates :bar, presence: true
6
+ end
7
+
8
+ Test::Subject = Struct.new(:foo) do
9
+ include ActiveModel::Validations
10
+ end
11
+
12
+ Test::Subject.validates :foo, contract: { policy: Test::Contract, **opts }
13
+ end
14
+
15
+ subject { Test::Subject.new(double(bar: value)) }
16
+
17
+ context "without key option" do
18
+ let(:opts) { {} }
19
+
20
+ context "when value satisfies contract" do
21
+ let(:value) { 1 }
22
+ it { is_expected.to be_valid }
23
+ end
24
+
25
+ context "when value breaks contract" do
26
+ let(:value) { nil }
27
+ it { is_expected.to be_invalid_with_error :foo }
28
+ end
29
+ end
30
+
31
+ context "with original_keys option" do
32
+ let(:opts) { { original_keys: true } }
33
+
34
+ context "when value satisfies contract" do
35
+ let(:value) { 1 }
36
+ it { is_expected.to be_valid }
37
+ end
38
+
39
+ context "when value breaks contract" do
40
+ let(:value) { nil }
41
+ it { is_expected.to be_invalid_with_error :bar }
42
+ end
43
+ end
44
+
45
+ context "with nested_keys option" do
46
+ let(:opts) { { nested_keys: true } }
47
+
48
+ context "when value satisfies contract" do
49
+ let(:value) { 1 }
50
+ it { is_expected.to be_valid }
51
+ end
52
+
53
+ context "when value breaks contract" do
54
+ let(:value) { nil }
55
+ it { is_expected.to be_invalid_with_error "foo[bar]" }
56
+ end
57
+ end
58
+ end
@@ -0,0 +1,35 @@
1
+ RSpec.describe EachValidator do
2
+ before do
3
+ Test::Subject = Struct.new(:list) do
4
+ include ActiveModel::Validations
5
+ validates :list, each: { presence: true }
6
+ end
7
+ end
8
+
9
+ subject { Test::Subject.new(list) }
10
+
11
+ context "when all elements of array satisfy validation rule" do
12
+ let(:list) { %i(foo bar baz) }
13
+ it { is_expected.to be_valid }
14
+ end
15
+
16
+ context "when some element of array breaks validation rule" do
17
+ let(:list) { [:foo, :bar, nil] }
18
+ it { is_expected.to be_invalid_with_error "list[2]" }
19
+ end
20
+
21
+ context "when value is an empty array" do
22
+ let(:list) { [] }
23
+ it { is_expected.to be_valid }
24
+ end
25
+
26
+ context "when value is nil" do
27
+ let(:list) { :foo }
28
+ it { is_expected.to be_valid }
29
+ end
30
+
31
+ context "when value is neiter nil nor an array" do
32
+ let(:list) { :foo }
33
+ it { is_expected.to be_valid }
34
+ end
35
+ end
@@ -0,0 +1,27 @@
1
+ RSpec.describe OutcomeValidator do
2
+ before do
3
+ Test::Subject = Struct.new(:foo, :bar) do
4
+ include ActiveModel::Validations
5
+ validates :foo, outcome: { value: "bar.baz", presence: true }
6
+ end
7
+ end
8
+
9
+ subject { Test::Subject.new(1, bar) }
10
+
11
+ context "when outcome is valid" do
12
+ let(:bar) { double baz: 1 }
13
+ it { is_expected.to be_valid }
14
+ end
15
+
16
+ context "when outcome is invalid" do
17
+ let(:bar) { double baz: nil }
18
+ it { is_expected.to be_invalid_with_error :foo, :"bar_baz_presence" }
19
+ end
20
+
21
+ context "when outcome produces nil inside chain" do
22
+ let(:bar) { nil }
23
+ it "uses nil outcome" do
24
+ expect(subject).to be_invalid_with_error :foo, :"bar_baz_presence"
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,347 @@
1
+ RSpec.describe SizeValidator do
2
+ before do
3
+ Test::Subject = Struct.new(:foo, :bar, :baz) do
4
+ include ActiveModel::Validations
5
+ end
6
+ end
7
+
8
+ let(:foo) { %w(Color Size) }
9
+ let(:bar) { double baz: 2 }
10
+ let(:baz) { double qux: %w(Green XXXL) }
11
+
12
+ subject { Test::Subject.new(foo, bar, baz) }
13
+
14
+ context "equal_to number" do
15
+ before { Test::Subject.validates :foo, size: { equal_to: 2 } }
16
+
17
+ context "when attribute has size equal to limit" do
18
+ let(:foo) { %w(Color Size) }
19
+ it { is_expected.to be_valid }
20
+ end
21
+
22
+ context "when attribute has size less than limit" do
23
+ let(:foo) { %w(Color) }
24
+ it { is_expected.to be_invalid_with_error :foo, :size_equal_to }
25
+ end
26
+
27
+ context "when attribute has size greater than limit" do
28
+ let(:foo) { %w(Color Size Style) }
29
+ it { is_expected.to be_invalid_with_error :foo, :size_equal_to }
30
+ end
31
+
32
+ context "when attribute is not an array" do
33
+ let(:foo) { 1 }
34
+ it { is_expected.to be_invalid_with_error :foo, :size_equal_to }
35
+ end
36
+ end
37
+
38
+ context "other_than number" do
39
+ before { Test::Subject.validates :foo, size: { other_than: 2 } }
40
+
41
+ context "when attribute has size equal to limit" do
42
+ let(:foo) { %w(Color Size) }
43
+ it { is_expected.to be_invalid_with_error :foo, :size_other_than }
44
+ end
45
+
46
+ context "when attribute has size less than limit" do
47
+ let(:foo) { %w(Color) }
48
+ it { is_expected.to be_valid }
49
+ end
50
+
51
+ context "when attribute has size greater than limit" do
52
+ let(:foo) { %w(Color Size Style) }
53
+ it { is_expected.to be_valid }
54
+ end
55
+
56
+ context "when attribute is not an array" do
57
+ let(:foo) { 1 }
58
+ it { is_expected.to be_invalid_with_error :foo, :size_other_than }
59
+ end
60
+ end
61
+
62
+ context "greater_than number" do
63
+ before { Test::Subject.validates :foo, size: { greater_than: 2 } }
64
+
65
+ context "when attribute has size equal to limit" do
66
+ let(:foo) { %w(Color Size) }
67
+ it { is_expected.to be_invalid_with_error :foo, :size_greater_than }
68
+ end
69
+
70
+ context "when attribute has size less than limit" do
71
+ let(:foo) { %w(Color) }
72
+ it { is_expected.to be_invalid_with_error :foo, :size_greater_than }
73
+ end
74
+
75
+ context "when attribute has size greater than limit" do
76
+ let(:foo) { %w(Color Size Style) }
77
+ it { is_expected.to be_valid }
78
+ end
79
+
80
+ context "when attribute is not an array" do
81
+ let(:foo) { 1 }
82
+ it { is_expected.to be_invalid_with_error :foo, :size_greater_than }
83
+ end
84
+ end
85
+
86
+ context "greater_than_or_equal_to number" do
87
+ before do
88
+ Test::Subject.validates :foo, size: { greater_than_or_equal_to: 2 }
89
+ end
90
+
91
+ context "when attribute has size equal to limit" do
92
+ let(:foo) { %w(Color Size) }
93
+ it { is_expected.to be_valid }
94
+ end
95
+
96
+ context "when attribute has size less than limit" do
97
+ let(:foo) { %w(Color) }
98
+ it do
99
+ is_expected
100
+ .to be_invalid_with_error :foo, :size_greater_than_or_equal_to
101
+ end
102
+ end
103
+
104
+ context "when attribute has size greater than limit" do
105
+ let(:foo) { %w(Color Size Style) }
106
+ it { is_expected.to be_valid }
107
+ end
108
+
109
+ context "when attribute is not an array" do
110
+ let(:foo) { 1 }
111
+ it do
112
+ is_expected
113
+ .to be_invalid_with_error :foo, :size_greater_than_or_equal_to
114
+ end
115
+ end
116
+ end
117
+
118
+ context "less_than number" do
119
+ before { Test::Subject.validates :foo, size: { less_than: 2 } }
120
+
121
+ context "when attribute has size equal to limit" do
122
+ let(:foo) { %w(Color Size) }
123
+ it { is_expected.to be_invalid_with_error :foo, :size_less_than }
124
+ end
125
+
126
+ context "when attribute has size less than limit" do
127
+ let(:foo) { %w(Color) }
128
+ it { is_expected.to be_valid }
129
+ end
130
+
131
+ context "when attribute has size greater than limit" do
132
+ let(:foo) { %w(Color Size Style) }
133
+ it { is_expected.to be_invalid_with_error :foo, :size_less_than }
134
+ end
135
+
136
+ context "when attribute is not an array" do
137
+ let(:foo) { 1 }
138
+ it { is_expected.to be_invalid_with_error :foo, :size_less_than }
139
+ end
140
+ end
141
+
142
+ context "less_than_or_equal_to number" do
143
+ before { Test::Subject.validates :foo, size: { less_than_or_equal_to: 2 } }
144
+
145
+ context "when attribute has size equal to limit" do
146
+ let(:foo) { %w(Color Size) }
147
+ it { is_expected.to be_valid }
148
+ end
149
+
150
+ context "when attribute has size less than limit" do
151
+ let(:foo) { %w(Color) }
152
+ it { is_expected.to be_valid }
153
+ end
154
+
155
+ context "when attribute has size greater than limit" do
156
+ let(:foo) { %w(Color Size Style) }
157
+ it do
158
+ is_expected.to be_invalid_with_error :foo, :size_less_than_or_equal_to
159
+ end
160
+ end
161
+
162
+ context "when attribute is not an array" do
163
+ let(:foo) { 1 }
164
+ it do
165
+ is_expected.to be_invalid_with_error :foo, :size_less_than_or_equal_to
166
+ end
167
+ end
168
+ end
169
+
170
+ context "equal_to attribute" do
171
+ before { Test::Subject.validates :foo, size: { equal_to: "bar.baz" } }
172
+
173
+ context "when attribute has size equal to limit" do
174
+ let(:foo) { %w(Color Size) }
175
+ it { is_expected.to be_valid }
176
+ end
177
+
178
+ context "when attribute has size less than limit" do
179
+ let(:foo) { %w(Color) }
180
+ it do
181
+ is_expected.to be_invalid_with_error :foo, :size_equal_to_bar_baz
182
+ end
183
+ end
184
+
185
+ context "when attribute has size greater than limit" do
186
+ let(:foo) { %w(Color Size Style) }
187
+ it do
188
+ is_expected.to be_invalid_with_error :foo, :size_equal_to_bar_baz
189
+ end
190
+ end
191
+
192
+ context "when attribute is not an array" do
193
+ let(:foo) { 1 }
194
+ it do
195
+ is_expected.to be_invalid_with_error :foo, :size_equal_to_bar_baz
196
+ end
197
+ end
198
+ end
199
+
200
+ context "other_than attribute" do
201
+ before { Test::Subject.validates :foo, size: { other_than: "bar.baz" } }
202
+
203
+ context "when attribute has size equal to limit" do
204
+ let(:foo) { %w(Color Size) }
205
+ it do
206
+ is_expected.to be_invalid_with_error :foo, :size_other_than_bar_baz
207
+ end
208
+ end
209
+
210
+ context "when attribute has size less than limit" do
211
+ let(:foo) { %w(Color) }
212
+ it { is_expected.to be_valid }
213
+ end
214
+
215
+ context "when attribute has size greater than limit" do
216
+ let(:foo) { %w(Color Size Style) }
217
+ it { is_expected.to be_valid }
218
+ end
219
+
220
+ context "when attribute is not an array" do
221
+ let(:foo) { 1 }
222
+ it do
223
+ is_expected.to be_invalid_with_error :foo, :size_other_than_bar_baz
224
+ end
225
+ end
226
+ end
227
+
228
+ context "greater_than attribute" do
229
+ before { Test::Subject.validates :foo, size: { greater_than: "bar.baz" } }
230
+
231
+ context "when attribute has size equal to limit" do
232
+ let(:foo) { %w(Color Size) }
233
+ it do
234
+ is_expected.to be_invalid_with_error :foo, :size_greater_than_bar_baz
235
+ end
236
+ end
237
+
238
+ context "when attribute has size less than limit" do
239
+ let(:foo) { %w(Color) }
240
+ it do
241
+ is_expected.to be_invalid_with_error :foo, :size_greater_than_bar_baz
242
+ end
243
+ end
244
+
245
+ context "when attribute has size greater than limit" do
246
+ let(:foo) { %w(Color Size Style) }
247
+ it { is_expected.to be_valid }
248
+ end
249
+
250
+ context "when attribute is not an array" do
251
+ let(:foo) { 1 }
252
+ it do
253
+ is_expected.to be_invalid_with_error :foo, :size_greater_than_bar_baz
254
+ end
255
+ end
256
+ end
257
+
258
+ context "greater_than_or_equal_to attribute" do
259
+ before do
260
+ Test::Subject.validates :foo,
261
+ size: { greater_than_or_equal_to: "bar.baz" }
262
+ end
263
+
264
+ context "when attribute has size equal to limit" do
265
+ let(:foo) { %w(Color Size) }
266
+ it { is_expected.to be_valid }
267
+ end
268
+
269
+ context "when attribute has size less than limit" do
270
+ let(:foo) { %w(Color) }
271
+ it do
272
+ is_expected
273
+ .to be_invalid_with_error :foo, :size_greater_than_or_equal_to_bar_baz
274
+ end
275
+ end
276
+
277
+ context "when attribute has size greater than limit" do
278
+ let(:foo) { %w(Color Size Style) }
279
+
280
+ it { is_expected.to be_valid }
281
+ end
282
+
283
+ context "when attribute is not an array" do
284
+ let(:foo) { 1 }
285
+ it do
286
+ is_expected
287
+ .to be_invalid_with_error :foo, :size_greater_than_or_equal_to_bar_baz
288
+ end
289
+ end
290
+ end
291
+
292
+ context "less_than attribute" do
293
+ before { Test::Subject.validates :foo, size: { less_than: "bar.baz" } }
294
+
295
+ context "when attribute has size equal to limit" do
296
+ let(:foo) { %w(Color Size) }
297
+ it { is_expected.to be_invalid_with_error :foo, :size_less_than_bar_baz }
298
+ end
299
+
300
+ context "when attribute has size less than limit" do
301
+ let(:foo) { %w(Color) }
302
+ it { is_expected.to be_valid }
303
+ end
304
+
305
+ context "when attribute has size greater than limit" do
306
+ let(:foo) { %w(Color Size Style) }
307
+ it { is_expected.to be_invalid_with_error :foo, :size_less_than_bar_baz }
308
+ end
309
+
310
+ context "when attribute is not an array" do
311
+ let(:foo) { 1 }
312
+ it { is_expected.to be_invalid_with_error :foo, :size_less_than_bar_baz }
313
+ end
314
+ end
315
+
316
+ context "less_than_or_equal_to attribute" do
317
+ before do
318
+ Test::Subject.validates :foo, size: { less_than_or_equal_to: "bar.baz" }
319
+ end
320
+
321
+ context "when attribute has size equal to limit" do
322
+ let(:foo) { %w(Color Size) }
323
+ it { is_expected.to be_valid }
324
+ end
325
+
326
+ context "when attribute has size less than limit" do
327
+ let(:foo) { %w(Color) }
328
+ it { is_expected.to be_valid }
329
+ end
330
+
331
+ context "when attribute has size greater than limit" do
332
+ let(:foo) { %w(Color Size Style) }
333
+ it do
334
+ is_expected.to be_invalid_with_error \
335
+ :foo, :size_less_than_or_equal_to_bar_baz
336
+ end
337
+ end
338
+
339
+ context "when attribute is not an array" do
340
+ let(:foo) { 1 }
341
+ it do
342
+ is_expected.to be_invalid_with_error \
343
+ :foo, :size_less_than_or_equal_to_bar_baz
344
+ end
345
+ end
346
+ end
347
+ end