rails-api / active_model_serializers

ActiveModel::Serializer implementation and Rails hooks
MIT License
5.32k stars 1.39k forks source link

unable to serialize error 406 (Not Acceptable). #2133

Open ramonlg opened 7 years ago

ramonlg commented 7 years ago

I'm working on an app, and I'm updating from the version 0.8.3 to 0.10.5. Before the update the errors were serialized like this:

{
  "errors": {
    "code": 404,
    "message": "Not Found",
    "details": {}
  }
}

I managed to update to the recente version, and almost everything is ok. But I'm having some trouble when try to serialize Not Acceptable Error(406).

For example, if I try to access this url http://localhost:3001/users.pdf, instead of rendering error 406, it shows error 500, and I get this on console:

Processing by ErrorsController#show as PDF
  Parameters: {"error_code"=>"406"}
[active_model_serializers] Rendered ErrorsSerializer with ActiveModelSerializers::Adapter::Json (1.12ms)
Completed 500 Internal Server Error in 24ms (ActiveRecord: 0.0ms)
Error during failsafe response: undefined method `model_name' for Hash:Class

Expected behavior

{
  "errors": {
    "code": 406,
    "message": "Not Acceptable",
    "details": {}
  }
}

Actual behavior

500 Internal Server Error

Environment

ActiveModelSerializers Version: 0.10.5 Ruby Version: 2.1.5 Rails Version: 4.2.1.7

Output of ruby -e "puts RUBY_DESCRIPTION": ruby 2.1.5p273 (2014-11-13 revision 48405) [x86_64-darwin14.0]

OS Type & Version: OSX Yosemite version 10.10.5

Gemfile

source 'https://rubygems.org'
ruby '2.1.5'

# Bundle edge Rails instead: gem 'rails', github: 'rails/rails'
gem 'rails', '~> 4.2.0'

# Error details on models
gem 'active_model-errors_details'

# Use mysql as the database for Active Record
gem 'mysql2'

# Build JSON APIs with ease. Read more: https://github.com/rails/jbuilder
gem 'jbuilder', '~> 2.0'

# API Documentation
gem 'apipie-rails'
gem 'maruku'

# has_secure_password
gem 'bcrypt'

# Use Puma as the app server
gem 'puma'

# Foreman
gem 'foreman'

# Solr client
gem 'rsolr'

# Pagination
gem 'kaminari'

# Responders
gem 'responders'

# Serializers
gem 'active_model_serializers', '~> 0.10.0'

# Dotenv load
gem 'dotenv-deployment', require: 'dotenv/deployment'

# Metrics
gem 'newrelic_rpm'

# Cache
gem 'dalli'
gem 'dalli-elasticache'
gem 'kgio'
gem 'connection_pool'
gem 'redis-rails'

# Redis
gem 'redis'
gem 'hiredis'

# Heroku
gem 'rails_12factor', group: [:staging, :production]

# Rack middleware for CORS configuration
gem 'rack-cors', :require => 'rack/cors'

gem 'jwt'
gem 'logglier'

# Access an IRB console on exception pages or by using <%= console %> in views
gem 'web-console', group: :development

group :development, :test do
  # Call 'byebug' anywhere in the code to stop execution and get a debugger console
  gem 'byebug'

  # Spring speeds up development by keeping your application running in the background.
  gem 'spring'
  gem 'spring-commands-rspec'

  # Metrics
  gem 'metric_fu'

  # HTTP mock libraries
  gem 'webmock', require: false

  gem 'annotate'
end

group :test do
  # RSpec, factory and data cleanup
  gem 'rspec-rails'
  gem 'factory_girl_rails'
  gem 'database_cleaner'

  # Code coverage
  gem 'simplecov', require: false
end

Gemfile.lock

GEM
  remote: https://rubygems.org/
  specs:
    abstract_type (0.0.7)
    actionmailer (4.2.7.1)
      actionpack (= 4.2.7.1)
      actionview (= 4.2.7.1)
      activejob (= 4.2.7.1)
      mail (~> 2.5, >= 2.5.4)
      rails-dom-testing (~> 1.0, >= 1.0.5)
    actionpack (4.2.7.1)
      actionview (= 4.2.7.1)
      activesupport (= 4.2.7.1)
      rack (~> 1.6)
      rack-test (~> 0.6.2)
      rails-dom-testing (~> 1.0, >= 1.0.5)
      rails-html-sanitizer (~> 1.0, >= 1.0.2)
    actionview (4.2.7.1)
      activesupport (= 4.2.7.1)
      builder (~> 3.1)
      erubis (~> 2.7.0)
      rails-dom-testing (~> 1.0, >= 1.0.5)
      rails-html-sanitizer (~> 1.0, >= 1.0.2)
    active_model-errors_details (1.3.1)
      activemodel (>= 3.2.13, < 5.0.0)
      activesupport
    active_model_serializers (0.10.5)
      actionpack (>= 4.1, < 6)
      activemodel (>= 4.1, < 6)
      case_transform (>= 0.2)
      jsonapi-renderer (>= 0.1.1.beta1, < 0.2)
    activejob (4.2.7.1)
      activesupport (= 4.2.7.1)
      globalid (>= 0.3.0)
    activemodel (4.2.7.1)
      activesupport (= 4.2.7.1)
      builder (~> 3.1)
    activerecord (4.2.7.1)
      activemodel (= 4.2.7.1)
      activesupport (= 4.2.7.1)
      arel (~> 6.0)
    activesupport (4.2.7.1)
      i18n (~> 0.7)
      json (~> 1.7, >= 1.7.7)
      minitest (~> 5.1)
      thread_safe (~> 0.3, >= 0.3.4)
      tzinfo (~> 1.1)
    adamantium (0.2.0)
      ice_nine (~> 0.11.0)
      memoizable (~> 0.4.0)
    addressable (2.5.0)
      public_suffix (~> 2.0, >= 2.0.2)
    annotate (2.7.1)
      activerecord (>= 3.2, < 6.0)
      rake (>= 10.4, < 12.0)
    apipie-rails (0.3.7)
      json
    arel (6.0.4)
    arrayfields (4.9.2)
    ast (2.3.0)
    bcrypt (3.1.11)
    binding_of_caller (0.7.2)
      debug_inspector (>= 0.0.1)
    builder (3.2.3)
    byebug (9.0.6)
    cane (2.6.2)
      parallel
    case_transform (0.2)
      activesupport
    chronic (0.10.2)
    churn (0.0.35)
      chronic (>= 0.2.3)
      hirb
      json_pure
      main
      rest-client (>= 1.6.0)
      ruby_parser (~> 3.0)
      sexp_processor (~> 4.1)
    code_analyzer (0.4.7)
      sexp_processor
    code_metrics (0.1.3)
    coderay (1.1.1)
    concord (0.1.5)
      adamantium (~> 0.2.0)
      equalizer (~> 0.0.9)
    concurrent-ruby (1.0.4)
    connection_pool (2.2.1)
    crack (0.4.3)
      safe_yaml (~> 1.0.0)
    dalli (2.7.6)
    dalli-elasticache (0.2.0)
      dalli (>= 1.0.0)
    database_cleaner (1.5.3)
    debug_inspector (0.0.2)
    diff-lcs (1.2.5)
    docile (1.1.5)
    domain_name (0.5.20161129)
      unf (>= 0.0.5, < 1.0.0)
    dotenv (1.0.2)
    dotenv-deployment (0.3.0)
      dotenv (~> 1.0)
    equalizer (0.0.11)
    erubis (2.7.0)
    factory_girl (4.8.0)
      activesupport (>= 3.0.0)
    factory_girl_rails (4.8.0)
      factory_girl (~> 4.8.0)
      railties (>= 3.0.0)
    fattr (2.3.0)
    flay (2.8.1)
      erubis (~> 2.7.0)
      path_expander (~> 1.0)
      ruby_parser (~> 3.0)
      sexp_processor (~> 4.0)
    flog (4.4.0)
      path_expander (~> 1.0)
      ruby_parser (~> 3.1, > 3.1.0)
      sexp_processor (~> 4.4)
    foreman (0.82.0)
      thor (~> 0.19.1)
    globalid (0.3.7)
      activesupport (>= 4.1.0)
    hashdiff (0.3.2)
    hirb (0.7.3)
    hiredis (0.6.1)
    http-cookie (1.0.3)
      domain_name (~> 0.5)
    i18n (0.7.0)
    ice_nine (0.11.2)
    jbuilder (2.6.1)
      activesupport (>= 3.0.0, < 5.1)
      multi_json (~> 1.2)
    json (1.8.6)
    json_pure (2.0.3)
    jsonapi-renderer (0.1.2)
    jwt (1.5.6)
    kaminari (1.0.0)
      activesupport (>= 4.1.0)
      kaminari-actionview (= 1.0.0)
      kaminari-activerecord (= 1.0.0)
      kaminari-core (= 1.0.0)
    kaminari-actionview (1.0.0)
      actionview
      kaminari-core (= 1.0.0)
    kaminari-activerecord (1.0.0)
      activerecord
      kaminari-core (= 1.0.0)
    kaminari-core (1.0.0)
    kgio (2.11.0)
    launchy (2.4.3)
      addressable (~> 2.3)
    logglier (0.5.0)
      multi_json (~> 1)
    loofah (2.0.3)
      nokogiri (>= 1.5.9)
    mail (2.6.4)
      mime-types (>= 1.16, < 4)
    main (6.2.1)
      arrayfields (~> 4.7, >= 4.7.4)
      chronic (~> 0.6, >= 0.6.2)
      fattr (~> 2.2, >= 2.2.0)
      map (~> 6.1, >= 6.1.0)
    map (6.6.0)
    maruku (0.7.2)
    memoizable (0.4.2)
      thread_safe (~> 0.3, >= 0.3.1)
    metric_fu (4.12.0)
      cane (~> 2.5, >= 2.5.2)
      churn (~> 0.0.35)
      code_metrics (~> 0.1)
      coderay
      flay (~> 2.1, >= 2.0.1)
      flog (~> 4.1, >= 4.1.1)
      launchy (~> 2.0)
      metric_fu-Saikuro (~> 1.1, >= 1.1.3)
      multi_json
      rails_best_practices (~> 1.14, >= 1.14.3)
      redcard
      reek (>= 1.3.4, < 3.0)
      roodi (~> 3.1)
    metric_fu-Saikuro (1.1.3)
    mime-types (3.1)
      mime-types-data (~> 3.2015)
    mime-types-data (3.2016.0521)
    mini_portile2 (2.1.0)
    minitest (5.10.1)
    multi_json (1.12.1)
    mysql2 (0.4.5)
    netrc (0.11.0)
    newrelic_rpm (3.17.2.327)
    nokogiri (1.7.0.1)
      mini_portile2 (~> 2.1.0)
    parallel (1.10.0)
    parser (2.3.3.1)
      ast (~> 2.2)
    path_expander (1.0.1)
    procto (0.0.3)
    public_suffix (2.0.5)
    puma (3.6.2)
    rack (1.6.5)
    rack-cors (0.4.0)
    rack-test (0.6.3)
      rack (>= 1.0)
    rails (4.2.7.1)
      actionmailer (= 4.2.7.1)
      actionpack (= 4.2.7.1)
      actionview (= 4.2.7.1)
      activejob (= 4.2.7.1)
      activemodel (= 4.2.7.1)
      activerecord (= 4.2.7.1)
      activesupport (= 4.2.7.1)
      bundler (>= 1.3.0, < 2.0)
      railties (= 4.2.7.1)
      sprockets-rails
    rails-deprecated_sanitizer (1.0.3)
      activesupport (>= 4.2.0.alpha)
    rails-dom-testing (1.0.8)
      activesupport (>= 4.2.0.beta, < 5.0)
      nokogiri (~> 1.6)
      rails-deprecated_sanitizer (>= 1.0.1)
    rails-html-sanitizer (1.0.3)
      loofah (~> 2.0)
    rails_12factor (0.0.3)
      rails_serve_static_assets
      rails_stdout_logging
    rails_best_practices (1.17.0)
      activesupport
      code_analyzer (>= 0.4.3)
      erubis
      i18n
      json
      require_all
      ruby-progressbar
    rails_serve_static_assets (0.0.5)
    rails_stdout_logging (0.0.5)
    railties (4.2.7.1)
      actionpack (= 4.2.7.1)
      activesupport (= 4.2.7.1)
      rake (>= 0.8.7)
      thor (>= 0.18.1, < 2.0)
    rainbow (2.2.1)
    rake (11.3.0)
    redcard (1.1.0)
    redis (3.3.2)
    redis-actionpack (5.0.1)
      actionpack (>= 4.0, < 6)
      redis-rack (>= 1, < 3)
      redis-store (>= 1.1.0, < 1.4.0)
    redis-activesupport (5.0.1)
      activesupport (>= 3, < 6)
      redis-store (~> 1.2.0)
    redis-rack (1.6.0)
      rack (~> 1.5)
      redis-store (~> 1.2.0)
    redis-rails (5.0.1)
      redis-actionpack (~> 5.0.0)
      redis-activesupport (~> 5.0.0)
      redis-store (~> 1.2.0)
    redis-store (1.2.0)
      redis (>= 2.2)
    reek (2.2.1)
      parser (~> 2.2)
      rainbow (~> 2.0)
      unparser (~> 0.2.2)
    require_all (1.4.0)
    responders (2.3.0)
      railties (>= 4.2.0, < 5.1)
    rest-client (2.0.0)
      http-cookie (>= 1.0.2, < 2.0)
      mime-types (>= 1.16, < 4.0)
      netrc (~> 0.8)
    roodi (3.3.1)
      ruby_parser (~> 3.2, >= 3.2.2)
    rsolr (1.1.2)
      builder (>= 2.1.2)
    rspec-core (3.5.4)
      rspec-support (~> 3.5.0)
    rspec-expectations (3.5.0)
      diff-lcs (>= 1.2.0, < 2.0)
      rspec-support (~> 3.5.0)
    rspec-mocks (3.5.0)
      diff-lcs (>= 1.2.0, < 2.0)
      rspec-support (~> 3.5.0)
    rspec-rails (3.5.2)
      actionpack (>= 3.0)
      activesupport (>= 3.0)
      railties (>= 3.0)
      rspec-core (~> 3.5.0)
      rspec-expectations (~> 3.5.0)
      rspec-mocks (~> 3.5.0)
      rspec-support (~> 3.5.0)
    rspec-support (3.5.0)
    ruby-progressbar (1.8.1)
    ruby_parser (3.8.3)
      sexp_processor (~> 4.1)
    safe_yaml (1.0.4)
    sexp_processor (4.7.0)
    simplecov (0.12.0)
      docile (~> 1.1.0)
      json (>= 1.8, < 3)
      simplecov-html (~> 0.10.0)
    simplecov-html (0.10.0)
    spring (2.0.0)
      activesupport (>= 4.2)
    spring-commands-rspec (1.0.4)
      spring (>= 0.9.1)
    sprockets (3.7.1)
      concurrent-ruby (~> 1.0)
      rack (> 1, < 3)
    sprockets-rails (3.2.0)
      actionpack (>= 4.0)
      activesupport (>= 4.0)
      sprockets (>= 3.0.0)
    thor (0.19.4)
    thread_safe (0.3.5)
    tzinfo (1.2.2)
      thread_safe (~> 0.1)
    unf (0.1.4)
      unf_ext
    unf_ext (0.0.7.2)
    unparser (0.2.5)
      abstract_type (~> 0.0.7)
      adamantium (~> 0.2.0)
      concord (~> 0.1.5)
      diff-lcs (~> 1.2.5)
      equalizer (~> 0.0.9)
      parser (~> 2.3.0)
      procto (~> 0.0.2)
    web-console (2.3.0)
      activemodel (>= 4.0)
      binding_of_caller (>= 0.7.2)
      railties (>= 4.0)
      sprockets-rails (>= 2.0, < 4.0)
    webmock (2.3.2)
      addressable (>= 2.3.6)
      crack (>= 0.3.2)
      hashdiff

PLATFORMS
  ruby

DEPENDENCIES
  active_model-errors_details
  active_model_serializers (~> 0.10.0)
  annotate
  apipie-rails
  bcrypt
  byebug
  connection_pool
  dalli
  dalli-elasticache
  database_cleaner
  dotenv-deployment
  factory_girl_rails
  foreman
  hiredis
  jbuilder (~> 2.0)
  jwt
  kaminari
  kgio
  logglier
  maruku
  metric_fu
  mysql2
  newrelic_rpm
  puma
  rack-cors
  rails (~> 4.2.0)
  rails_12factor
  redis
  redis-rails
  responders
  rsolr
  rspec-rails
  simplecov
  spring
  spring-commands-rspec
  web-console
  webmock

api_responder.rb

class ApiResponder < ActionController::Responder
  include Responders::HttpCacheResponder

  protected

    def default_render
      byebug
      @default_response ? @default_response.call(options) : controller.default_render(options.merge(format => resource))
    end

    def api_location
      nil
    end

    def display_errors
      byebug
      controller.render(options.merge({
        format => resource,
        status: options[:error_status] || :unprocessable_entity,
        serializer: ErrorsSerializer,
        root: :errors
      }))
    end
end

errors_controller.rb

require "api_responder"

class ErrorsController < ApplicationController
  self.responder = ApiResponder
  respond_to :json

  def show
    respond_with({}, serializer: ErrorsSerializer, status: params[:error_code].to_i, location: nil, root: :errors) do |format|
      format.any { render json: {}, serializer: ErrorsSerializer, status: params[:error_code].to_i }
    end
  end
end

errors_serializer.rb

class ErrorsSerializer < ActiveModel::Serializer
  attributes :code, :message, :details

  def code
    Rack::Utils.status_code(error_status)
  end

  def message
    I18n.t("errors.messages.#{error_status}", default: Rack::Utils::HTTP_STATUS_CODES[code])
  end

  def details
    object.respond_to?(:errors) ? object.errors.details.as_json : {}
  end

  protected

    def error_status
      instance_options[:error_status] || instance_options[:status] || 500
    end
end

config/initializers/active_model_serializer.rb

ActiveModel::Serializer.config.adapter = :json

And I have this line on my routes file:

  with_options defaults: { format: :json } do
    match '/:error_code' => 'errors#show', error_code: /(400|401|403|404|406|422|500)/, via: :all
  end
cassidycodes commented 7 years ago

You might want to have a look at the docs on the Root key: https://github.com/rails-api/active_model_serializers/blob/0-10-stable/docs/general/serializers.md#root I believe you're getting this error because the JSON adapter is trying to add a root key based on the model name, which in your case is just a hash.

ramonlg commented 7 years ago

This solved the problem. Thank you.

mashara-dev commented 4 years ago

so how do you solve this? @ramonlg