'Is it possible to set instance variables on class methods that are only visible to the current method and any method it calls?
Lets say I have the following:
class MyClass
class << self
def call(req_id)
@request_id = req_id
method_1
method_2
end
def method_1
puts "method 1 - req id: #{@request_id}"
sleep(@request_id)
end
def method_2
puts "method 2 - req id: #{@request_id}"
end
end
end
def func3
MyClass.call(6)
end
def func4
MyClass.call(2)
end
t1 = Thread.new{func3()}
sleep(1)
t2 = Thread.new{func4()}
t1.join
t2.join
And this produces the following output:
method 1 - req id: 6
method 1 - req id: 2
method 2 - req id: 2
method 2 - req id: 2
This makes sense since the class instance variable request_id gets changed by func4. But is there a way that we can make request_id specific only to it's own thread such that we get the following result:
method 1 - req id: 6
method 1 - req id: 2
method 2 - req id: 2
method 2 - req id: 6
I can accomplish this by straight up passing req_id to func3 and func4 but would like to avoid that if possible.
Is this possible to do by using instance vars?
Solution 1:[1]
You can use instance methods
Just create instances in class method
Like this as idea
class MyClass
class << self
def call(req_id)
new(req_id).call
end
end
def call
method1
method2
end
private
def initialize(req_id)
@request_id = req_id
end
def method1
puts "method 1 - req id: #{@request_id}"
sleep(@request_id)
end
def method2
puts "method 2 - req id: #{@request_id}"
end
end
def func3
MyClass.call(6)
end
def func4
MyClass.call(2)
end
t1 = Thread.new { func3 }
sleep(1)
t2 = Thread.new { func4 }
t1.join
t2.join
# will print
method 1 - req id: 6
method 1 - req id: 2
method 2 - req id: 2
method 2 - req id: 6
Solution 2:[2]
Only with dirty tricks: You could create the variable, and it will then be visible to the methods you are calling, but before you return from your "root" method, you have to destroy the variable again (using remove_instance_variable), lest it would continue to exist for the lifetime of this object.
For the same reason, you have to be careful with exceptions. Therefore I would place the remove_instance_variable into an ensure clause, to make sure that it is executed even if the method is left prematurely by an exception.
However it may be better tor rethink your design. Instead of creating and destroying instance variables on the fly, consider creating them in the constructor and set them to nil initially. Instead of removing the variable, set it to nil again.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | mechnicov |
| Solution 2 | user1934428 |
