Question Chargement latéral conditionnel avec ActiveModel :: Serializers


Je construis une API en utilisant ActiveModel :: Serializers. Quelle est la meilleure façon de charger les données de manière conditionnelle à l'aide de paramètres?

Je peux donc faire des demandes comme GET /api/customers:

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

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

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

Quelque chose comme ça en fonction des paramètres. Je sais que ActiveModel :: Serializers a le include_[ASSOCIATION]? syntaxe, mais comment puis-je l'utiliser efficacement à partir de mes contrôleurs?


Ceci est ma solution actuelle, mais ce n'est pas soigné:

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

Doit être un moyen plus facile?


17
2017-07-20 17:58


origine


Réponses:


Je cherche également une manière efficace et propre de le faire.

J'ai trouvé une solution mais ce n'est pas joli.

Dans mon BaseController / ApplicationController, j'ai ajouté cette méthode:

serialization_scope :params

Donc, la portée est maintenant les paramètres Hash et je peux l'utiliser dans le include_[ASSOCIATION]? méthodes de mes sérialiseurs.

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

Je n'aime pas cette méthode parce que si j'ai besoin d'utiliser la portée de quelque chose comme le current_user pour renvoyer conditionnellement des données si c'est un administrateur par exemple.

Mais cette solution peut fonctionner dans certains cas.

METTRE À JOUR

Tu peux passer view_context au lieu de passer directement le params.

Et vous pouvez déléguer dans votre sérialiseur pour garder le params nom au lieu de scope.

dans votre ApplicationController:

serialization_scope :view_context

dans votre sérialiseur:

delegate :params, to: :scope

Et voila, vous pouvez utiliser params [: incorporer] dans le include_[ASSOCIATION]? méthodes de vos sérialiseurs.


8
2017-07-23 16:53



J'ai encore une autre solution basée sur vos réponses parce que je voulais des fonctionnalités similaires. Selon la documentation, si l’on veut un contrôle de niveau inférieur de la sérialisation des associations, ils peuvent remplacer include_associations!.

Par exemple:

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

2
2017-11-14 01:19



Très utile de connaître include_associations !, merci! Notant qu’avec la gem active_model_serializers (version 0.8.3) vous pouvez utiliser @options définir le contexte dans le contrôleur. Par exemple, si dans le contrôleur vous appelez

render json: customer, include_addresses: true

puis dans CustomerSerializer:

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

les adresses seront alors sérialisées. Si vous rendez avec include_addresses mis à false, ils ne le seront pas. Avec les nouvelles versions de active_model_serializers, utilisez serialization_options plutôt que @options.


1
2018-03-01 18:04