Kurz: Das bekannteste Webframework ist Ruby on Rails (2004). Prinzipien: Konvention vor Konfiguration (sinnvolle Standardnamen statt langer Einstellungen) und DRY (Don’t Repeat Yourself). Rails bringt alles mit.
Teil des Kurses Ruby
Ruby im Web
Das bekannteste Webframework ist Ruby on Rails (2004). Prinzipien: Konvention vor Konfiguration (sinnvolle Standardnamen statt langer Einstellungen) und DRY (Don’t Repeat Yourself). Rails bringt alles mit: Routing, Datenbank (ActiveRecord), Templates, Mailer, Hintergrundjobs, Tests, Sicherheit.
Leichtere Alternativen: Sinatra (Mini-Framework), Hanami, Roda, Rack (die gemeinsame Schnittstelle).
Sinatra: ein Webserver in fünf Zeilen
require "sinatra"
require "json"
get "/" do
"Hallo Welt"
end
get "/gruss/:name" do
"Hallo, #{params[:name]}!"
end
post "/api/echo" do
content_type :json
daten = JSON.parse(request.body.read)
{ empfangen: daten }.to_json
endStart mit ruby app.rb, dann http://localhost:4567.
Rack: das Fundament
Jede Rack-App ist ein Objekt, das call(env) versteht und [status, header, body] liefert. Wir testen so eine App ohne Server:
class MiniApp
def call(env)
pfad = env["PATH_INFO"]
case pfad
when "/" then [200, { "content-type" => "text/plain" }, ["Startseite"]]
when %r{\A/nutzer/(\d+)\z} then [200, { "content-type" => "text/plain" }, ["Nutzer #{$1}"]]
else [404, { "content-type" => "text/plain" }, ["nicht gefunden"]]
end
end
end
app = MiniApp.new
["/", "/nutzer/42", "/gibtsnicht"].each do |pfad|
status, header, body = app.call("PATH_INFO" => pfad)
puts "#{pfad} -> #{status} #{header['content-type']} #{body.join}"
endAusgabe:
/ -> 200 text/plain Startseite
/nutzer/42 -> 200 text/plain Nutzer 42
/gibtsnicht -> 404 text/plain nicht gefundenRails im Überblick
gem install rails
rails new blog # Projekt anlegen
cd blog
rails generate scaffold Artikel titel:string text:text
rails db:migrate # Tabellen anlegen
rails server # http://localhost:3000
rails console # interaktiv mit der App arbeiten
rails test # TestsDie Struktur (MVC):
| Teil | Ordner | Aufgabe |
|---|---|---|
| Model | app/models | Daten und Geschäftslogik (ActiveRecord) |
| View | app/views | HTML-Templates (ERB) |
| Controller | app/controllers | Anfragen entgegennehmen, Antwort wählen |
| Routen | config/routes.rb | URL -> Controller |
| Migrationen | db/migrate | Datenbankschema |
# app/models/artikel.rb
class Artikel < ApplicationRecord
has_many :kommentare, dependent: :destroy
validates :titel, presence: true, length: { maximum: 120 }
scope :neueste, -> { order(created_at: :desc).limit(5) }
end
# app/controllers/artikel_controller.rb
class ArtikelController < ApplicationController
def index
@artikel = Artikel.neueste
end
def create
@artikel = Artikel.new(artikel_params)
if @artikel.save
redirect_to @artikel, notice: "Gespeichert"
else
render :new, status: :unprocessable_entity
end
end
private
def artikel_params = params.require(:artikel).permit(:titel, :text)
end
# config/routes.rb
Rails.application.routes.draw do
resources :artikel
root "artikel#index"
end<%# app/views/artikel/index.html.erb %>
<h1>Artikel</h1>
<% @artikel.each do |a| %>
<h2><%= link_to a.titel, a %></h2>
<p><%= truncate(a.text, length: 100) %></p>
<% end %><%= %> gibt aus (HTML wird automatisch escaped), <% %> führt nur aus.
ActiveRecord: Datenbank wie Ruby-Objekte
Artikel.create(titel: "Hallo", text: "Welt")
Artikel.find(1)
Artikel.where(titel: "Hallo").order(:created_at).first
Artikel.where("created_at > ?", 1.week.ago).count
artikel.update(titel: "Neu")
artikel.destroy
Artikel.includes(:kommentare).each { |a| a.kommentare.size } # N+1-Problem vermeidenWeitere Einsatzgebiete
| Bereich | Werkzeug |
|---|---|
| Hintergrundjobs | Sidekiq, GoodJob, Solid Queue |
| Automatisierung | Rake, Thor (CLIs), Chef/Puppet |
| Static Sites | Jekyll, Middleman, Bridgetown |
| Tests/QA | RSpec, Capybara, Cucumber |
| Spiele/Grafik | Gosu, Ruby2D |
| Skripting | eingebettet (z. B. in Metasploit, Homebrew) |
Performance und Betrieb
- Ruby 3 ist deutlich schneller als 2.x (YJIT-Compiler:
ruby --yjit) - Nebenläufigkeit: Threads (mit GVL),
Ractor,Fiberund derasync-Gem - Deployment: Puma als Server, Docker, Kamal, Heroku, Render, Fly.io
Merke
- Rails: MVC, Konvention vor Konfiguration, ActiveRecord, Migrationen
- Sinatra/Rack für schlanke Dienste
rails new,generate,db:migrate,server,console,test- N+1-Abfragen mit
includesvermeiden
Übungsaufgabe
Skizziere in Worten die Rails-Modelle für ein Blog (Artikel, Kommentare, Nutzer) und ihre Beziehungen.
Quiz zur Selbstkontrolle
Wofür steht MVC?
- Model, View, Controller (richtig)
- Module, Variable, Class
- Main, Value, Code
- Method, View, Config
Was ist Rack?
- Die gemeinsame Schnittstelle zwischen Ruby-Webservern und -Frameworks (richtig)
- Ein Datenbanktreiber
- Ein Testframework
- Ein Texteditor
Was bedeutet Konvention vor Konfiguration?
- Sinnvolle Standards ersetzen lange Einstellungen (richtig)
- Konfigurationsdateien sind verboten
- Alle Dinge müssen konfiguriert werden
- Rails hat keine Konfiguration
Weiter im Kurs
Zurück: Tests, Gems und Bundler
Weiter: Referenz und Spickzettel
Alle Kapitel: Ruby im Überblick