Schöne URLs mit Friendly_Id

Schöne URLs mit Friendly_Id

Wenn Sie genug von Modell-IDs in der URL haben, kann die Überschreibung von to_param nur begrenzt helfen. Das FriendlyId-Plugin kann Ihnen helfen, indem es das Generieren eines URL-Slugs vereinfacht und eine Verlaufshistorie beibehält.

Einfache Rails-Blogging-Anwendung

Wir haben eine einfache Rails-Blogging-Anwendung. Ihre Startseite zeigt eine Liste der neuesten Artikel mit einem Link zu jedem Artikel an. Wenn wir auf einen der Links klicken, gelangen wir zur Seite des entsprechenden Artikels, aber die URL beschreibt den Inhalt nicht besonders gut.
$ rails new friendlyid_app
$ cd friendlyid_app
$ rails g scaffold Article name content:text published_at:datetime
$ rails db:migrate
Einrichten das BasisCodes ergibt:

1.png 884 KB


Der Artikel wird in der URL nur durch seine interne ID beschrieben, was das Standardverhalten in Rails ist. Wir würden bessere URLs haben, wenn der Name des Artikels irgendwie eingefügt wäre.

Der einfachste Weg, dies zu tun, besteht darin, die Methode to_param im Modell zu überschreiben, dessen URLs wir ändern möchten, in diesem Fall im Artikelmodell. Dies ist eine interne Methode, die Rails verwendet, um ein Objekt in einen URL-Parameter umzuwandeln.
// app/models/article.rb

class Article < ApplicationRecord
  def to_param
    "#{id} #{name}".parameterize
  end
end
Wir haben dies überschrieben, sodass es auch den Namen des Artikels zurückgibt. Wir müssen parameterize auf den String aufrufen, um ihn in einen URL-freundlichen Wert zu konvertieren. Das wird unsere Artikel-URL zu folgendem ändern:
http://localhost:8080/articles/1-superman
Es ist wichtig, dass die ID des Objekts am Anfang steht, damit die find-Methode von ActiveRecord weiterhin funktioniert. Wenn wir nicht möchten, dass die ID in der URL enthalten ist, ist es etwas anspruchsvoller, dies zum Laufen zu bringen, aber es ist möglich.

Einführung von FriendlyId

Hier kommt das FriendlyId-Plugin ins Spiel. Damit wird es einfacher, den Namen eines Modells in einer URL zu verwenden, ohne ihn mit einer ID voranzustellen. Das Gem hat eine Reihe von Funktionen, aber bevor wir uns damit befassen, werden wir sehen, was erforderlich ist, um es unserer Anwendung hinzuzufügen. Wie immer müssen wir es zu der Gemfile unserer Anwendung hinzufügen und dann bundle ausführen, um es zu installieren.
// Gemfile

...
gem 'friendly_id'

$ bundle install
In unserem Modell erweitern wir anstelle von to_param das Modell um das FriendlyId-Modul und definieren das Attribut, das wir in der URL verwenden möchten.
// app/models/article.rb

class Article < ApplicationRecord
  extend FriendlyId
  friendly_id :name
end
Nun wird unser Artikel eine URL haben, die den Namen des Artikels, aber nicht seine ID enthält.
http://localhost:8080/articles/Superman
Dieser Ansatz ist jedoch nicht besonders schön für Artikel mit komplexeren Namen; ein Artikel mit dem Namen "Batman & Robin" würde diese URL erhalten:
http://localhost:8080/articles/Batman%20&%20Robin

Verwendung von Slugs

Die URL wird aus dem vollständigen Namen des Artikels einschließlich Leerzeichen und Satzzeichen generiert. Dies ist kein Problem, wenn der an FriendlyId übergebene Parameter bereits URL-freundlich ist. Dies ist jedoch nicht der Fall für die Namen unserer Artikel, daher werden wir ein neues Slug-Attribut verwenden. Dies können wir durch Verwendung der Option use von FriendlyId tun.
// app/models/article.rb

class Article < ApplicationRecord
  extend FriendlyId
  friendly_id :name, use: :slugged
