How to serialize errors from not valid Ruby Objects?
rafaltrojanowski opened this issue · 4 comments
Hey,
This may be a duplicate of #22
Here is my snippet:
# controller
class CountriesController < ApplicationController
include JSONAPI::Errors
def index
# All good here:
# non_valid_active_record_object = Country.new
# render jsonapi_errors: non_valid_active_record_object.errors
# Another example:
service_object_with_errors = NonValidServiceObject.new
service_object_with_errors.save
puts service_object_with_errors.errors.to_h.inspect # => {:name=>"can't be blank"}
render jsonapi_errors: service_object_with_errors.errors, status: 422
end
end
# ruby object that uses ActiveModel validations
class NonValidServiceObject
include ActiveModel::Model
validates :name, presence: true
attr_accessor :name
def save
if valid?
else
self
end
end
end
Response:
{"errors":[{"status":"500","source":null,"title":"Internal Server Error","detail":null}]}
Logs:
Started GET "/countries" for ::1 at 2020-07-04 22:04:01 +0200
Processing by CountriesController#index as HTML
#<NonValidServiceObject:0x00007fa83c3068d0>
___________________________________________
{:name=>"can't be blank"}
DEPRECATION WARNING: Rails 6.1 will return Content-Type header without modification. If you want just the MIME type, please use `#media_type` instead. (called from index at /Users/rafaltrojanowski/Projects/coffeehaunt/app/controllers/countries_controller.rb:36)
DEPRECATION WARNING: Rails 6.1 will return Content-Type header without modification. If you want just the MIME type, please use `#media_type` instead. (called from content_type at /Users/rafaltrojanowski/.rbenv/versions/2.6.3/lib/ruby/gems/2.6.0/gems/actionpack-6.0.0/lib/action_controller/metal.rb:150)
Completed 500 Internal Server Error in 5ms (Views: 0.4ms | ActiveRecord: 0.0ms | Allocations: 3079)
Started GET "/serviceworker.js" for ::1 at 2020-07-04 22:04:03 +0200
Expected Behavior
Actual Behavior
Steps to Reproduce the Problem
Specifications
- Version:
- Ruby version:
Heya @rafaltrojanowski
Could you generate a full backtrace please. Either by writing a test (jsonapi.rb
500 error handling is disabled in the test environments) or by overwriting the error handling method
Generally speaking, you can generate any valid error response easily, here's an example:
https://github.com/stas/jsonapi.rb/blob/master/lib/jsonapi/errors.rb#L36-L39
Let me know if any of this helped!
Hey @stas
I went with passing errors explicitly for now as you suggested in a second link.
For the example that I posted above I'm getting:
def render_jsonapi_internal_server_error(exception)
binding.pry
# Call your exception notifier here. Example:
# Raven.capture_exception(exception)
super(exception)
end
#<NameError: uninitialized constant NonValidServiceObjectSerializer>
Backtrace:
["/Users/rafaltrojanowski/.rbenv/versions/2.6.3/lib/ruby/gems/2.6.0/gems/bootsnap-1.4.0/lib/bootsnap/load_path_cache/core_ext/active_support.rb:76:in `block in load_missing_constant'",
"/Users/rafaltrojanowski/.rbenv/versions/2.6.3/lib/ruby/gems/2.6.0/gems/bootsnap-1.4.0/lib/bootsnap/load_path_cache/core_ext/active_support.rb:8:in `without_bootsnap_cache'",
"/Users/rafaltrojanowski/.rbenv/versions/2.6.3/lib/ruby/gems/2.6.0/gems/bootsnap-1.4.0/lib/bootsnap/load_path_cache/core_ext/active_support.rb:76:in `rescue in load_missing_constant'",
"/Users/rafaltrojanowski/.rbenv/versions/2.6.3/lib/ruby/gems/2.6.0/gems/bootsnap-1.4.0/lib/bootsnap/load_path_cache/core_ext/active_support.rb:58:in `load_missing_constant'",
"/Users/rafaltrojanowski/.rbenv/versions/2.6.3/lib/ruby/gems/2.6.0/gems/activesupport-6.0.0/lib/active_support/inflector/methods.rb:282:in `const_get'",
"/Users/rafaltrojanowski/.rbenv/versions/2.6.3/lib/ruby/gems/2.6.0/gems/activesupport-6.0.0/lib/active_support/inflector/methods.rb:282:in `block in constantize'",
"/Users/rafaltrojanowski/.rbenv/versions/2.6.3/lib/ruby/gems/2.6.0/gems/activesupport-6.0.0/lib/active_support/inflector/methods.rb:280:in `each'",
"/Users/rafaltrojanowski/.rbenv/versions/2.6.3/lib/ruby/gems/2.6.0/gems/activesupport-6.0.0/lib/active_support/inflector/methods.rb:280:in `inject'",
"/Users/rafaltrojanowski/.rbenv/versions/2.6.3/lib/ruby/gems/2.6.0/gems/activesupport-6.0.0/lib/active_support/inflector/methods.rb:280:in `constantize'",
"/Users/rafaltrojanowski/.rbenv/versions/2.6.3/lib/ruby/gems/2.6.0/gems/activesupport-6.0.0/lib/active_support/core_ext/string/inflections.rb:68:in `constantize'",
"/Users/rafaltrojanowski/.rbenv/versions/2.6.3/lib/ruby/gems/2.6.0/gems/jsonapi.rb-1.5.7/lib/jsonapi/rails.rb:127:in `serializer_class'",
"/Users/rafaltrojanowski/.rbenv/versions/2.6.3/lib/ruby/gems/2.6.0/gems/jsonapi.rb-1.5.7/lib/jsonapi/rails.rb:54:in `block in add_errors_renderer!'",
"/Users/rafaltrojanowski/.rbenv/versions/2.6.3/lib/ruby/gems/2.6.0/gems/actionpack-6.0.0/lib/action_controller/metal/renderers.rb:150:in `block in _render_to_body_with_renderer'",
"/Users/rafaltrojanowski/.rbenv/versions/2.6.3/lib/ruby/2.6.0/set.rb:338:in `each_key'",
"/Users/rafaltrojanowski/.rbenv/versions/2.6.3/lib/ruby/2.6.0/set.rb:338:in `each'",
"/Users/rafaltrojanowski/.rbenv/versions/2.6.3/lib/ruby/gems/2.6.0/gems/actionpack-6.0.0/lib/action_controller/metal/renderers.rb:146:in `_render_to_body_with_renderer'",
"/Users/rafaltrojanowski/.rbenv/versions/2.6.3/lib/ruby/gems/2.6.0/gems/actionpack-6.0.0/lib/action_controller/metal/renderers.rb:142:in `render_to_body'",
"/Users/rafaltrojanowski/.rbenv/versions/2.6.3/lib/ruby/gems/2.6.0/gems/actionpack-6.0.0/lib/abstract_controller/rendering.rb:25:in `render'",
"/Users/rafaltrojanowski/.rbenv/versions/2.6.3/lib/ruby/gems/2.6.0/gems/actionpack-6.0.0/lib/action_controller/metal/rendering.rb:36:in `render'",
"/Users/rafaltrojanowski/.rbenv/versions/2.6.3/lib/ruby/gems/2.6.0/gems/actionpack-6.0.0/lib/action_controller/metal/instrumentation.rb:44:in `block (2 levels) in render'",
"/Users/rafaltrojanowski/.rbenv/versions/2.6.3/lib/ruby/gems/2.6.0/gems/activesupport-6.0.0/lib/active_support/core_ext/benchmark.rb:14:in `block in ms'",
"/Users/rafaltrojanowski/.rbenv/versions/2.6.3/lib/ruby/2.6.0/benchmark.rb:308:in `realtime'",
"/Users/rafaltrojanowski/.rbenv/versions/2.6.3/lib/ruby/gems/2.6.0/gems/activesupport-6.0.0/lib/active_support/core_ext/benchmark.rb:14:in `ms'",
"/Users/rafaltrojanowski/.rbenv/versions/2.6.3/lib/ruby/gems/2.6.0/gems/actionpack-6.0.0/lib/action_controller/metal/instrumentation.rb:44:in `block in render'",
"/Users/rafaltrojanowski/.rbenv/versions/2.6.3/lib/ruby/gems/2.6.0/gems/actionpack-6.0.0/lib/action_controller/metal/instrumentation.rb:85:in `cleanup_view_runtime'",
"/Users/rafaltrojanowski/.rbenv/versions/2.6.3/lib/ruby/gems/2.6.0/gems/activerecord-6.0.0/lib/active_record/railties/controller_runtime.rb:34:in `cleanup_view_runtime'",
"/Users/rafaltrojanowski/.rbenv/versions/2.6.3/lib/ruby/gems/2.6.0/gems/actionpack-6.0.0/lib/action_controller/metal/instrumentation.rb:43:in `render'",
#<NameError: uninitialized constant NonValidServiceObjectSerializer>
@rafaltrojanowski this looks like like an error related to not providing a serialization class for the NonValidServiceObject
that you defined.
Which makes sense if the errors you're trying to render are not ActiveModel::Errors
:
https://github.com/stas/jsonapi.rb/blob/master/lib/jsonapi/rails.rb#L45-L46
Why not just manually provide the error handling based on the example I already shared with you?!
Generally speaking, you can generate any valid error response easily, here's an example:
https://github.com/stas/jsonapi.rb/blob/master/lib/jsonapi/errors.rb#L36-L39
Thanks :)