Wie rendern Sie in Rails JSON mithilfe einer Ansicht?

125

Angenommen, Sie befinden sich in Ihrem Benutzer-Controller und möchten eine JSON-Antwort für eine Show-Anfrage erhalten. Es wäre schön, wenn Sie eine Datei in Ihren Ansichten / Benutzern / Verzeichnis mit dem Namen show.json und nach Ihren Benutzern # show erstellen könnten Wenn die Aktion abgeschlossen ist, wird die Datei gerendert.

Derzeit müssen Sie Folgendes tun:

def show
  @user = User.find( params[:id] )
  respond_to do |format|
    format.html
    format.json{
      render :json => @user.to_json
    }
  end
end

Aber es wäre schön, wenn Sie einfach eine show.json-Datei erstellen könnten, die automatisch so gerendert wird:

def show
  @user = User.find( params[:id] )
  respond_to do |format|
    format.html
    format.json
  end
end

Dies würde mir jede Menge Kummer ersparen und das schrecklich schmutzige Gefühl wegwaschen, das ich bekomme, wenn ich meinen JSON im Controller rendere

Matthew
quelle
Wenn ich mir diesen Beitrag jetzt ansehe, sieht es so aus, als würde mich das nicht viel retten, aber ich habe kompliziertere Fälle. Vertrauen Sie mir, wenn ich sage, dass dies mir Kopfschmerzen bereitet
Matthew
1
In Rails 3 können Sie einfach format.jsonmit einer show.json.erbDatei aufrufen . Siehe meine Antwort.
James Lim

Antworten:

64

Sie sollten in Ihrem respond_toBlock in der Lage sein, Folgendes zu tun :

respond_to do |format|
    format.json 
    render :partial => "users/show.json"
end

Dadurch wird die Vorlage in gerendert app/views/users/_show.json.erb.

Alex Reisner
quelle
5
Das ist gut, aber Sie werden schnell feststellen, dass erb ein schmerzhafter Weg ist, um json zu generieren. Schauen Sie sich meine Antwort für einige Alternativen an.
tybro0103
1
Gibt es eine Möglichkeit, dies ohne Verwendung eines Teils zu tun?
Wylliam Judd
55

Versuchen Sie, eine Ansicht hinzuzufügen. users/show.json.erbDiese sollte gerendert werden, wenn Sie eine Anfrage für das JSON-Format stellen, und Sie erhalten den zusätzlichen Vorteil, dass es auch von erb gerendert wird, sodass Ihre Datei ungefähr so ​​aussehen könnte

{
    "first_name": "<%= @user.first_name.to_json %>",
    "last_name": "<%= @user.last_name.to_json %>"
}
erik
quelle
9
Vielleicht möchten Sie @user.first_name.to_jsonstatt verwenden escape_javascript. Es gibt einige subtile Unterschiede zwischen dem, was JS erlaubt und dem, was streng JSON ist. (Und diese Unterschiede werden immer wichtiger, wenn Browser ihre eigenen JSON-Parser implementieren.)
James A. Rosen
1
Sie sollten die einfachen Anführungszeichen wahrscheinlich in doppelte Anführungszeichen ändern, da JSON (im Gegensatz zu JS) nur Zeichenfolgen in doppelten Anführungszeichen akzeptiert.
Abe Voelker
1
Das ist gut, aber Sie werden schnell feststellen, dass erb ein schmerzhafter Weg ist, um json zu generieren. Schauen Sie sich meine Antwort für einige Alternativen an.
tybro0103
Ich weiß, dass dies eine alte Antwort ist, aber es ist völlig falsch. to_json gibt bereits eine formatierte json-Zeichenfolge "" zurück, sodass der resultierende json niemals mit zusätzlichen Anführungszeichen ("" value "") gültig ist. Wenn der Vorname des Benutzers Null ist, hat der resultierende JSON die Zeichenfolge "null" als Wert. Außerdem verwendet <% = HTML-Escapezeichen, wodurch HTML-Zeichen in den Eingabedaten entstellt werden.
d4n3
Ich denke, Sie müssen auch Anführungszeichen entfernen, <%= xyz.to_json %>sonst bleiben Ihnen zusätzliche Anführungszeichen.
Akostadinov
32

Wie andere bereits erwähnt haben, benötigen Sie eine Benutzer- / show.json-Ansicht, es gibt jedoch Optionen, die für die Vorlagensprache berücksichtigt werden müssen ...

