Skip to content

Commit 866d024

Browse files
committed
RUBY-1021 implement #select and #reject for Options::Redacted
1 parent 2748bf5 commit 866d024

File tree

2 files changed

+288
-0
lines changed

2 files changed

+288
-0
lines changed

lib/mongo/options/redacted.rb

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,80 @@ def has_key?(key)
6565
end
6666
alias_method :key?, :has_key?
6767

68+
# Returns a new options object consisting of pairs for which the block returns false.
69+
#
70+
# @example Get a new options object with pairs for which the block returns false.
71+
# new_options = options.reject { |k, v| k == 'database' }
72+
#
73+
# @yieldparam [ String, Object ] The key as a string and its value.
74+
#
75+
# @return [ Options::Redacted ] A new options object.
76+
#
77+
# @since 2.1.0
78+
def reject(&block)
79+
new_options = dup
80+
new_options.reject!(&block) || new_options
81+
end
82+
83+
# Only keeps pairs for which the block returns false.
84+
#
85+
# @example Remove pairs from this object for which the block returns true.
86+
# options.reject! { |k, v| k == 'database' }
87+
#
88+
# @yieldparam [ String, Object ] The key as a string and its value.
89+
#
90+
# @return [ Options::Redacted ] This object.
91+
#
92+
# @since 2.1.0
93+
def reject!
94+
if block_given?
95+
n_keys = keys.size
96+
self.keys.each do |key|
97+
self.delete(key) if yield(key, self[key])
98+
end
99+
n_keys == keys.size ? nil : self
100+
else
101+
self.to_enum
102+
end
103+
end
104+
105+
# Returns a new options object consisting of pairs for which the block returns true.
106+
#
107+
# @example Get a new options object with pairs for which the block returns true.
108+
# ssl_options = options.select { |k, v| k =~ /ssl/ }
109+
#
110+
# @yieldparam [ String, Object ] The key as a string and its value.
111+
#
112+
# @return [ Options::Redacted ] A new options object.
113+
#
114+
# @since 2.1.0
115+
def select(&block)
116+
new_options = dup
117+
new_options.select!(&block) || new_options
118+
end
119+
120+
# Only keeps pairs for which the block returns true.
121+
#
122+
# @example Remove pairs from this object for which the block does not return true.
123+
# options.select! { |k, v| k =~ /ssl/ }
124+
#
125+
# @yieldparam [ String, Object ] The key as a string and its value.
126+
#
127+
# @return [ Options::Redacted ] This object.
128+
#
129+
# @since 2.1.0
130+
def select!
131+
if block_given?
132+
n_keys = keys.size
133+
self.keys.each do |key|
134+
self.delete(key) unless yield(key, self[key])
135+
end
136+
n_keys == keys.size ? nil : self
137+
else
138+
self.to_enum
139+
end
140+
end
141+
68142
private
69143

70144
def redacted_string(method)

spec/mongo/options/redacted_spec.rb

