Hi,
I just encountered this and would like to sanity check.
When you present a Grape::Entity, rendering of the entity is deferred until some point deep within the framework and so runtime errors within your entity do not impede evaluation of the rest of your route (including after blocks).
For example, the below will error and the consumer of the API is not going to get a useful response, but log_success! and the after block are both still going to run:
module API
class API < Grape::API
class User < Struct.new(:name, keyword_init: true); end
class UserEntity < Grape::Entity
expose :display_name
def display_name
end
end
helpers do
def log_success!
puts 'It works, pay me.'
end
end
after do
puts 'Pay me more.'
end
get '/' do
user = User.new(name: 'Boop')
present user, with: UserEntity
log_success!
end
end
end
Started GET "/" for 127.0.0.1 at 2020-08-24 12:30:27 +0100
It works, pay me.
Pay me more.
caught error of type NoMethodError in after callback inside Grape::Middleware::Formatter : undefined method `/' for "Boop":String
NoMethodError - undefined method `/' for "Boop":String:
A workaround seems to be to force the serialisation of the entity within the route, e.g. to use:
get '/' do
user = User.new(name: 'Boop')
present UserEntity.represent(user).as_json
# Now we don't get here if the above errors.
#
log_success!
end
Are there any unintended consequences of doing it like this or is there an alternative? Obviously in a real application we'll want to rescue from errors and present the errors in a JSON response of their own but I don't think that's material here.
Thanks.