end
Das wird nach einer Slug-Spalte in der Tabelle articles der Datenbank suchen, also müssen wir diese erstellen, und wir werden eine Migration erstellen, um dies zu tun.
$ rails g migration add_slug_to_articles slug:uniq
$ rails g friendly_id
Es ist eine gute Idee, für dieses Attribut einen Index hinzuzufügen, da es für das Auffinden von Datensätzen verwendet wird.
// db/migrate/20240126184932_add_slug_to_articles.rb

class AddSlugToArticles < ActiveRecord::Migration[7.1]
  def change
    add_column :articles, :slug, :string
    add_index :articles, :slug, unique: true
  end
end
Wir können nun rails db:migrate ausführen, um die Spalte und den Index zur Datenbanktabelle hinzuzufügen. Es gibt hier noch eine weitere Sache zu tun: Wir haben bereits einige vorhandene Artikel-Datensätze, und ihre Slug-Spalte wird nicht gefüllt sein. Um dies zu beheben, können wir die Rails-Konsole öffnen und jeden Datensatz erneut speichern.
$ rails c
irb(main):001> Article.find_each(&:save)
irb(main):002> exit
Nun wird unser Artikel "Batman & Robin" eine viel schönere URL basierend auf seinem neuen Slug haben.
// app/controllers/articles_controller.rb

  # Use callbacks to share common setup or constraints between actions.
  def set_article
    @article = Article.friendly.find(params[:id])
  end

Umgang mit geänderten Artikelnamen

Wenn wir einen Artikel bearbeiten und seinen Namen ändern, wird auch sein Slug aktualisiert. Wenn wir unseren Artikel "Batman & Robin" in "Batman & Robin 2" umbenennen, wird sein Slug zu "batman-robin-2" und damit auch seine URL. Wenn wir die alte URL des Artikels jetzt besuchen, sehen wir eine Fehlermeldung.

Diese Historie muss irgendwo gespeichert werden, daher werden wir eine neue Datenbanktabelle erstellen. FriendlyId stellt einen Generator zur Verfügung, der dies für uns erledigt. Was wir eben schon erledigt haben.
 // app/models/article.rb

class Article < ApplicationRecord
  extend FriendlyId
  friendly_id :name, use: %i[slugged history]
end
Hier gibt es jedoch einen Haken: Die Historienfunktion scheint nur bei neu erstellten Datensätzen zu funktionieren. Wenn wir bereits vorhandene Datensätze haben, müssen wir sie neu generieren, wenn wir diese Funktion hinzufügen. Wir erstellen einen neuen Artikel namens "Hello World", um dies zu testen.

Es wäre besser, wenn wir zu der aktuellen URL umgeleitet würden, wenn wir eine veraltete URL besuchen. Um dies zu tun, müssen wir einige Änderungen am Controller vornehmen. Der ArticlesController ist ein Standard-RESTful-Controller mit den üblichen sieben Aktionen. Wir werden die show-Aktion ändern, da dies die Aktion ist, die einen einzelnen Artikel anzeigt.

Wir möchten, dass diese Aktion uns zu der aktuellen URL des Artikels umleitet, wenn die URL, die verwendet wurde, um die Seite zu besuchen, nicht die aktuelle ist. Dies können wir erreichen, indem wir prüfen, ob der Pfad, der verwendet wurde, um die Seite zu besuchen, nicht gleich dem aktuellen Pfad des Artikels ist. In diesem Fall hat der Benutzer einen älteren Slug oder die ID des Artikels verwendet. In beiden Fällen sollten wir zu der aktuellen URL umleiten.
// app/controllers/articles_controller.rb
  
# GET /articles/1 or /articles/1.json
  def show
    return unless request.path != article_path(@article)

    redirect_to @article, status: :moved_permanently
  end
Wir haben hier nur einige der Funktionen von FriendlyId behandelt, und Sie sollten die Dokumentation lesen, um zu sehen, was es sonst noch kann. Zum Beispiel ermöglicht uns das Reserved-Modul, bestimmte Schlüsselwörter wie "new" und "edit" zu reservieren, damit sie nicht von einem Slug verwendet werden. Das Scoped-Modul ermöglicht uns, Slugs innerhalb einer Assoziation zu gruppieren, während das SimpleI18n-Modul Unterstützung für Internationalisierung für mehrere Sprachen hinzufügt.
Meld dich an und schreibe ein Kommentar