Skip to content
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

Allows for a block of code to always run after the endpoint #1864

Merged
merged 11 commits into from
Feb 26, 2019

Conversation

myxoh
Copy link
Member

@myxoh myxoh commented Feb 20, 2019

#1865

Motive: Sometime we do things like logging, or open sessions, or other actions during an API request and we want to make sure those actions are wrapped up afterwards.

This introduces a DSL way of handling this after every request on an API

lib/grape/dsl/request_response.rb Outdated Show resolved Hide resolved
lib/grape/middleware/error.rb Outdated Show resolved Hide resolved
@LeFnord
Copy link
Member

LeFnord commented Feb 21, 2019

is it a different funcionality as this one #before-and-after?

@myxoh
Copy link
Member Author

myxoh commented Feb 21, 2019

@LeFnord
It's related to the before-and-after (potentially that section would be a better place on the description)
The difference between after and ensure_block is that ensure_block will run even when there has been an exception on the API while after will not

@LeFnord
Copy link
Member

LeFnord commented Feb 21, 2019

… ok, something like an around 😉

@myxoh
Copy link
Member Author

myxoh commented Feb 21, 2019

Difference would be that this is not run before.
So the cycle would be
before
api_call
IF success
after
END
ensure

@LeFnord
Copy link
Member

LeFnord commented Feb 21, 2019

nice … please update above readme section with this, thanks

@dm1try
Copy link
Member

dm1try commented Feb 21, 2019

is it a different funcionality as this one #before-and-after?
It's related to the before-and-after

I don't think so; the implementation looks like a missing complementary part for rescue_from sugar and even lives in the error middleware.

Sometime we do things like logging, or open sessions, or other actions during an API request and we want to make sure those actions are wrapped up afterwards.

maybe this can be solved by using an endpoint middleware(the spec)

@myxoh
Copy link
Member Author

myxoh commented Feb 22, 2019

I've updated the lifecycle clarifying how this will run. I agree that it could be sorted by Middleware @dm1try but I do feel like having an after block that always run should be a feature in Grape regardless.
Could we move the discussion around the feature to the issue: #1865 and discuss over here only the implementation?

@dm1try
Copy link
Member

dm1try commented Feb 23, 2019

I've updated the lifecycle clarifying how this will run.

Users might be confused by the current implementation, as the description hints that ensure_block is the part of a request lifecycle, though this block is run in the different scope(in the error middleware) which means it does not share the endpoint state.

before do
 @state = true
end
ensure_block do
  @state # error
end

Moreover according to the ordering in the current middleware stack, ensure_block can be called without a preceding before block if the error will be raised before an endpoint run(for example, versioner middleware can raise an error that will be caught by error middleware); it feels unexpected.

but I do feel like having an after block that always run should be a feature in Grape regardless.

btw, the same behavior that proposed here can be emulated by using filters middleware without providing anything new:

use Grape::Middleware::Filter, after: -> { do_something }

@dblock
Copy link
Member

dblock commented Feb 24, 2019

I like the syntactic sugar of ensure_block. I would prefer ensure, but I presume it won't work as a reserved keyword? naming is hard :)

I think @dm1try has a very valid point (nice catch) about scope of execution and corresponding before, I think that needs to be fixed and explained clearly what the scope of execution is

@myxoh
Copy link
Member Author

myxoh commented Feb 24, 2019

Nice catch @dm1try, I'll give it a go at moving the scope, this was just a simple MVP.

Regarding wording, I went for ensure initially but yes, it being a reserved keyword made things nasty.

We could go with things like always or finally (borrowing from other languages)

@dblock
Copy link
Member

dblock commented Feb 24, 2019

How do others feel about finally vs. ensure_block?

@myxoh
Copy link
Member Author

myxoh commented Feb 25, 2019

after some thought I think I like finally better. I've also proceeded to move the logic to the endpoint so it shares scope with other callbacks like before and the helpers.

@LeFnord
Copy link
Member

LeFnord commented Feb 25, 2019

+1 for finally

Copy link
Member

@dblock dblock left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks great. Only some nitpicky comments around my English language OCD

README.md Outdated

Blocks can be executed before or after every API call, using `before`, `after`,
`before_validation` and `after_validation`.
If the API fails the `after` call will not be trigered, if you need code to execute for sure
use the `finally`
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Missing period.

README.md Outdated
4. `after_validation` (if Validation Successful)
5. _the API call_ (if Validation Successful)
6. `after` (if Validation & API Successful)
7. `finally` (ALWAYS)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nitpicking, let's not SHOUT :) I would make all of the comments lowercase (upon successful validation, always, etc.)

@@ -3121,6 +3124,13 @@ before do
end
```

You can ensure a block of code runs after every request (including failures) with `finally`:
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add a space below.

README.md Outdated
You can ensure a block of code runs after every request (including failures) with `finally`:
```ruby
finally do
This.block(of: code) # Will definetely run after every request
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

maybe just # this code will run after every successful or failed request, cause This.block(of: code) is not ruby


# Allows you to specify a something that will always be executed after a call
# API call. Unlike the `after` block, this code will run even on
# unsuccesful requests
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add a period after requests.


# status verifies body presence when DELETE
@body ||= response_object
# The Body commonly is an Array of Strings, the application instance itself, or a File-like object
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lowercase body

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(I'm merely moving this around but happy to address this anyway)

@dblock
Copy link
Member

dblock commented Feb 25, 2019

I'm cool with this change if @dmitry is cool with this change?

lib/grape/endpoint.rb Outdated Show resolved Hide resolved
@myxoh
Copy link
Member Author

myxoh commented Feb 25, 2019

I'll address your changes @dblock as soon as @dm1try helps me decide on the situation of a finally raising an error

@myxoh
Copy link
Member Author

myxoh commented Feb 26, 2019

Addressed

@dblock dblock merged commit b79bd9c into ruby-grape:master Feb 26, 2019
@dblock
Copy link
Member

dblock commented Feb 26, 2019

Merged.

I want to thank @dm1try @LeFnord and of course @myxoh for this beautiful example of collaboration, strong, but not stubborn opinions and an excellent feature that will make API developers' work easier. 🍻

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

5 participants