Search code examples
ruby-on-railsrubyrubygemsruby-on-rails-5ruby-on-rails-5.2

Rails API route Resources wrong response


I have a Ruby on Rails 5.2.4 running on Ruby 2.6.6. The frontend expects that the data returned by the backend is a JSON structured on: "resources" (if there is a list of data) or "recource" if there is only one data.

The app was created for Rails 5.0 and I made some updates so it will work well on Rails 5.2 also. Maybe I missed something.

The routes.rb looks like:

resources :route_a, only: [:index, :show]
resources :route_b, only: [:index]
resources :route_c, only: [:create]
resource  :route_d, only: [:create, :update, :destroy]
...
resources :route_e, only: [] do
  resource :route_f, only: [] do
    post 'route_g', on: :member
  end
end

The frontend Javascript framework expects the returned data to contain a "resources" or "resource" key. But in 80% of cases the data doesn't return the resources/resource structured JSON. What is wrong with Rails? Is this issue related to a gem, to the database? Why for some routes the response is returned in a resources/resource structured data and for other routes the plain JSON is returned?

Instad of a response such as:

[{"id":33,"type":"M..

I need to have:

[{"resources":{"id":33,"type":"M...

I'm new to Rails, sorry for probably asking basic things, but I don't know what's the issue here. Thank you.

Important

I have a file: config/initializers/wrap_parameters.rb that contains:

# Enable parameter wrapping for JSON. You can disable this by setting :format to an empty array.
ActiveSupport.on_load(:action_controller) do
  wrap_parameters format: [:json]
end

# To enable root element in JSON for ActiveRecord objects.
# ActiveSupport.on_load(:active_record) do
#   self.include_root_in_json = true
# end

Important 2

This is the /api/integrations page controller:

class IntegrationsController < ApiController

def index
    integrations = policy_scope(Integration)
    integrations = integrations.where(type: params[:type_eq]) if params[:type_eq]
    render_resources integrations, ransack_query: params[:q]
  end
end

The api/integrations response is:

[{"id":254,"name":"Integration 1"...

The result doesn't contain any resources key inside. I described the render_resources method below:

def render_resources(resources, options = {})
    options[:pagination] = true if options[:pagination].nil?
    pagination = options.delete(:pagination)
    ransack_query = options.delete(:ransack_query) || {}
    ransack_sort = options.delete(:ransack_sort) || params[:sort]

    resources = resources.ransack(ransack_query.to_hash.merge(s: ransack_sort)).result if ransack_sort || ransack_query.any?

    total = resources.respond_to?(:total_count) ? resources.total_count : resources.length
    default = {root: :resources, meta: {total: total}}
    results = pagination ? resources.page(params[:page]).per(params[:per_page]) : resources
    results = results.includes(options[:includes]) if options[:includes]
    render({json: results}.merge(default).merge(options))
  end

Since this method doesn't return anymore the response containing a resources key, am I right to say that it's because of the implied libraries - Ransack and Pagination? Because up until I updated ruby and rails gems, the functionality worked as expected. Still, I don't know what is the library that should structure the response's JSON data in a resources or resource key.


Solution

  • If you went straight from rails 5.0 to 5.2 you might have skipped fixing some deprecation warnings present in 5.1. Same situation with ruby upgrades - unless you have vast test coverage and everything works fine - it's better to go one minor (5.0->5.1->5.2) version at a time.

    Also during rails upgrade other gems are also upgraded, each new version of each gem might have some breaking changes (or new bugs)

    If you're using active_model_serializers - you might have effects from their changes to default adapter (now it's json_api) and other movement around root option, see changelog for 0.10 and previous changelogs depending on version you're upgrading from