Rails + APIs = ♥

Mathis Hofer

Die im Juni dieses Jahres veröffentlichte Version 5.0 von Ruby on Rails beinhaltet einen sogenannten API Modus. Dieser macht das bewährte Web Framework zum perfekten Partner von Single-page Applications oder Mobile Apps.

Rails und REST sind alte Freunde. Schon mit der Version 1.2 (veröffentlicht im Januar 2007) wurde auf den heutigen de facto Standard für APIs gesetzt (siehe 10 Jahre Ruby on Rails @ Puzzle ITC). Mit einem Ressourcen-basierten Controller werden auch gleich REST-Clients bedient, wie das Beispiel aus dem damaligen Blogartikel demonstriert:

class WeblogController < ActionController::Base
  def index
    @posts = Post.find :all
    respond_to do |format|
      format.html
      format.xml { render :xml => @posts.to_xml }
      format.rss { render :action => "feed.rxml" }
    end
  end
end

Schöne neue Welt

Client-seitige JavaScript Frameworks oder native Apps verändern die Rolle des Backends. Dieses muss statt HTML nur JSON ausliefern. Das bedeutet, dass Funktionen wie Templates/Helpers, Cookies, Sessions, Flash, Assets etc. in diesem Context nicht benötigt werden.

Während ein Fullstack Rails Projekt wiefolgt aufgesetzt wird:

rails new blog

…kann nun mit der –api Option ein ausschliessliches API Projekt eingerichtet werden:

rails new blog --api

In diesem Modus erbt der ApplicationController vom ActionController::API, einer leichtgewichtigen Version des ActionController::Base. Weiter werden unnötige Middlewares weggelassen und die Generatoren erstellen keine Views, Helpers und Assets.

So sieht dann ein Controller aus, welcher nur JSON zurückliefert:

class PostsController < ApplicationController
  def index
    posts = Post.all
    render json: posts
  end
end

Es ist auch möglich bestehende Rails Projekte auf den API Modus zu wechseln.

JSON, do you speak it?

Standardmässig serialisiert Rails die Resultate mit der #to_json Methode der Models. Alternativ kann man auch Jbuilder, Active Model Serializers oder JSONAPI::Resources einsetzen. Bei Jbuilder handelt es sich um eine DSL zum Generieren von JSON Strukturen, JSONAPI::Resources ist eine umfassende Lösung für APIs die nach der JSON API Spezifikation gebaut werden.

Eine komfortable Variante für die JSON-Serialisierung sind die Active Model Serializers, welche über das Gem active_model_serializers installiert werden. Per Serializer, wird definiert welche Attribute und Assoziationen des Models wie gerendert werden, z.B. im File blog/app/serializers/post_serializer.rb:

class PostSerializer < ActiveModel::Serializer
  attributes :title, :text

  has_many :comments

  def title
    object.title.upcase
  end
end

Validierung

Ein Aspekt der auch bei REST APIs nicht in Vergessenheit geraten darf, ist die Server-seitige Validierung der Daten. Dazu werden die gewohnten Active Record Validierungen im Model definiert:

class Post < ApplicationRecord
  validates :title, presence: true,
                    length: { minimum: 5 }
end

Der Controller rendert die Fehlerdetails als JSON, falls die Validierung scheitert:

class PostsController < ApplicationController
  def create
    post = Post.new(post_params)

    if post.save
      render json: post
    else
      render json: post.errors.details,
             status: :unprocessable_entity
    end
  end
end

Die entsprechende Response kann im Client zur Anzeige einer internationalisierten Meldung verwendet werden. Die Fehlerdetails beinhalten sowohl das betroffene Attribut, als auch den Fehler mit möglichen Fehlerargumenten:

Status Code: 422 Unprocessable Entity

{
  "title": [
    {
      "error": "too_short",
      "count": 5
    }
  ]
}

Fazit

Ob für klassische Fullstack Web Applikationen (mit oder ohne Turbolinks) oder als reines API Backend mit dem nun integrierten API Modus – Rails ist eine verlässliche Wahl und aktueller denn je. Momentan setzen wir in einem Kundenprojekt als Beispiel API-only Rails 5.0 zusammen mit einem Angular 2 Frontend ein.

Wenn Du noch mehr zum neuen API Modus erfahren möchtest: in den Rails Guides kannst Du im Kapitel Using Rails for API-only Applications weitere Details darüber nachlesen.

2 Kommentare

  • mh, 8. September 2016

    Singe vs. Single

  • mm
    Nicole Pauli, 9. September 2016

    Vielen Dank!