Skip to content

Commit 759abc7

Browse files
committed
Fix shared state between class instances
Use Marshal load and dump to make a deep clone.
1 parent 61ab055 commit 759abc7

File tree

3 files changed

+29
-1
lines changed

3 files changed

+29
-1
lines changed

.rubocop.yml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,3 +18,5 @@ Metrics/AbcSize:
1818
Style/DocumentationMethod:
1919
Enabled: true
2020

21+
RSpec/ExampleLength:
22+
Max: 15

lib/ez_attributes.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ def attributes(*args, **args_with_default)
2626
optional_args = args_with_default.map { |name, _| "#{name}: __args_with_default[:#{name}]" }
2727
init_args = (required_args + optional_args).join(', ')
2828

29-
define_method('__args_with_default', -> { args_with_default.dup })
29+
define_method('__args_with_default', -> { Marshal.load(Marshal.dump(args_with_default)) })
3030
private :__args_with_default
3131

3232
all_args = args + args_with_default.keys

spec/ez_attributes_spec.rb

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -111,4 +111,30 @@
111111
expect(obj.if).to eq true
112112
end
113113
end
114+
115+
context 'when an instance mutates state' do
116+
let(:test_class) do
117+
Class.new do
118+
extend EzAttributes
119+
120+
attributes a: []
121+
122+
def change_attr
123+
a << 1
124+
end
125+
end
126+
end
127+
128+
it 'does not share state with other instances', :aggregate_failures do
129+
obj1 = test_class.new
130+
obj1.change_attr
131+
obj1.change_attr
132+
133+
obj2 = test_class.new
134+
obj2.change_attr
135+
136+
expect(obj1.a).to eq [1, 1]
137+
expect(obj2.a).to eq [1]
138+
end
139+
end
114140
end

0 commit comments

Comments
 (0)