-
Notifications
You must be signed in to change notification settings - Fork 21.4k
/
with.rb
46 lines (44 loc) · 1.16 KB
/
with.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
# frozen_string_literal: true
class Object
# Set and restore public attributes around a block.
#
# client.timeout # => 5
# client.with(timeout: 1) do |c|
# c.timeout # => 1
# end
# client.timeout # => 5
#
# The receiver is yielded to the provided block.
#
# This method is a shorthand for the common begin/ensure pattern:
#
# old_value = object.attribute
# begin
# object.attribute = new_value
# # do things
# ensure
# object.attribute = old_value
# end
#
# It can be used on any object as long as both the reader and writer methods
# are public.
def with(**attributes)
old_values = {}
begin
attributes.each do |key, value|
old_values[key] = public_send(key)
public_send("#{key}=", value)
end
yield self
ensure
old_values.each do |key, old_value|
public_send("#{key}=", old_value)
end
end
end
end
# #with isn't usable on immediates, so we might as well undefine the
# method in common immediate classes to avoid potential confusion.
[NilClass, TrueClass, FalseClass, Integer, Float, Symbol].each do |klass|
klass.undef_method(:with)
end