Zum Inhalt springen
Ruby Anfänger 25 min

Methoden & Keyword-Args

Ruby-Methoden: Parameter, Default-Werte, Keyword-Arguments, Splat und Double-Splat. Plus Blocks, yield und die Konvention der ?/!-Methoden.

Aktualisiert:
Inhaltsverzeichnis

Methoden & Keyword-Args in Ruby

Methoden sind in Ruby extrem flexibel - mit Keyword-Arguments, optionalen Parametern und Blocks gibt es viele Wege, eine API zu designen.

Grundform

def gruessen(name)
  "Hallo, #{name}!"
end

puts gruessen("Anna")
  • def ... end statt {...}
  • Kein return noetig - der letzte Ausdruck ist der Rueckgabewert
  • snake_case ist Konvention fuer Methodennamen

Expliziter return

def sicher_teilen(a, b)
  return nil if b == 0
  a / b
end

return bricht die Methode sofort ab - nuetzlich fuer Guard-Clauses.

Parameter und Default-Werte

def gruessen(name, gruss = "Hallo")
  "#{gruss}, #{name}!"
end

gruessen("Anna")           # "Hallo, Anna!"
gruessen("Max", "Hi")      # "Hi, Max!"

Keyword-Arguments

Benannte Parameter:

def gruessen(name:, gruss: "Hallo")
  "#{gruss}, #{name}!"
end

gruessen(name: "Anna")               # "Hallo, Anna!"
gruessen(name: "Max", gruss: "Hi")   # "Hi, Max!"
  • name: ohne Default = pflicht
  • gruss: "Hallo" = optional mit Default

Keyword-Arguments machen API-Aufrufe selbstdokumentierend - besonders bei mehreren Parametern:

def nutzer_anlegen(name:, email:, rolle: :user, aktiv: true)
  # ...
end

nutzer_anlegen(
  name: "Anna",
  email: "anna@example.com",
  rolle: :admin
)

Splat (*) und Double-Splat (**)

Variadic Positional: *args

def summe(*zahlen)
  zahlen.sum
end

summe(1, 2, 3)       # 6
summe(1, 2, 3, 4, 5) # 15

# Array entpacken
arr = [10, 20, 30]
summe(*arr)           # 60

Variadic Keyword: **kwargs

def config(**options)
  options.each { |k, v| puts "#{k} = #{v}" }
end

config(port: 3000, host: "localhost", debug: true)

Kombiniert

def flexibel(name, *positional, key: "default", **rest)
  # name: pflicht, positional
  # positional: beliebig viele positional args
  # key: keyword mit default
  # rest: weitere keywords
end

Block-Argumente

Jede Methode kann einen Block empfangen - das ist ein zentrales Ruby-Konzept:

def dreimal
  yield
  yield
  yield
end

dreimal { puts "Hallo!" }
# Hallo!
# Hallo!
# Hallo!

yield ruft den uebergebenen Block auf.

Block mit Argumenten

def mit_zahlen
  yield 1
  yield 2
  yield 3
end

mit_zahlen { |n| puts n * 10 }
# 10, 20, 30

Optionaler Block

def eventuell
  if block_given?
    yield "wurde aufgerufen"
  else
    "kein Block"
  end
end

eventuell                       # "kein Block"
eventuell { |t| puts t }        # "wurde aufgerufen"

Block als Parameter

Mit &block fangst du ihn als Proc:

def zweimal(&block)
  block.call
  block.call
end

zweimal { puts "Hallo" }

Rueckgabewerte

def position(liste, wert)
  liste.each_with_index do |e, i|
    return i if e == wert
  end
  nil
end

puts position([10, 20, 30], 20)   # 1
puts position([10, 20, 30], 99)   # (nil)

Mehrere Rueckgabewerte

def min_max(zahlen)
  return zahlen.min, zahlen.max
end

kleinste, groesste = min_max([3, 1, 4, 1, 5, 9, 2])
puts "#{kleinste} .. #{groesste}"   # 1 .. 9

Ruby gibt ein Array zurueck, die Destrukturierung nimmt es auseinander.

Konventionen: ? und !

Ruby erlaubt ? und ! am Ende von Methodennamen - reine Konvention, aber sehr aussagekraeftig:

? - gibt Boolean zurueck

[].empty?           # true
"hallo".include?("all")  # true
42.even?            # true

! - “gefaehrlich” oder “modifiziert in-place”

str = "hallo"
str.upcase           # "HALLO" - neues Objekt
str                   # "hallo" - unveraendert

str.upcase!          # modifiziert str direkt
str                   # "HALLO"

Oder: “wirft Exception statt nil zurueckzugeben”:

arr = [1, 2, 3]
arr.first             # 1 (nil wenn leer)
arr.first!            # (gibt es so nicht, nur Beispielkonvention)

User.find(1)          # findet oder nil
User.find!(1)         # findet oder raise (ActiveRecord)

Methoden als Werte

Methodenreferenz mit method:

def verdoppeln(n)
  n * 2
end

m = method(:verdoppeln)
puts m.call(5)        # 10

Oder als Proc weiterreichen:

[1, 2, 3].map(&method(:verdoppeln))   # [2, 4, 6]

Symbol-to-Proc: &:methode

Ein Ruby-Klassiker:

namen = ["max", "anna", "leo"]

# Lang:
namen.map { |n| n.upcase }

# Kurz:
namen.map(&:upcase)
# ["MAX", "ANNA", "LEO"]

Das &:symbol erzeugt einen Proc, der die Methode aufruft.

Praktisches Beispiel

def nutzer_formatieren(name:, alter: nil, rollen: [], &formatter)
  info_teile = [name]
  info_teile << "#{alter} Jahre" if alter
  info_teile << rollen.join(", ") unless rollen.empty?

  text = info_teile.join(" - ")
  formatter ? formatter.call(text) : text
end

puts nutzer_formatieren(name: "Anna", alter: 28, rollen: [:admin])
# Anna - 28 Jahre - admin

puts nutzer_formatieren(name: "Max") { |t| "[#{t.upcase}]" }
# [MAX]

Zusammenfassung

  • def ... end, snake_case, letzter Ausdruck ist Rueckgabewert
  • Default-Werte (parameter = wert) und Keyword-Args (key: default)
  • *args fuer variadic, **kwargs fuer keyword-variadic
  • Blocks via yield oder &block - fundamental im Ruby-Alltag
  • ?-Methoden fuer Booleans, !-Methoden fuer destruktive Aktionen
  • &:methode als kompakte Block-Form (map(&:upcase))

Im naechsten Kapitel: Klassen, Blocks und das Enumerable-Modul - Rubys OOP-Herzstueck.

Zurück zum Ruby Kurs