ERB

Funktioniert sofort. Großartig für HTML, aber Sie werden schnell feststellen, dass es für JSON schrecklich ist.

RABL

Gute Lösung. Müssen eine Abhängigkeit hinzufügen und ihre DSL lernen.

JSON Builder

Gleiches Angebot wie RABL: Gute Lösung. Müssen eine Abhängigkeit hinzufügen und ihre DSL lernen.

Einfacher Rubin

Ruby ist großartig darin, JSON zu generieren, und es gibt nichts Neues zu lernen, da Sie to_jsoneinen Hash oder ein AR-Objekt aufrufen können . Registrieren Sie einfach die Erweiterung .rb für Vorlagen (in einem Initialisierer):

ActionView::Template.register_template_handler(:rb, :source.to_proc)

Erstellen Sie dann die Ansicht users / show.json.rb:

@user.to_json

Weitere Informationen zu diesem Ansatz finden Sie unter http://railscasts.com/episodes/379-template-handlers

tybro0103
quelle
7
Beachten Sie, dass in Rails 4 der .ruby-Vorlagenhandler standardmäßig unter github.com/rails/rails/commit/de1060f4e02925c12004f2 registriert ist, sodass Sie die Registrierung von .rb überspringen und Ihre Datei users / show.json.ruby benennen können.
Tim Diggins
1
Um dies weiter zu aktualisieren, wurde json_builder von github.com/rails/jbuilder abgelöst .
Tim Diggins
27

RABL ist wahrscheinlich die schönste Lösung dafür, die ich gesehen habe, wenn Sie nach einer saubereren Alternative zur ERb-Syntax suchen. json_builder und argonaut, die andere Lösungen sind, scheinen beide etwas veraltet zu sein und funktionieren ohne Patches nicht mit Rails 3.1.

RABL ist über ein Juwel erhältlich oder Sie können das GitHub-Repository überprüfen. gute Beispiele auch

https://github.com/nesquena/rabl

zapnap
quelle
21

Nur um diese Antwort für andere zu aktualisieren, die zufällig auf dieser Seite landen.

In Rails 3 müssen Sie nur eine Datei unter erstellen views/users/show.json.erb. Das @userObjekt steht der Ansicht zur Verfügung (genau wie bei HTML). Sie benötigen es nicht einmal to_jsonmehr.

Zusammenfassend ist es nur

# users contoller
def show
  @user = User.find( params[:id] )
  respond_to do |format|
    format.html
    format.json
  end
end

und

/* views/users/show.json.erb */
{
    "name" : "<%= @user.name %>"
}
James Lim
quelle
1
Ich habe das vor 1,5 Jahren beantwortet. Heutzutage verwende ich reply_with nur, wenn ich JSON benötige, z respond_with @user, only: [:name]. Weitere Informationen finden Sie in diesem Tutorial .
James Lim
1
Nur um diese Antwort zu ergänzen, dies ist aus zwei Gründen tatsächlich gefährlich: Es ermöglicht das Einfügen von Benutzerdaten, da es keinen Zeilenumbrüchen und Backslashes entgeht, und <% = html entgeht den Daten, sodass beispielsweise Sean O'Connor seinen Namen hat verstümmelt an Sean O'Connor.
d4n3
10

Fügen Sie einfach eine show.json.erbDatei mit dem Inhalt hinzu

<%= @user.to_json %>

Manchmal ist es nützlich, wenn Sie einige zusätzliche Hilfsmethoden benötigen, die in Controller nicht verfügbar sind, dh image_path(@user.avatar)oder etwas, um zusätzliche Eigenschaften in JSON zu generieren:

<%= @user.attributes.merge(:avatar => image_path(@user.avatar)).to_json %>
Priit
quelle
8
Es müsste sein, um <%= raw(@user.to_json) %>zu vermeiden, dass HTML entweicht. Was ich tue, ist, dass ich mich auf to_json verlasse, solange es mir gibt, was ich will, aber wenn ich etwas anderes machen will, schablone ich es mit dem, was normalerweise a ist { :blah => @user.the_blah }.to_json.
Clacke
0

Ich bin neu bei RoR, das habe ich herausgefunden. Sie können ein JSON-Format direkt rendern

def YOUR_METHOD_HERE
  users = User.all
  render json: {allUsers: users} # ! rendering all users
END
aRtoo
quelle