Подтвердить что ты не робот

Боковой загрузкой условно с помощью ActiveModel:: Сериализаторы

Я создаю API с помощью ActiveModel:: Serializers. Каков наилучший способ изолировать данные условно с помощью параметров?

Поэтому я могу делать запросы типа GET /api/customers:

"customers": {
   "first_name": "Bill",
   "last_name": "Gates"
}

И GET /api/customers?embed=address,note

"customers": {
   "first_name": "Bill",
   "last_name": "Gates"
},
"address: {
   "street": "abc"
},
"note": {
   "body": "Banned"
}

Что-то вроде этого в зависимости от параметров. Я знаю, что ActiveModel:: Сериализаторы имеют синтаксис include_[ASSOCIATION]?, но как я могу эффективно использовать его с моих контроллеров?


Это мое текущее решение, но оно не опрятно:

customer_serializer.rb:

def include_address?
  !options[:embed].nil? && options[:embed].include?(:address)
end

application_controller.rb:

def embed_resources(resources = [])
  params[:embed].split(',').map { |x| resources << x.to_sym } if params[:embed]
  resources
end

customers_controller.rb:

def show
  respond_with @customer, embed: embed_resources
end

Должен быть более простой способ?

4b9b3361

Ответ 1

Я также ищу эффективный и чистый способ сделать это.

Я нашел решение, но это не очень.

В моем BaseController/ApplicationController я добавил этот метод:

serialization_scope :params

Итак, область теперь является параметром Hash, и я могу использовать ее в методах include_[ASSOCIATION]? моих сериализаторов.

def include_associations?
    if scope[:embed]
        embed = scope[:embed].split(',') 
        return true if embed.include?('associations')
    end
end

Мне не нравится этот метод, потому что если мне нужно использовать область для чего-то еще, как current_user, чтобы условно вернуть данные, если это админ, например.

Но это решение может работать в некоторых случаях.

UPDATE

Вы можете передать view_context вместо прямого прохождения params.

И вы можете делегировать в своем Сериализаторе имя params вместо scope.

в вашем приложении ApplicationController:

serialization_scope :view_context

в вашем сериализаторе:

delegate :params, to: :scope

И вы можете использовать params [: embed] в методах include_[ASSOCIATION]? ваших сериализаторов.

Ответ 2

У меня есть еще одно решение, основанное на ваших ответах, потому что мне нужна аналогичная функциональность. Согласно документации, если требуется более низкий уровень управления сериализацией ассоциаций, они могут переопределить include_associations!.

Например:

def include_associations!
    if scope[:embed]
        include! :addresses, {embed: :ids, include: true}
    else
        include! :addresses, {embed: :ids}
    end
end

Ответ 3

Очень полезно знать об include_associations!, спасибо! Отметив, что с помощью gem (active) версии_model_serializers (версия 0.8.3) вы можете использовать @options для установки контекста в контроллере. Например, если в контроллере вы вызываете

render json: customer, include_addresses: true

затем в CustomerSerializer:

has_many :addresses
def include_associations!
  if @options[:include_addresses]
    include! :addresses
  end
end

тогда адреса будут сериализованы. Если вы сделаете с include_addresses установленным на false, они не будут. С более новыми версиями active_model_serializers используйте serialization_options, а не @options.