Боковой загрузкой условно с помощью 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
Должен быть более простой способ?
Ответы
Ответ 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
.