-
Notifications
You must be signed in to change notification settings - Fork 63
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
Parse standard JSON API request instead of requiring _jsonapi key #79
Comments
+1, running into the same issue. |
Hey @TylerRick I found out what our issue is. In https://github.com/jsonapi-rb/jsonapi-rails/blob/master/lib/jsonapi/rails/railtie.rb#L13 you can see the parser is inserting the # config/initializers/register_mime_types.rb
api_mime_types = %W(
application/vnd.api+json
text/x-json
application/json
)
Mime::Type.register 'application/vnd.api+json', :json, api_mime_types EDIT: You actually don't need to register the mime type. The railtie already does this Then in all your requests you'll need to specify You probably want to set this up for your specs too. For RSpec I created a file # frozen_string_literal: true
module ApiDefaultHeaders
extend ActiveSupport::Concern
HTTP_METHODS = %w(get post put delete patch).freeze
included do
# make requests xhr requests for all tests
let(:default_headers) {
{
HTTP_ACCEPT: 'application/vnd.api+json',
CONTENT_TYPE: 'application/vnd.api+json'
}
}
HTTP_METHODS.each do |m|
define_method(m) do |path, *args|
args[0] ||= {}
args[0][:headers] ||= {}
args[0][:headers].merge!(default_headers)
super(path, *args)
end
end
end
end Then in # spec/rails_helper.rb
RSpec.configure do |config|
# use application/vnd.api+json as the default headers
config.include ApiDefaultHeaders #, api: true
# to use in api specs...
# RSpec.describe SomeController, type: request, api: true do
end EDIT #2 # frozen_string_literal: true
module ApiDefaultHeaders
extend ActiveSupport::Concern
HTTP_METHODS = %w(get post put delete patch).freeze
included do
# make requests jsonapi compliant
let(:default_headers) {
{
HTTP_ACCEPT: 'application/vnd.api+json',
CONTENT_TYPE: 'application/vnd.api+json'
}
}
HTTP_METHODS.each do |m|
define_method(m) do |path, *args|
args[0] ||= {}
args[0][:headers] ||= {}
args[0][:headers].merge!(default_headers)
# convert hash to json if not already
args[0][:params] ||= {}
args[0][:params].to_json unless args[0][:params].is_a? String
super(path, *args)
end
end
end
end Now you can write params as you normally would with a hash and the request should work correctly |
@TylerRick Thanks for providing this clear writeup. What's happening is that the lib does not, indeed, expect the payload to be non standard, but the deserialization process does wrap it within a |
Thanks for the response. I'm afraid I still don't understand but that's okay, I didn't end up using this library in my project since it was was taking too long to figure out. This may trip up other newcomers though, so it still may be worth improving (or clarifying in the docs). The docs (http://jsonapi-rb.org/guides/deserialization/deserializing.html, for example) make it sound like the payload just needs to be at the top-level like (I noticed that error was actually replaced with a more specific message in So again, it seems like |
@TylerRick you're right and not mistaken. I'm running into the same issue when doing an external request, even when providing the |
Okay, it seems that @JoeWoodward's solution for registering/overriding the To fix the specs you don't have to do any changes in mime types or headers. Just do a normal request in
and define
You don't have to call Unfortunately it doesn't help setting the correct I hope that solves your problem too @TylerRick. |
The actual issue here is that controller test (I use rspec controller specs) are broken out of the box. I assumed that if I switched to using |
In my case, I was running into this in development, not in tests (though I might run into it there too). I don't understand why it doesn't accept/deserialize requests from external (non-Rails) sources, in standard JSONAPI format, which doesn't require a |
That is odd. Are you sure that you're correctly setting the content type of your requests? I only have the issue in controller tests. The actual application is working fine. |
Thanks for the suggestion. I don't have the test app anymore so I can't test it, but that might have been the problem. I probably didn't do anything to set the content type (or it might have used a JSON content type, I can't remember). |
Looks like the I ran into problems because in thrashing with getting rails and jsonapi to work well together and in trying all the gems I had an stray initializer that was registering the mimetype |
I had this line previously in my initializer, but I just realized it broken again after updating one of our other gems, maybe this can still be helpful ActionDispatch::Request.parameter_parsers[:jsonapi] =
ActionDispatch::Request.parameter_parsers[:json] |
As @Startouf points out, the parser, registered by the gem in the railtie can be overwritten in your initializer. Setting it to the default json parser prevents your params from being nested within an # rails 5.x only!
ActionDispatch::Request.parameter_parsers[:jsonapi] = ActionDispatch::Request.parameter_parsers[:json] |
Started looking into using this project in my Rails app but right out of the gate I started getting
errors with even the simplest test request made to my
create
action.Tracked it down to this source code:
Indeed failing with a helpful error message would be better than a Ruby exception, but why is it requiring a
_jsonapi
key in theparams
in the first place?It seems rather non-standard (I don't see mention of a
_jsonapi
key in the http://jsonapi.org/ spec) and surprising and I don't see anything about it in the Readme nor on http://jsonapi-rb.org/guides/getting_started/rails.html guide either nor http://jsonapi-rb.org/guides/deserialization/deserializing.html.Why does it expect the payload to be wrapped with this extra key? And how are such payloads expected to be generated? Maybe I'm just missing something but it would be nice if the getting started code was a little more complete and included an example of producing a payload in addition to consuming it (not that I plan on using this library to produce the payload—planning to use an Angular service to make the request—but it would at least serve as an example). The example shows a
create
action but doesn't show how you would make a request that it can understand.What I would expect instead
I would expect that a JSON payload formatted according to the JSON API spec would be parsed without error, so that I could use this in the backend with any frontend framework that speaks JSON API.
Example of a valid payload for creating a resource (from http://jsonapi.org/format/#crud-creating):
My test example
Using versions:
The text was updated successfully, but these errors were encountered: