2013-05-01 5 views
12

Ho riscontrato un problema con la limitazione del livello di associazioni serializzate all'interno di una risorsa modello attiva.Limitazione delle associazioni Cascata nel serial serial modello attivo

Ad esempio:

Un gioco ha molte squadre che ha molti giocatori

class GameSerializer < ActiveModel::Serializer 
    attributes :id 
    has_many :teams 
end 

class TeamSerializer < ActiveModel::Serializer 
    attributes :id 
    has_many :players 
end 

class PlayerSerializer < ActiveModel::Serializer 
    attributes :id, :name 
end 

Quando ho recuperare il JSON per la squadra, che include tutti i giocatori in un sub-array, se lo desideri.

Quando richiamo il JSON per il gioco, include tutti i team in un sotto array, eccellente, ma anche tutti i giocatori per ogni squadra. Questo è il comportamento previsto, ma è possibile limitare il livello delle associazioni? Il gioco ha solo restituito i team serializzati senza i giocatori?

risposta

12

Un'altra opzione è quella di abusare Rails' ansioso caricamento per determinare le associazioni da rinominare der:

nel controller rotaie:

def show 
    @post = Post.includes(:comments).find(params[:id]) 
    render json: @post 
end 

poi nella terra di AMS:

class PostSerializer < ActiveModel::Serializer 
    attributes :id, :title 
    has_many :comments, embed: :id, serializer: CommentSerializer, include: true 

    def include_comments? 
    # would include because the association is hydrated 
    object.association(:comments).loaded? 
    end 
end 
non

Probabilmente la soluzione più pulita, ma funziona bene per me!

+0

'object.association (: comments) .loaded?' Questo è esattamente quello che stavo cercando, grazie! Penso che questo metodo sia più pulito della risposta accettata. Dai documenti active_model_serializer si consiglia di includere le associazioni utilizzando un join o include nel controller per evitare le query n + 1. Dove ero stumped era nel serializzatore come determinare se un'associazione è stata caricata o per ometterla. Dai documenti: "cerca di evitare le query n + 1 assicurando che i dati vengano caricati in modo ottimale, ad esempio se stai usando ActiveRecord, potresti voler utilizzare query include o joins come necessario" – Mark

+2

Dove devo chiamare the include_comments? metodo? – Kaspar

8

È possibile creare un altro Serializer:

class ShortTeamSerializer < ActiveModel::Serializer 
    attributes :id 
end 

Poi:

class GameSerializer < ActiveModel::Serializer 
    attributes :id 
    has_many :teams, serializer: ShortTeamSerializer 
end 

Oppure si può definire un include_teams? in GameSerializer:

class GameSerializer < ActiveModel::Serializer 
    attributes :id 
    has_many :teams 

    def include_teams? 
    @options[:include_teams] 
    end 
end 
+0

Grazie Pablo, questo è quello che ho finito per fare ... Ho provato a renderlo un po 'rails-y, modellando: index e: mostra la pluralizzazione ma avendo un 'TeamsSerializer' e' TeamSerializer'. Casi speciali ricevono un serializzatore diverso. –

+4

Da dove proviene @options? – Samnang