2017-02-15 4 views
2

Ich verwende Schienen (5.0.1) und active_model_serializers (0.10.2). Ich möchte irgendwie bedingt die has_many Verbände serialisiert:ActiveModel Serializer: has_many mit Bedingung zur Laufzeit?

class Question < ApplicationRecord 
    has_many :responses, :inverse_of => :question 
end 

class Response < ApplicationRecord 
    belongs_to :question, :inverse_of => :responses 
end 

class QuestionSerializer < ActiveModel::Serializer 
    attributes :id, :title, :created_at, :updated_at 
    has_many :responses 
end 

class ResponseSerializer < ActiveModel::Serializer 
    attributes :id, :title 
end 

Ich benutze jsonapi und Abfrage http://localhost:3000/api/questions/1 ich diese Antwort:

Antwort-1:

{ 
    "data": { 
    "id": "1", 
    "type": "questions", 
    "attributes": { 
     "title": "First", 
     "created-at": "2017-02-14T09:49:20.148Z", 
     "updated-at": "2017-02-14T13:55:37.365Z" 
    }, 
    "relationships": { 
     "responses": { 
     "data": [ 
      { 
      "id": "1", 
      "type": "responses" 
      } 
     ] 
     } 
    } 
    } 
} 

Wenn ich entfernen has_many :responses von QuestionSerializer ich diese:

Antwort-2:

{ 
    "data": { 
    "id": "1", 
    "type": "questions", 
    "attributes": { 
     "title": "First", 
     "created-at": "2017-02-14T09:49:20.148Z", 
     "updated-at": "2017-02-14T13:55:37.365Z" 
    } 
    } 
} 

Wie kann ich bedingt erhalten entweder Antwort-1 oder Antwort-2 zur Laufzeit? Ich habe alle gefundenen Empfehlungen ausprobiert - keiner arbeitet mit AMS 0.10.2. Derzeit arbeitet die Bedingung nur auf diese Weise:

class QuestionSerializer < ActiveModel::Serializer 
    attributes :id, :title, :created_at, :updated_at 
    has_many :responses if true 
end 

OR:

class QuestionSerializer < ActiveModel::Serializer 
    attributes :id, :title, :created_at, :updated_at 
    has_many :responses if false 
end 

In diesen zwei Fällen wirklich ich entweder Antwort-1 oder Antwort-2. Aber das ist hart codiert und ich möchte vielleicht einen Param in den Serialisierer einbringen oder ähnliches tun.

Was soll ich tun?

Antwort

2

Ich denke, Sie haben Ihre eigene Frage irgendwie beantwortet. Wenn Sie in das AMS documentation for associations schauen, heißt es, dass Bedingungen unterstützt werden.

Von dem, was ich sagen kann, du bist

class QuestionSerializer < ActiveModel::Serializer 
    has_many :responses, if: false 
end 

Die attributes Methode auch ein Tippfehler einfach weg unterstützt die if Option, wie here beschrieben.

Was ist Ihre active_model_serializers Version?

BEARBEITEN: Ich habe einen Fehler in meiner Antwort auch. Ich verwende active_model_serializers (0.10.3) und ich bin in der Lage

class QuestionSerializer < ActiveModel::Serializer 
    has_many :responses, if: -> { false } 
end 

Die if Option entweder mit Methoden, Procs oder Strings arbeitet zu tun. Ich denke, Sie können zur Laufzeit entscheiden, indem Sie eine Methode als bedingte bereitstellen.

class QuestionSerializer < ActiveModel::Serializer 
    attr_writer :should_render_association 
    has_many :responses, if: -> { should_render_association } 
end 
# Usage: 
serializer = QuestionSerializer.new(question) 
serializer.should_render_association = false 
serializer.to_json 
# => no "responses" key 
+0

Ich sah es in der Dokumentation. Ich benutze AMS 0.10.2. Sei überrascht - 'wenn:' Bedingung ** nicht funktioniert ** (!), Nur 'if' tut. Trotz der Dokumentation! Der Server sagt: 'Syntaxfehler, unerwartet ':''. Aber meine Frage war nicht darüber. – prograils

+0

Ich habe die Antwort aktualisiert, ich denke, es funktioniert. Tut mir leid, wenn ich etwas verpasse, ich dachte, der entscheidende Punkt wäre, ein Attribut bedingt zu rendern, aber zur Laufzeit zu entscheiden. – gkats

1

Dank @gkats fand ich eine Antwort (AMS 0.10.2):

class QuestionSerializer < ActiveModel::Serializer 
    attributes :id, :title, :created_at, :updated_at 
    has_many :responses, if: -> { should_render_association } 

    def should_render_association 
    @instance_options[:show_children] 
    end 
end 

class Api::ResponsesController < Api::ApplicationController 
    def show 
    render json: @response, show_children: param[:include_children] 
    end 
end 

Das Problem war, alles über die Syntax: if: in dem Serialisierer zu einem Block angewandt werden soll, anstatt auf eine Funktion.

Verwandte Themen