-
-
Notifications
You must be signed in to change notification settings - Fork 1.2k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
fix(#1922): Allow to use instance variables defined in the endpoints inside rescue_from #2377
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This looks very good! No other specs are failing, which means we're on the right track to defining this behavior.
- What happens if I do
@var = 1
in the first call, does it exist in the second call to the same API? What's the scope of@var
across multiple API methods? All these need tests. - Document this behavior in README.
- The meaning of
@var
has changed inrescue_from
, it will need an UPGRADING explanation. No specs were broken, but is it a breaking change?
Hi @dblock 👋 thanks! For the first point: If you do class MyAPI < Grape::API
class MyError < StandardError; end
rescue_from MyError do |e|
puts "rescue_from_self => #{self.class}"
puts "rescue_from_my_var => #{@my_var}"
error!({ my_var: @my_var }, 401)
end
get '/first' do
@my_var = 1
puts "my_var => #{@my_var}"
puts "self => #{self.class}"
raise MyError.new
end
get '/second' do
puts "my_var => #{@my_var}"
puts "self => #{self.class}"
raise MyError.new
end
end And here the output after performing my_var => 1
self => #<Class:0x0000000105ffa518>
rescue_from_self => #<Class:0x0000000105ffa518>
rescue_from_my_var => 1
::1 - - [22/Nov/2023:16:34:44 +0100] "GET /first HTTP/1.1" 401 12 0.0334
my_var =>
self => #<Class:0x0000000105ff9578>
rescue_from_self => #<Class:0x0000000105ff9578>
rescue_from_my_var =>
::1 - - [22/Nov/2023:16:34:47 +0100] "GET /second HTTP/1.1" 401 15 0.0012
my_var => 1
self => #<Class:0x0000000105ffa518>
rescue_from_self => #<Class:0x0000000105ffa518>
rescue_from_my_var => 1
::1 - - [22/Nov/2023:16:34:51 +0100] "GET /first HTTP/1.1" 401 12 0.0014 As you can see, one instance per endpoint is created (when calling Do you think we should add several tests for checking that this behavior does not change? For point number 2: Totally agree on document this behavior in the README 👍 let me add a commit to this PR For point number 3: Yes. Before these changes, the meaning of Thank you again for the review!! |
Great. Let's write a spec like this. Thanks again! |
…the instance variables behavior. Extra tests added
Hey @dblock 👋 I've just updated the specs for including the cases we discussed above. Also, I've updated the Let me know if anything else is needed 😄 |
…e run_rescue_handler method
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks good. Can I ask for a quick example in UPGRADING and also say "This behavior was undefined until 2.1.0." so that it doesn't sound like a breaking change.
Merged, thank you. |
Just FYI. Because the context for calling a rescue_from block has changed, the
and now the
So if for some reason the |
@numbata So should these method be aligned? Either way, it would be helpful to write a test that demonstrates this, and/or add it to UGPRADING.md. |
Hey 👋
I was taking a look at #1922 and after some checks I can see that we are in a different instance when we are inside the
rescue_from
method.The current output of the previous code is:
This means that we cannot have access to the same instance variables declared in the
before
because we are not in the same instance.For solving it, I'm adding the scope of the endpoint when performing the handler. So now I'm performing
endpoint.instance_exec(&handler)
instead ofinstance_exec(&handler)
where theendpoint
is the instance obtained from@env["api.endpoint"]
here.Doing it in that way, we are executing the handler under the endpoint instance scope and we have the variables accessible.
However, there are some trade-offs that we need to fix in this issue in order to pass all the tests.
As now we are performing the handler under the
endpoint
instance, the methods called inside therescue_from
should be defined in theinside_route.rb
file. I've experienced problems with two of those methods:error!
method. Is defined both times ininside_routes.rb
and in theerror.rb
. However, the one defined in theinside_routes.rb
is throwing an error and the one defined in theerror.rb
is just returning a rack response.error!
method, call theerror!
method from theerror.rb
again for returning the rack response. Check thisrack_response
method is used in several tests inside therescue_from
. However, this method is not defined in theinside_route.rb
file, what causes that aNoMethodError
is raised.rack_response
method in theinside_route.rb
file, so now endpoints can also perform this method for building a rack response.