Lines changed: 214 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -129,4 +129,218 @@
129129
end
130130
end
131131
end
132+
133+
describe '#reject' do
134+
135+
let(:options) do
136+
described_class.new(a: 1, b: 2, c: 3)
137+
end
138+
139+
context 'when no block is provided' do
140+
141+
it 'returns an enumerable' do
142+
expect(options.reject).to be_a(Enumerator)
143+
end
144+
end
145+
146+
context 'when a block is provided' do
147+
148+
context 'when the block evaluates to true for some pairs' do
149+
150+
let(:result) do
151+
options.reject { |k,v| k == 'a' }
152+
end
153+
154+
it 'returns an object consisting of only the remaining pairs' do
155+
expect(result).to eq(described_class.new(b: 2, c: 3))
156+
end
157+
158+
it 'returns a new object' do
159+
expect(result).not_to be(options)
160+
end
161+
end
162+
163+
context 'when the block does not evaluate to true for any pairs' do
164+
165+
let(:result) do
166+
options.reject { |k,v| k == 'd' }
167+
end
168+
169+
it 'returns an object with all pairs intact' do
170+
expect(result).to eq(described_class.new(a: 1, b: 2, c: 3))
171+
end
172+
173+
it 'returns a new object' do
174+
expect(result).not_to be(options)
175+
end
176+
end
177+
end
178+
end
179+
180+
describe '#reject!' do
181+
182+
let(:options) do
183+
described_class.new(a: 1, b: 2, c: 3)
184+
end
185+
186+
context 'when no block is provided' do
187+
188+
it 'returns an enumerable' do
189+
expect(options.reject).to be_a(Enumerator)
190+
end
191+
end
192+
193+
context 'when a block is provided' do
194+
195+
context 'when the block evaluates to true for some pairs' do
196+
197+
let(:result) do
198+
options.reject! { |k,v| k == 'a' }
199+
end
200+
201+
it 'returns an object consisting of only the remaining pairs' do
202+
expect(result).to eq(described_class.new(b: 2, c: 3))
203+
end
204+
205+
it 'returns the same object' do
206+
expect(result).to be(options)
207+
end
208+
end
209+
210+
context 'when the block does not evaluate to true for any pairs' do
211+
212+
let(:result) do
213+
options.reject! { |k,v| k == 'd' }
214+
end
215+
216+
it 'returns nil' do
217+
expect(result).to be(nil)
218+
end
219+
end
220+
end
221+
end
222+
223+
describe '#select' do
224+
225+
let(:options) do
226+
described_class.new(a: 1, b: 2, c: 3)
227+
end
228+
229+
context 'when no block is provided' do
230+
231+
it 'returns an enumerable' do
232+
expect(options.reject).to be_a(Enumerator)
233+
end
234+
end
235+
236+
context 'when a block is provided' do
237+
238+
context 'when the block evaluates to true for some pairs' do
239+
240+
let(:result) do
241+
options.select { |k,v| k == 'a' }
242+
end
243+
244+
it 'returns an object consisting of those pairs' do
245+
expect(result).to eq(described_class.new(a: 1))
246+
end
247+
248+
it 'returns a new object' do
249+
expect(result).not_to be(options)
250+
end
251+
end
252+
253+
context 'when the block does not evaluate to true for any pairs' do
254+
255+
let(:result) do
256+
options.select { |k,v| k == 'd' }
257+
end
258+
259+
it 'returns an object with no pairs' do
260+
expect(result).to eq(described_class.new)
261+
end
262+
263+
it 'returns a new object' do
264+
expect(result).not_to be(options)
265+
end
266+
end
267+
268+
context 'when the object is unchanged' do
269+
270+
let(:options) do
271+
described_class.new(a: 1, b: 2, c: 3)
272+
end
273+
274+
let(:result) do
275+
options.select { |k,v| ['a', 'b', 'c'].include?(k) }
276+
end
277+
278+
it 'returns a new object' do
279+
expect(result).to eq(described_class.new(a: 1, b: 2, c: 3))
280+
end
281+
end
282+
end
283+
end
284+
285+
describe '#select!' do
286+
287+
let(:options) do
288+
described_class.new(a: 1, b: 2, c: 3)
289+
end
290+
291+
context 'when no block is provided' do
292+
293+
it 'returns an enumerable' do
294+
expect(options.reject).to be_a(Enumerator)
295+
end
296+
end
297+
298+
context 'when a block is provided' do
299+
300+
context 'when the block evaluates to true for some pairs' do
301+
302+
let(:result) do
303+
options.select! { |k,v| k == 'a' }
304+
end
305+
306+
it 'returns an object consisting of those pairs' do
307+
expect(result).to eq(described_class.new(a: 1))
308+
end
309+
310+
it 'returns the same object' do
311+
expect(result).to be(options)
312+
end
313+
end
314+
315+
context 'when the block does not evaluate to true for any pairs' do
316+
317+
let(:result) do
318+
options.select! { |k,v| k == 'd' }
319+
end
320+
321+
it 'returns an object with no pairs' do
322+
expect(result).to eq(described_class.new)
323+
end
324+
325+
it 'returns the same object' do
326+
expect(result).to be(options)
327+
end
328+
end
329+
330+
context 'when the object is unchanged' do
331+
332+
let(:options) do
333+
described_class.new(a: 1, b: 2, c: 3)
334+
end
335+
336+
let(:result) do
337+
options.select! { |k,v| ['a', 'b', 'c'].include?(k) }
338+
end
339+
340+
it 'returns nil' do
341+
expect(result).to be(nil)
342+
end
343+
end
344+
end
345+
end
132346
end

0 commit comments

Comments
 (0)