2014-01-06 9 views
12

Sagen wir, ich habe ein Modell User und einen Serializer UserSerializer < ActiveModel::Serializer und einen Controller, der wie folgt aussieht:Aktives Modell Serializer: Hinzufügen zusätzlicher Informationen außerhalb Wurzel in ArraySerializer

class UsersController < ApplicationController 
    respond_to :json 
    def index 
    respond_with User.all 
    end 
end 

Jetzt bekomme ich ein, wenn ich Besuch /users JSON-Antwort, die wie folgt aussieht:

{ 
    "users": [ 
    { 
     "id": 7, 
     "name": "George" 
    }, 
    { 
     "id": 8, 
     "name": "Dave" 
    } 
    . 
    . 
    . 
    ] 
} 

Aber was, wenn ich einige zusätzliche Informationen in der JSON-Antwort enthalten sein soll, die nicht relevant einen bestimmten Nutzer ist? Zum Beispiel:

{ 
    "time": "2014-01-06 16:52 GMT", 
    "url": "http://www.example.com", 
    "noOfUsers": 2, 
    "users": [ 
    { 
     "id": 7, 
     "name": "George" 
    }, 
    { 
     "id": 8, 
     "name": "Dave" 
    } 
    . 
    . 
    . 
    ] 
} 

Dieses Beispiel ist erfunden, aber es ist eine gute Annäherung dessen, was ich erreichen möchte. Ist dies mit aktiven Modell-Serialisierern möglich? (Vielleicht durch Unterklassen ActiveModel::ArraySerializer? Ich konnte es nicht herausfinden). Wie füge ich zusätzliche Root-Elemente hinzu?

+1

Versuchen Sie, Render: Json => User.all Anstelle von respond_with, siehe auch as_json könnte es hilfreich sein. –

Antwort

4

Verstanden Arbeiten mit render:

render json: { 
    "time": "2014-01-06 16:52 GMT", 
    "url": "http://www.example.com", 
    "noOfUsers": 2, 
    "users": @users 
} 

Das Problem ist, bedeutet dies UserSerializer nicht nennen, es ruft nur .as_json auf jedem einzelnen Benutzerobjekt und überspringt den Serializer. Also musste ich es explizit machen:

def index 
    . 
    . 
    . 
    render json: { 
    "time": "2014-01-06 16:52 GMT", 
    "url": "http://www.example.com", 
    "noOfUsers": 2, 
    "users": serialized_users 
    } 
end 

def serialized_users 
    ActiveModel::ArraySerializer.new(@users).as_json 
end 

Nicht die eleganteste Lösung, aber es funktioniert.

9

Sie können sie als das zweite Argument übergeben

def index 
respond_with User.all, meta: {time: "2014-01-06 16:52 GMT",url: "http://www.example.com", noOfUsers: 2} 
end 

In der Version 0.9.3 in einer initializer auf respond_with ActiveModel::Serializer.root = true:

ActiveSupport.on_load(:active_model_serializers) do 
    # Disable for all serializers (except ArraySerializer) 
    ActiveModel::Serializer.root = true 
end 

In Controller

render json: @user, meta: { total: 10 } 
+2

Dies funktioniert nicht. – GMA

+0

Dies funktioniert bei ActiveModelSerializers 0.8.1. Siehe https://github.com/rails-api/active_model_serializers/blob/0-8-stable/lib/active_model/array_serializer.rb#L41. Offenbar hat sich dies im Master geändert, siehe https://github.com/rails-api/active_model_serializers/blob/78cceb4113c35cddb8cbef42742dc8a7f4cebbb8/lib/active_model/serializable.rb – aceofspades

+0

Beachten Sie auch, dass dies nur für Arrays gilt, wenn Sie Metadaten in einer Instanz haben möchten Setzen Sie den Aufruf '# meta =' auf der Serializer-Instanz selbst. – aceofspades

0

Nur ein einfaches Hack, wenn Sie nicht wollen, entweder die Serializer oder machen ändern:

data = serializer.new(object, root: false) 
# cannot modify data here since it is a serializer class 
data = data.as_json 
# do whatever to data as a Hash and pass the result for render 
data[:extra] = 'extra stuff' 
render json: data 
0

konnte ich bekommen diese Arbeit für meinen Anwendungsfall, indem einfach die folgenden in meinem Controller. Nichts anderes wird mit AMS 0.10 benötigt.

render 
    json: @user, 
    meta: { 
     time: "2014-01-06 16:52 GMT", 
     url: "http://www.example.com", 
     noOfUsers: 2 
    } 
Verwandte Themen