HI,
How to raise own exception in resource eg in case of duplicate records?
@Exelord You should be able to create a new JSONAPI::Exception and raise that when you detect the error.
module JSONAPI
module Exceptions
class DuplicateRecordError < Error
attr_accessor :id
def initialize(id)
@id = id
end
def errors
[JSONAPI::Error.new(code: JSONAPI::RECORD_NOT_FOUND,
status: :bad_request,
title: 'Record already exists',
detail: "The record identified by #{id} already exists.")]
end
end
end
end
JSONAPI::Exception::Errors will be caught and turned into a compliant error response.
However I'm wondering if this should be a core exception and we're just missing it. In what cases are you needing to raise this? I can see at least one situation we could use this ad I don't think we test for: trying to create a resource with a client generated id a second time.
@lgebhardt Thanks for your replay :) :+1:
I will test this on monday. It was just example cuz I have to create many of custom exceptions. One of them is case when user want to activate his currently active account and then I need a custom code of that error to pass it in frontend's translations.
I think that case of DuplicateRecordErrorwill be only exist on Database level cuz client generated ids aren't used by most apps. But of course u can think about it if you found some cases :) and please let me know... feed my curiosity :dart:
Hmm...
I created a file /lib/exceptions.rb and add there your code. I also require this file in initializer. After that in controller method:
def index
fail JSONAPI::Exceptions::DuplicateRecordError.new(4)
end
and it doesn't render the error :/
The response look like:
JSONAPI::Exceptions::DuplicateRecordError at /api/v1/accounts
=============================================================
> JSONAPI::Exceptions::DuplicateRecordError
By declaring the index method on the controller you are bypassing the JR logic for the index method so the JR code won't ever see the exception. You would need to raise this exception from your resource or from a custom OperationsProcessor.
Note, with JR you will rarely have any code in your controller for the actions. I suspect this is one of the harder things for people new to the project to wrap their heads around. In JSONAPI::ActsAsResourceController the index method calls process_request. It is in process_request that the JSONAPI::Exceptions are caught and rendered as an error response.
OK, so How can I ovveride index or show method for erg resource?
For example:
I need to check if param domain is passed to index function. If is i have to return exactly one record. Now I use:
if params[:domain]
check_account
else
super
end
and
def check_account
if account
render json: JSONAPI::ResourceSerializer.new(AccountResource)
.serialize_to_hash(AccountResource.new(account, nil))
else
response_errors(formatted_errors(:account_not_found), 403)
end
end
It almost works but context is not passed to the resource :/ Is there a workaround or right way to do that?
If the rest works why don't you just pass context into the AccountResource constructor?
Because when I write JSONAPI::ResourceSerializer.new(AccountResource, context: context) it doesnt works for me :/ context is still undefined
The ResourceSerializer doesn't use context as an option in the initializer. It expects the context to come from the resource it's serializing. So in your example you should be doing:
def check_account
if account
render json: JSONAPI::ResourceSerializer.new(AccountResource)
.serialize_to_hash(AccountResource.new(account, context))
else
response_errors(formatted_errors(:account_not_found), 403)
end
end
@lgebhardt back to your first response to this issue: Shouldn't jsonapi-resources check if the resource exists first before create and if so, return a status of :conflict (409)?
Hey @lgebhardt, your advice a few comments above, about creating a new type of error was pretty useful, thanks! I wonder if it is ok to create like errors folder inside app. I think it gives a way to idiomatically add in new types of errors. What do you think?
Most helpful comment
@Exelord You should be able to create a new
JSONAPI::Exceptionand raise that when you detect the error.JSONAPI::Exception::Errorswill be caught and turned into a compliant error response.However I'm wondering if this should be a core exception and we're just missing it. In what cases are you needing to raise this? I can see at least one situation we could use this ad I don't think we test for: trying to create a resource with a client generated id a second time.