Hey, I had a use-case where I was trying to create a controller action which didn't fit neatly into CRUD actions. I'm wondering if there's a way to do this in jsonapi-resources without too much trouble. I'd like to take advantage of the standardized success/error response formatting, but don't want to play too much around with the internals to achieve this goal. Anyone have any ideas?
Have you tried adding the method to your controller?
@lgebhardt yeah, I have. I'm thinking about stuff like what if my controller action raises an exception, it would be nice to have a way to make it render errors in the same format as jsonapi-resources, etc...
You could reuse the handle_exceptions method. For example:
class FoosController < JSONAPI::ResourceController
def bar
#handle bar stuff
rescue => e
handle_exceptions(e)
end
end
You would need to make sure all your exceptions are derived from JSONAPI::Exceptions::Error, or you could override the handle_exceptions class to account for your custom exceptions.
Similarly what's the standard for overriding a crud action and allowing other parameters. I have an object which takes file upload which obviously is using multipart form-data so I don't want to use the default controller action.
I think one approach that has potential would be to check the Content-Type header. If the Content-Type is application/vnd.api+json you could treat the request as a JSONAPI request, and otherwise you could process it as a file upload.
The content type is not currently being enforced through the controller, but #69 is almost ready.
Once #69 is merged you could try some code like (I have not tested this, so no promises):
class PostsController < JSONAPI::ResourceController
skip_before_filter :setup_request, only: [:create]
skip_before_filter :ensure_correct_media_type, only: [:create]
def create
if request.content_type == JSONAPI::MEDIA_TYPE
setup_request
process_request_operations
elsif request.content_type == your type here
#Handle file upload
else
raise JSONAPI::Exceptions::UnsupportedMediaTypeError.new(request.content_type)
end
end
end
Would it be possible to use all the goodness (attributes validation, errors, etc) of jsonapi-resources for different methods?
I have a publish method which behaves very similar to the update method, but it validates a different set of attributes and sets some other extra info in the model.
How can I use the process_request_operations which validates that the attributes are correct, the error, the response, etc, but behaving like the update method? or even better calling a different method than update_attributes/save (eg publish)
You're often better to recast those non-RESTful actions as REST resources. In the case of a publish method, consider exposing a publication resource that has an associated article or document that gets 'published' when the publication is created.
Hi @xdmx @adamworrall ,
I have similar use case as @xdmx. The hack I have is, instead of resitfy actions into resources, add a virtual attribute on the model say command. When I wish to "publish", i would do the following with Ember Data:
model.set('command', 'publish');
model.save()
then in rails, I would use a before_validation, or before_update call back to dispatch to the right method do all the work and reset command back to nil. This way, I can check whether the command is valid given the current state of the model and leverage all the goodness in rails/jsonapi-resource/ember-data to handle the usual errors and updates. And if you want to give additional parameters to the special action/command, just add another virtual attr to the model, e.g. command_params (this is almost equivalent to a rpc call).
I find this approach a bit dirty but workable especially given the constraints of Ember data. We don't have to hack around Ember data model urls, pushpayload, and create additional resource files.
What do you think?
@lgebhardt , are there some plans to support other media types ( in case of upload ) officially ?
@Fivell I do have plans to support file uploads, but at this point I've done no work towards that goal.
@lgebhardt, any update on this?
@Fivell Sorry, I still haven't looked into uploads.
@lgebhardt Did you start working with it? I need so much this feature! 馃槃
@gigorok No, I haven't started any work on non CRUD operations. Have you tried modifying your controller to handle this? See my above suggestion on switching based on the content type.
@lgebhardt how we solved this @envoy for file uploading is we have an endpoint that only accepts a Content-Type: multipart for the body of the file and other values and the Accept: application/vnd+jsonapi as the response format. This is well within the ability for JsonAPI content negotiation.
@warmwaffles actually per the spec, it requires client to request application/vnd+jsonapi as the content-type as well. I was going to do that, but it's also out of spec.
@TrevorHinesley it's not out of spec, it's the whole part of HTTP content negotiation.
Clients MUST send all JSON API data in request documents with the header
Content-Type: application/vnd.api+jsonwithout any media type parameters.
If the request does not have a json api in the content-type, then it will not be parsed as such. However if the client requests that the response be Json Api, we should honor that. This is a grey area of the spec, and should be left alone honestly. Allows more freedom.
@warmwaffles ahh good point. I stand corrected--that's great! Thanks a ton. Makes my life easier haha.
Most helpful comment
@Fivell I do have plans to support file uploads, but at this point I've done no work towards that goal.