Получение приложения Rails 5 для возврата формата JSON API

Я пытаюсь заставить свое приложение возвращаться в нижнем регистре верблюда для возможного форматирования JSON API.

Я установил gem 'active_model_serializers' и создал новый инициализатор со следующим кодом:

ActiveModelSerializers.config.adapter = :json_api
ActiveModelSerializers.config.key_transform = :camel_lower

Затем у меня есть небольшой API, который возвращает json, как это делают все лучшие интернет-приложения:

class Api::V1::UsersController < API::V1::BaseController
  def sky
      @user = User.find_by_id(params[:user_id])

      if @user
          obj =  {
              sky: {
                  sectors: @user.sectors,
                  slots: @user.slots
              }
          }

          render json: obj
      else
          raise "Unable to get Sky"
      end
  end

Подробнее о шаблоне наследования контроллера API: class API::V1::BaseController < ActionController::Base

Проблема

В моем ответе API все по-прежнему запутано, и я вижу эту ошибку в консоли [active_model_serializers] Rendered ActiveModel::Serializer::Null, но мои исследования завели меня в тупик относительно того, что делать.

Любые предложения будут очень приветствоваться. Спасибо!


person Zack Shapiro    schedule 16.06.2017    source источник
comment
Это приложение rails, а не приложение rails-api, между прочим   -  person Zack Shapiro    schedule 17.06.2017


Ответы (4)


Проблема в том, что вы не вызываете активный сериализатор записей в своем контроллере, поэтому эти параметры конфигурации не используются.

Решение. Создайте UserSerializer в "app/serializers/user_serializer.rb", который должен выглядеть примерно так:

class UserSerializer < ActiveModel::Serializer
  attributes :id

  has_many :sectors
  has_many :slots
end

а также аналогично структурированные SectorSerializer и SlotSerializer со всеми атрибутами, которые вы хотите от каждого (вот документация по началу работы и документы по общему синтаксису для сериализаторов активных записей)

Затем в вашем контроллере:

class Api::V1::UsersController < API::V1::BaseController
  def sky
    @user = User.includes(:sectors, :slots).find_by_id(params[:user_id])

    if @user
      render json: @user
    else
      raise "Unable to get Sky"
    end
  end
end

Который будет загружать :slots и :sectors с includes, а затем вызывает ваш UserSerializer используя параметры конфигурации camel_case.

person George    schedule 22.06.2017
comment
Нет. Он все еще в верблюжьем корпусе. - person Zack Shapiro; 24.06.2017
comment
змеиный корпус, скорее - person Zack Shapiro; 24.06.2017
comment
@zack, какую версию сериализаторов активных моделей вы используете? - person George; 27.06.2017
comment
запустите bundle show | grep active_model_serializers, чтобы получить версию - person George; 27.06.2017
comment
Итак, прочитав еще немного, я не думаю, что сериализаторы активных моделей должны даже вызываться здесь. Кроме того, какие ключи не в верблюжьем корпусе? Судя по вашему примеру, это одно слово. - person George; 27.06.2017
comment
Я не думаю, что следует вызывать сериализаторы активных моделей, поскольку вы не вызываете render json: @an_instance_of_a_model и не вызываете сериализатор явно. Используете ли вы его где-нибудь в своем приложении? - person George; 27.06.2017
comment
Кроме того, какие ключи не в верблюжьем регистре? похоже, что все ваши ключи - это одно слово - person George; 27.06.2017
comment
@user.sectors — это массив из Sector объектов, таких же, как и @user.slots. Такие ключи, как user_id и sector_number, не имеют верблюжьего корпуса. - person Zack Shapiro; 27.06.2017
comment
у вас есть UserSerializer, определенный в app/serializers/user_serializer.rb? - person George; 27.06.2017
comment
Я не. Я не создавал сериализаторы - person Zack Shapiro; 28.06.2017
comment
@zack хорошо, это может быть проблемой - он может искать пользовательский сериализатор, а когда его нет, он просто выдает эту ошибку Rendered ActiveModel::Serializer::Null - person George; 28.06.2017
comment
@zack удачи? - person George; 28.06.2017
comment
Меня вчера затопило. Попробую сегодня днем. Спасибо за вашу помощь, Джордж, очень ценю это. Скоро отчитаюсь - person Zack Shapiro; 28.06.2017

В вашем контроллере поместите response_to :json

class Api::V1::UsersController < API::V1::BaseController

  respond_to :json

а в акции поставь то же что и у тебя

def sky
   ...      
   render json: obj
   ...       
end

и определить в базовом контроллере

protect_from_forgery with: :null_session, if: Proc.new { |c| c.request.format == 'application/json' }
person alehn96    schedule 24.06.2017
comment
Все еще в змеином корпусе - person Zack Shapiro; 24.06.2017

Из этого запроса на вытягивание (*) видно, что вы должны иметь возможность настроить key_format = :lower_camel в своей конфигурации ActiveModel::Serializers.

(*) https://github.com/rails-api/active_model_serializers/pull/534

person bratsche    schedule 19.06.2017

я думаю, это поможет вам. в моем случае я использую gem 'active_model_serializers', '~> 0.10.5', который зависит от case_transform (>= 0.2)

и в rails console я могу сделать

CaseTransform.camel_lower(initially_serialized_output)                                                       
=> {:name=>"My Company", :jsonThings=>{:rating=>8, :aKey=>{:aSubkey=>{:anotherKey=>"value"}}}}

мое исследование проводилось по шагам: https://github.com/rails-api/active_model_serializers/pull/1993 => https://github.com/NullVoxPopuli/case_transform-rust-extensions

ты нашел это?

person Alexey    schedule 24.06.2017
comment
Initial_serialized_output = {название: Моя компания, json_things: {рейтинг: 8, a_key: {a_subkey: {another_key: value} } } } - person Alexey; 25.06.2017