-
-
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
Allows for a block of code to always run after the endpoint #1864
Changes from 9 commits
7c86e92
948ef5d
439932a
8df7235
2c622ed
20260c4
338a845
cbdb07d
111f714
41b7965
e505e3d
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -109,7 +109,7 @@ | |
- [Register custom middleware for authentication](#register-custom-middleware-for-authentication) | ||
- [Describing and Inspecting an API](#describing-and-inspecting-an-api) | ||
- [Current Route and Endpoint](#current-route-and-endpoint) | ||
- [Before and After](#before-and-after) | ||
- [Before, After and Finally](#before-after-and-finally) | ||
- [Anchoring](#anchoring) | ||
- [Using Custom Middleware](#using-custom-middleware) | ||
- [Grape Middleware](#grape-middleware) | ||
|
@@ -3089,19 +3089,22 @@ class ApiLogger < Grape::Middleware::Base | |
end | ||
``` | ||
|
||
## Before and After | ||
## Before, After and Finally | ||
|
||
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` | ||
|
||
Before and after callbacks execute in the following order: | ||
|
||
1. `before` | ||
2. `before_validation` | ||
3. _validations_ | ||
4. `after_validation` | ||
5. _the API call_ | ||
6. `after` | ||
4. `after_validation` (if Validation Successful) | ||
5. _the API call_ (if Validation Successful) | ||
6. `after` (if Validation & API Successful) | ||
7. `finally` (ALWAYS) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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 ( |
||
|
||
Steps 4, 5 and 6 only happen if validation succeeds. | ||
|
||
|
@@ -3121,6 +3124,13 @@ before do | |
end | ||
``` | ||
|
||
You can ensure a block of code runs after every request (including failures) with `finally`: | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Add a space below. |
||
```ruby | ||
finally do | ||
This.block(of: code) # Will definetely run after every request | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. maybe just |
||
end | ||
``` | ||
|
||
**Namespaces** | ||
|
||
Callbacks apply to each API call within and below the current namespace: | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -43,6 +43,26 @@ def after_validation(&block) | |
def after(&block) | ||
namespace_stackable(:afters, block) | ||
end | ||
|
||
# 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 | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Add a period after |
||
# @example | ||
# class ExampleAPI < Grape::API | ||
# before do | ||
# ApiLogger.start | ||
# end | ||
# finally do | ||
# ApiLogger.close | ||
# end | ||
# end | ||
# | ||
# This will make sure that the ApiLogger is opened and close around every | ||
# request | ||
# @param ensured_block [Proc] The block to be executed after every api_call | ||
def finally(&block) | ||
namespace_stackable(:finallies, block) | ||
end | ||
end | ||
end | ||
end | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -245,33 +245,38 @@ def run | |
@request = Grape::Request.new(env, build_params_with: namespace_inheritable(:build_params_with)) | ||
@params = @request.params | ||
@headers = @request.headers | ||
begin | ||
cookies.read(@request) | ||
self.class.run_before_each(self) | ||
run_filters befores, :before | ||
|
||
if (allowed_methods = env[Grape::Env::GRAPE_ALLOWED_METHODS]) | ||
raise Grape::Exceptions::MethodNotAllowed, header.merge('Allow' => allowed_methods) unless options? | ||
header 'Allow', allowed_methods | ||
response_object = '' | ||
status 204 | ||
else | ||
run_filters before_validations, :before_validation | ||
run_validators validations, request | ||
remove_aliased_params | ||
run_filters after_validations, :after_validation | ||
response_object = @block ? @block.call(self) : nil | ||
end | ||
|
||
cookies.read(@request) | ||
self.class.run_before_each(self) | ||
run_filters befores, :before | ||
|
||
if (allowed_methods = env[Grape::Env::GRAPE_ALLOWED_METHODS]) | ||
raise Grape::Exceptions::MethodNotAllowed, header.merge('Allow' => allowed_methods) unless options? | ||
header 'Allow', allowed_methods | ||
response_object = '' | ||
status 204 | ||
else | ||
run_filters before_validations, :before_validation | ||
run_validators validations, request | ||
remove_aliased_params | ||
run_filters after_validations, :after_validation | ||
response_object = @block ? @block.call(self) : nil | ||
end | ||
run_filters afters, :after | ||
cookies.write(header) | ||
|
||
run_filters afters, :after | ||
cookies.write(header) | ||
# status verifies body presence when DELETE | ||
@body ||= response_object | ||
|
||
# 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 | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. lowercase There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. (I'm merely moving this around but happy to address this anyway) |
||
response_object = file || [body] | ||
|
||
# The Body commonly is an Array of Strings, the application instance itself, or a File-like object | ||
response_object = file || [body] | ||
[status, header, response_object] | ||
[status, header, response_object] | ||
ensure | ||
# An error on the finallies should not prevent a succesful request from executing | ||
begin run_filters finallies, :finally end | ||
dm1try marked this conversation as resolved.
Show resolved
Hide resolved
|
||
end | ||
end | ||
end | ||
|
||
|
@@ -392,6 +397,10 @@ def afters | |
namespace_stackable(:afters) || [] | ||
end | ||
|
||
def finallies | ||
namespace_stackable(:finallies) || [] | ||
end | ||
|
||
def validations | ||
route_setting(:saved_validations) || [] | ||
end | ||
|
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.
Missing period.