Defining OpenStruct attribute with same name as instance method

835 Views Asked by At

I'm running into an issue when trying to create an open struct with an attribute that has the same name as one of the OpenStruct instance methods. Specifically, i'd like to create an open struct that has an attribute capture. I'm using this as a stub in an rspec test, so i can't change the name of the method (it must be capture)

#=> OpenStruct.new(capture: true).capture 
#=> ArgumentError: wrong number of arguments (0 for 1)

looking at the OpenStruct methods, it has a method capture and it is this method that is getting called. Is there a way to instantiate an open struct with an attribute of the same name as one of its methods?

for clarity, i specifically need the method capture, which i've confirmed breaks on rails 4.0.x but not rails 5, but this situation holds true for any method openstruct might have.

#=> OpenStruct.new(class: true).class 
#=> OpenStruct
1

There are 1 best solutions below

5
max pleaner On

This works just fine for me in pry (running ruby 2.3, by the way)

[9] pry(main)> OpenStruct.new(capture: 1).capture
=> 1

Here's another way to do it:

[15] pry(main)> a = OpenStruct.new capture: 1
=> #<OpenStruct capture=1>
[22] pry(main)> a.singleton_class.class_exec { def capture; self[:capture] + 1; end }
=> :capture
[23] pry(main)> a.capture
=> 2

i don't know what testing library you're using, but if it's RSpec, you could use this mocking approach as well:

a = OpenStruct.new capture: 0
allow(a).to receive(:capture).and_return(a[:capture])
a.capture # => 0