[RUBY] Rails Tutorial 6. Ausgabe Lernzusammenfassung Kapitel 8

Überblick

Dieser Artikel vertieft mein Verständnis, indem er einen Kommentarartikel zum Rails-Tutorial schreibt, um mein Wissen weiter zu festigen Es ist Teil meines Studiums. In seltenen Fällen kann es lächerliche oder falsche Inhalte enthalten. Bitte beachten Sie. Ich würde es begrüßen, wenn Sie mir implizit sagen könnten ...

Quelle Rails Tutorial Kapitel 6

Was ist in diesem Kapitel zu tun?

Da wir im vorherigen Kapitel die Erstellung eines Benutzers ermöglicht haben, erstellen wir einen Mechanismus zum Anmelden mit dem erstellten Benutzer.

Session

Da HTTP zustandslos ist (es gibt keinen Status), können frühere Anforderungsinformationen nicht verwendet werden. Es gibt keine Möglichkeit, Daten in HTTP beizubehalten, wenn Sie auf eine andere Seite wechseln. Die Benutzerinformationen werden beibehalten, indem stattdessen eine "Sitzung" verwendet wird.

Cookies werden häufig verwendet, um diese Sitzung in Rails zu implementieren Da Cookies Textdaten sind, die im Browser gespeichert sind und auch beim Verschieben der Seite nicht verschwinden, können Benutzerinformationen beibehalten werden.

Sitzungscontroller

Die Sitzung wird auch implementiert, indem sie direkt mit REST-Aktionen verknüpft wird. Speziell

Bewegung Aktion
Login Formular new
Anmeldevorgang create
Abmeldevorgang destroy

Anmelden → Temporäre Sitzung erstellen Abmelden → Temporäre Sitzung löschen

Erstellen Sie zunächst einen Controller für die Sitzung. rails g controller sessions new

Durch das Erstellen eines Controllers mit dem Befehl generate wird auch eine entsprechende Ansicht erstellt. Dieses Mal wird die Ansicht nur für die neue Aktion im Anmeldeformular benötigt Geben Sie mit dem Befehl generate nur new an.

Aktualisieren Sie auch route.rb. Obwohl das Routing zur neuen Aktion definiert ist umschreiben.

  get '/login', to:'sessions#new'
  post '/login', to:'sessions#create'
  delete '/logout', to:'sessions#destroy'

Ändern Sie den automatisch generierten Test so, dass auch die angegebene Route verwendet wird.

rails routesSie können die Liste der Routen mit dem Befehl überprüfen.

Übung

  1. `` `get login_pathempfängt ein Anmeldeformular mit einer GET-Anfrage.post login_path```Sendet den im Anmeldeformular eingegebenen Wert in einer Post-Anfrage.

$ rails routes | grep sessions
                                login GET    /login(.:format)                                                                         sessions#new
                                      POST   /login(.:format)                                                                         sessions#create
                               logout DELETE /logout(.:format)                                                                        sessions#destroy

Login Formular

Im Formular haben wir das Formular mit form_with implementiert. Das Anmeldeformular erstellt keine Benutzerressource, sondern lediglich eine Sitzung Modellobjekt kann nicht angegeben werden. In einem solchen Fall

<%= form_with(url: login_path, scope: :session, local: true) do |f| %>


 Senden Sie eine Post-Anfrage an login_path von
 Durch Festlegen von scope :: session
 Die Werte verschiedener Attribute werden in params [: session] gespeichert.
 Zum Beispiel Passwort
 Gespeichert in params [: session] [: password].

##### Übung
1.
 Es gibt zwei Arten von Anmeldepfaden, aber form_with ist standardmäßig auf POST-Anforderung eingestellt.
 Stellen Sie eine POST-Anforderung an login_path. Mit anderen Worten, die Erstellungsaktion wird mit dem POST-Anmeldepfad erreicht.
 Im Fall von GET ist die neue Aktion erreicht.

#### Benutzersuche und Authentifizierung
 Dieses Mal erstellen wir einen Prozess, wenn die Anmeldung fehlschlägt.

```rb
 def new
  end
  
  def create
     render 'new'
  end
  
  def destroy
  end

Wenn Sie den Controller so definieren Wenn Sie das Formular abschicken, wird es unverändert an die neue Seite weitergeleitet.

Wenn Sie versuchen, das Formular in diesem Zustand zu senden image.png

Sie können sehen, dass der Sitzungsschlüssel zum Parameter-Hash hinzugefügt wurde und die E-Mail- und Kennwortschlüssel enthält.

params = { session: { password: "foobar", email: "[email protected]" }}

Es hat eine solche Struktur.

Mit diesem Empfangen Sie Benutzeranmeldeinformationen von Parametern und suchen Sie mit der Methode `` `find_bynach dem Benutzerauthenticate```Nach der Authentifizierung des Passworts mit der Methode Prozess beim Erstellen einer Sitzung.

Klicken Sie hier, um den Inhalt der darauf basierenden Erstellungsaktion anzuzeigen

  def create
    user = User.find_by(email: params[:session][:email].downcase)
    if user && user.authenticate(params[:session][:password])
    #Prozess zum Umleiten zur Benutzerseite(von jetzt an)
    else
   #Erstellen Sie eine Fehlermeldung.
      render 'new'
    end
  end

&& ist ein logischer Produktoperator, und beide sind nur dann wahr, wenn sie wahr sind. Voraussetzung ist, dass der Benutzer existiert und das Kennwort des Benutzers authentifiziert ist.

Übung
  1. Das erwartete Ergebnis wird erhalten.
>> user = nil
=> nil
>> user && user.authenticate("foobar")
=> nil
>> !!(user && user.authenticate("foobar"))                                                                                
=> false
>> user = User.first
   (1.4ms)  SELECT sqlite_version(*)
  User Load (0.6ms)  SELECT "users".* FROM "users" ORDER BY "users"."id" ASC LIMIT ?  [["LIMIT", 1]]
=> #<User id: 1, name: "take", email: "[email protected]", created_at: "2020-06-14 02:57:10", updated_at: "2020-06-14 02:57:10", password_digest: [FILTERED]>
>> !!(user && user.authenticate("foobar"))
=> true

Flash-Nachricht anzeigen

Erstellen Sie eine Flash-Nachricht, wenn die Anmeldung fehlschlägt.

danger] = "Invalid email/password combination"



 Wenn dies unverändert bleibt, bleibt die Nachricht auch dann erhalten, wenn die Seite auf eine andere Seite geändert wird.
 Weil ich das Formular mit Rendern erneut anzeige.
 Da das Rendern keine Umleitung, sondern ein erneutes Rendern der Ansicht ist, verschwindet Flash nicht.
 Ich werde dieses Problem von nun an beheben.

 ↓ Der Blitz wird auf anderen Seiten angezeigt ↓
 ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/617753/4bbfd1e0-1e51-1de0-0b09-44394f9d9723.png)


#### Flash-Test
 Erstellen Sie einen Integrationstest für die Anmeldung. Dieses Mal gibt es ein Problem, dass der Blitz auch auf anderen Seiten angezeigt wird, daher dieser Fehler
 Erstellen Sie den Test, um ihn zuerst zu erkennen, und schreiben Sie den Code so, dass der Test erfolgreich ist.

 Klicken Sie hier für diesen Code

```rb
  test "login with invalid information" do
    get login_path
    assert_template 'sessions/new'
    post login_path , params:{ session: { email:"",password:"" }}
    assert_template 'sessions/new'
    assert_not flash.empty?
    get root_path
    assert flash.empty?
  end

Die letzten beiden Zeilen greifen auf den Root-Pfad zu und testen, ob der Flash ausgeschaltet ist.

Natürlich wird ein Fehler auftreten. Verwenden Sie `` `flash.now```, um dieses Problem zu lösen.

flash.verschwindet jetzt, wenn Sie zur nächsten Aktion übergehen.


 ↑ Referenzseite (https://qiita.com/taraontara/items/2db82e6a0b528b06b949)

 Ich war für einen Moment verwirrt, dass alles flash.now sein sollte, aber im Fall von flash.now, wenn redirect_to verwendet wird, wird flash überhaupt nicht angezeigt
 Es ist aus. (Um die nächste Aktion mit redirect_to zu lesen)

 Ändern Sie sofort `` `flash``` in`` flash.now```.
 Diese Änderung besteht den Test.

##### Übung
1.
 Anmeldungsfehler
 ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/617753/341a1295-c6d4-e19b-1947-88e9044042f4.png)
 Es verschwindet, wenn Sie zu einer anderen Seite wechseln
 ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/617753/09cc611d-ce89-3f2c-0015-a7018fba1f01.png)


### Einloggen
 Implementieren Sie als Nächstes die Verarbeitung, wenn die Anmeldeinformationen gültig sind.
 Der Verarbeitungsablauf ist
 Authentifizieren Sie sich, erstellen Sie eine temporäre Sitzung mit Cookies, wenn der Benutzer korrekt ist. Schließen Sie den Anmeldevorgang ab.
 Zur entsprechenden Benutzerseite wechseln.

 Sitzungen werden separat verarbeitet, je nachdem, ob Sie angemeldet sind oder nicht, auch auf anderen Seiten als der Anmeldeseite.
 Nehmen Sie SessionsHelper in ApplicationController auf, damit es gemeinsam verwendet werden kann.
 Auf diese Weise kann es von allen Controllern gemeinsam verwendet werden.

#### log_in Methode
 Implementieren Sie den Anmeldevorgang mit der in Rails definierten Methode "Sitzung".
 Wenn Sie die Sitzungsmethode verwenden, wird der dem Schlüssel zugeordnete Wert in temporären Cookies gespeichert.
 Diese temporären Cookies verfallen, sobald der Browser geschlossen wird. Sie müssen sich daher jedes Mal anmelden, wenn Sie ihn schließen.

 Da die Anmeldung voraussichtlich an verschiedenen Stellen verwendet wird, definieren Sie sie in SessionsHelper als Methode.


#### **`sessions_helper.rb`**
```rb

module SessionsHelper
  def log_in(user)
    session[:user_id] = user.id
  end 
end

Fügen Sie es danach der Erstellungsaktion hinzu und leiten Sie es um, um es abzuschließen!

  def create
    user = User.find_by(email: params[:session][:email].downcase)
    if user && user.authenticate(params[:session][:password])
      log_in(user)
      redirect_to user
    else
      flash.now[:danger] = "Invalid email/password combination"
      render 'new'
    end
  end
Übung
  1. Im Fall von Chrome kann die Liste in Cookies auf der Registerkarte Anwendung der Entwicklertools angezeigt werden. image.png ↑ Die verschlüsselte Benutzer-ID wird gespeichert (_sample_app_session)

  2. Läuft ab → Die Zeit bis zum Ablauf wird geschrieben. Bei einer temporären Sitzung handelt es sich um eine Sitzung, und Sie können sehen, dass sie abläuft, wenn der Browser geschlossen wird.

Aktueller Benutzer

Definieren Sie die Methode `` `current_user```, damit die Benutzer-ID abgerufen und die Benutzerinformationen auf einer anderen Seite verwendet werden können.

Die Suche nach einem Benutzerobjekt anhand der in der Sitzung gespeicherten ID, die Verwendung von find führt jedoch zu einem Fehler, wenn der Benutzer nicht vorhanden ist. Verwenden Sie die find_by-Methode.

  def current_user
    if session[:user_id]
      User.find_by(id: session[:user_id])
    end
  end

Durch Speichern dieses Ergebnisses (Benutzerobjekt) in der Instanzvariablen Die Datenbankreferenz innerhalb einer Anforderung kann nur einmal durchgeführt werden, was zu einer Beschleunigung führt.

  def current_user
    if session[:user_id]
      if @current_user.nil?
        @current_user = User.find_by(id: session[:user_id])
      else
        @current_user
      end
    end
  end

Und||Sie können diese if-Anweisung mit dem Operator in eine Zeile schreiben.

@current_user = @current_user || User.find_by(id: session[:user_id])



 Wenn Sie diese Zeile in Kurzform schreiben, erhalten Sie außerdem den richtigen Code.

#### **`@current_user ||= User.find_by(id: session[:user_id])`**
Übung
>> User.find_by(id:"123")
   (0.4ms)  SELECT sqlite_version(*)
  User Load (0.1ms)  SELECT "users".* FROM "users" WHERE "users"."id" = ? LIMIT ?  [["id", 123], ["LIMIT", 1]]
=> nil

(1) Wenn nil angegeben wird, gibt die find_by-Methode nil zurück und @current_user wird ebenfalls nil. ② Wenn `` `@ current_user``` leer ist, aus der Datenbank lesen, aber wenn es Inhalt gibt, ersetzen Sie das Vertrauen (nichts tun)

>> session = {}
=> {}
>> session[:user_id] = nil
=> nil
>> @current_user ||= User.find_by(id:session[:user_id])
  User Load (0.2ms)  SELECT "users".* FROM "users" WHERE "users"."id" IS NULL LIMIT ?  [["LIMIT", 1]]
=> nil
>> session[:user_id] = User.first.id
  User Load (0.1ms)  SELECT "users".* FROM "users" ORDER BY "users"."id" ASC LIMIT ?  [["LIMIT", 1]]
=> 1
>> @current_user ||= User.find_by(id: session[:user_id])
  User Load (0.1ms)  SELECT "users".* FROM "users" WHERE "users"."id" = ? LIMIT ?  [["id", 1], ["LIMIT", 1]]
=> #<User id: 1, name: "take", email: "[email protected]", created_at: "2020-06-14 02:57:10", updated_at: "2020-06-14 02:57:10", password_digest: [FILTERED]>
>> @current_user ||= User.find_by(id: session[:user_id])
=> #<User id: 1, name: "take", email: "[email protected]", created_at: "2020-06-14 02:57:10", updated_at: "2020-06-14 02:57:10", password_digest: [FILTERED]>
>> 

Ändern Sie den Layout-Link

Ändern Sie die angezeigte Seite dynamisch, je nachdem, ob Sie angemeldet sind oder nicht. Wenn Sie in ERB verzweigen, je nachdem, ob Sie angemeldet sind oder nicht, ändern Sie den Link. Definieren Sie eine `logged_in?` Methode, die einen logischen Wert zurückgibt.

  def logged_in?
    !current_user.nil?
  end

Ich möchte sicherstellen, dass current_user nicht leer ist, also kehre ich den logischen Wert mit um!

Ändern Sie als Nächstes das Layout der Kopfzeile.

erb:_header.html.erb


<header class="navbar navbar-fixed-top navbar-inverse">
  <div class="container">
    <%= link_to "sample app",root_path, id: "logo" %>
    <nav>
      <ul class="nav navbar-nav navbar-right">
        <li><%= link_to "Home",   root_path %></li>
        <li><%= link_to "Help",   help_path %></li>
        <% if logged_in? %>
          <li><%= link_to "Users", '#' %></li>
          <li class="dropdown">
            <a href="#" class="dropdown-toggle" data-toggle="dropdown">
              Account <b class="caret"></b>
            </a>
            <ul class="dropdown-menu">
              <li><%= link_to "Profile", current_user %></li>
              <li><%= link_to "Settings", '#'%></li>
              <li class="divider"></li>
              <li>
                <%= link_to "Log out", logout_path, method: :delete%>
              </li>
            </ul>
          </li>
        <% else %>
          <li><%= link_to "Log in", login_path %></li>
        <% end %>
      </ul>
    </nav>
  </div>
</header>

Ich füge ein Dropdown-Menü mithilfe einer Bootstrap-Klasse hinzu (z. B. Dropdown). Ebenfalls <%= link_to "profile", current_user %>In der Schlange Der Link wird in Kurzform angegeben Der Link führt zur Show-Seite. Es ist eine Funktion, die ein Benutzerobjekt in einen Link zur Show-Seite konvertiert.

Das Dropdown-Menü muss also jQuery in Bootstrap laden Laden Sie über application.js.

Laden Sie zuerst die Pakete jQuery und Bootstrap mit Garn.

yarn add [email protected] [email protected]



 Fügen Sie als Nächstes die jQuery-Einstellungen zur Webpack-Umgebungsdatei hinzu.


#### **`config/webpack/environment.js`**
```js

const { environment } = require('@rails/webpacker')
const webpack = require('webpack')
environment.plugins.prepend('Provide',
  new webpack.ProvidePlugin({
    $: 'jquery/src/jquery',
    jQuery: 'jquery/src/jquery'
  })
)
module.exports = environment

Schließlich benötigen Sie jQuery in application.js und importieren Sie Bootstrap.

Zu diesem Zeitpunkt ist das Dropdown-Menü aktiviert Da ist es möglich, sich als gültiger Benutzer anzumelden Sie können Ihren vorhandenen Code effizient testen.

Wenn Sie den Browser schließen, wird die temporäre Sitzung wie erwartet gelöscht und Sie müssen sich erneut anmelden.

Übung
  1. Bildschirm zum Löschen von Chrome-Cookies Nach dem Löschen wird der Login-Link angezeigt. image.png

  2. Ausgelassen. Sie werden aufgefordert, sich anzumelden, wenn Sie Ihren Browser neu starten. (Temporäre Sitzung verschwindet.)

Testen Sie Layoutänderungen

Wir werden das Verhalten von sich dynamisch ändernden Header-Links mit Integrationstests testen. Die Operation ist

  1. Greifen Sie auf den Anmeldepfad zu
  2. Veröffentlichen Sie die Anmeldeinformationen
  3. Testen Sie, ob der Anmeldelink ausgeblendet ist
  4. Testen Sie, ob der Abmeldelink angezeigt wird
  5. Testen Sie, ob der Profillink angezeigt wird

Sie müssen sich zuerst als registrierter Benutzer anmelden, um diese zu testen Der Benutzer muss in der Testdatenbank registriert sein. In Rails können Sie Testdaten mithilfe von Fixture erstellen.

Da die Benutzerdaten registriert sind, wird das Passwort jedoch gehasht und als password_digest gespeichert Die Fixture-Daten müssen auch das Hash-Passwort in password_digest speichern

Definiert eine Digest-Methode, die eine gehashte Kennwortzeichenfolge zurückgibt Da es für Fixtures verwendet wird, wird es nicht für Benutzerobjekte verwendet. Daher wird es als Klassenmethode definiert.

Um das Gewicht zu reduzieren, minimieren Sie die Kosten für das Hashing während des Testens und erhöhen Sie die Kosten für die Sicherheit in einer Produktionsumgebung. Klicken Sie hier für die definierte Methode

  def User.digest(string)
    cost = ActiveModel::SecurePassword.min_cost ? BCrypt::Engine::MIN_COST :
                                                  BCrypt::Engine::cost
    BCrypt::Password.create(string, cost: cost)
  end

Nachdem die Digest-Methode fertig ist, erstellen Sie ein Fixture.

users.yml


michael:
  name: Michael Example
  email: [email protected] 
  password_digest: <%= User.digest('password') %>

Da erb im Fixture verwendet werden kann, wird die mit "password" gehashte Zeichenfolge mit der Digest-Methode password_digest zugewiesen. Sie können jetzt vom Gerät aus auf den Benutzer verweisen.

Ich werde sofort einen Test erstellen.

  test "login with valid information" do
    get login_path
    post login_path , params:{session:{email: @user.email,
                                       password: 'password'}}
    assert_redirected_to @user
    follow_redirect!
    assert_template 'users/show'
    assert_select "a[href=?]", login_path, count: 0
    assert_select "a[href=?]", logout_path
    assert_select "a[href=?]", user_path(@user)
  end

In diesem Test assert_redirected_toDas Umleitungsziel ist@userIch überprüfe, ob es ist. follow_redirect!Bewegen Sie sich tatsächlich zum Umleitungsziel. Wird danach die Show-Seite (Ansicht) mit `` `assert_templateangezeigt?assert_select```Es gibt keinen Login-Link. Es gibt einen Abmeldelink. Testen auf Showpage-Links.

Übung
  1. Ändern Sie die Postzeile wie folgt.

post login_path , params:{ session: { email: @user.email,password:"" }}


 Jetzt können Sie den Fall testen, in dem Ihre E-Mail-Adresse gültig und Ihr Passwort ungültig ist.

2.```user && user.authenticate(params[:session][:password])```
↓

#### **`user&.authenticate(params[:session][:password])`**

Diese beiden sind gleichwertig

Melden Sie sich an, wenn Sie sich als Benutzer registrieren

Wenn Sie sich nach der Registrierung als Benutzer nicht anmelden, ist dies verwirrend und führt zu Verwirrung bei den Benutzern. Melden Sie sich daher gleichzeitig mit der Registrierung an. Da der Anmeldevorgang durch die Methode `log_in``` definiert wird, wird die Methode` log_in``` zur Aktion Create von UsersController hinzugefügt. Fügen Sie es einfach hinzu.

  def create
    @user = User.new(user_params)
    if @user.save
      log_in @user
      flash[:success] = "Welcome to the Sample App!"
      redirect_to @user
    else
      render 'new'
    end
  end

Um festzustellen, ob Sie beim Erstellen des hier hinzugefügten Benutzers angemeldet sind Ich möchte die Methode `logged_in?` Verwenden, die der Hilfsmethode hinzugefügt wurde Da eine Hilfsmethode zum Testen im Test nicht aufgerufen werden kann, wird `test_helper.rb``` Neu registrieren. Dies wird als is_logged_in? `` Methode definiert, um verwirrende Namen zu vermeiden.

  def is_logged_in?
    !session[:user_id].nil?
  end
Übung
  1. Es wird ROT, weil ich überprüfen werde, ob ich mit der Methode `` is_logged_in? `Angemeldet bin.
  2. Sie können auskommentieren, indem Sie die Zielzeile auswählen und die Windows-Taste +/ drücken.

Ausloggen

Wir werden die Abmeldefunktion implementieren. Da es einen Link gibt, werden wir die Aktion definieren. Der Inhalt des Prozesses ist die Umkehrung der Methode `` `log_in```, und die Sitzung kann gelöscht werden.

  def log_out
    session.delete(:user_id)
    @current_user = nil
  end

Erstellen Sie auch eine Zerstörungsaktion mit der definierten Methode `` `log_out```.

  def destroy
    log_out
    redirect_to root_url
  end

Spezifikationen zum Abmelden und Springen zur Stamm-URL beim Zugriff.

Aktualisieren Sie den Test auch hier.

user_login_test.rb


require 'test_helper'

class UsersLoginTest < ActionDispatch::IntegrationTest
  
  def setup
    @user = users(:michael)
  end
  
  test "login with valid email/invalid information" do
    get login_path
    assert_template 'sessions/new'
    post login_path , params:{ session: { email: @user.email,password:"" }}
    assert_not is_logged_in?
    assert_template 'sessions/new'
    assert_not flash.empty?
    get root_path
    assert flash.empty?
  end
  
  test "login with valid information" do
    get login_path
    post login_path , params:{session:{email: @user.email,
                                       password: 'password'}}
    assert_redirected_to @user
    follow_redirect!
    assert_template 'users/show'
    assert_select "a[href=?]", login_path, count: 0
    assert_select "a[href=?]", logout_path
    assert_select "a[href=?]", user_path(@user)
    delete logout_path
    assert_not is_logged_in?
    assert_redirected_to root_url
    follow_redirect!
    assert_select "a[href=?]", login_path
    assert_select "a[href=?]", logout_path ,count: 0
    assert_select "a[href=?]", user_path(@user), count: 0
  end
end

Hier, ob der Abmeldevorgang ausgeführt wird, ob die Umleitung erfolgreich ist, ob der angezeigte Link korrekt ist usw. Ich teste.

Außerdem wird der Inhalt von "Anmelden mit gültiger E-Mail-Adresse / ungültigem Kennwort" mithilfe der Methode "is_logged_in" umgeschrieben.

Übung

  1. Die Sitzung wird gelöscht und springt zur Stamm-URL. Die Links auf der Seite ändern sich auch zu denen vor der Anmeldung. Wir haben den Vorgang bestätigt, daher wird er weggelassen.

  2. Es verschwindet nicht, wenn Sie Chrome verwenden, aber der Abmeldevorgang ist abgeschlossen. debuggerSie können es auch direkt mit z.

[12, 21] in /home/ubuntu/environment/sample_app/app/controllers/sessions_controller.rb
   12:       render 'new'
   13:     end
   14:   end
   15:   
   16:   def destroy
   17:     log_out
   18:     redirect_to root_url
   19:     debugger
=> 20:   end
   21: end
(byebug) logged_in?
false

Zum vorherigen Kapitel

Zum nächsten Kapitel

Recommended Posts

Rails Tutorial 6. Ausgabe Lernzusammenfassung Kapitel 10
Rails Tutorial 6. Ausgabe Lernzusammenfassung Kapitel 7
Rails Tutorial 6. Ausgabe Lernzusammenfassung Kapitel 4
Rails Tutorial 6. Ausgabe Lernzusammenfassung Kapitel 6
Rails Tutorial 6. Ausgabe Lernzusammenfassung Kapitel 5
Rails Tutorial 6. Ausgabe Lernzusammenfassung Kapitel 2
Rails Tutorial 6. Ausgabe Lernzusammenfassung Kapitel 3
Rails Tutorial 6. Ausgabe Lernzusammenfassung Kapitel 8
Rails Tutorial (4. Ausgabe) Memo Kapitel 6
Rails Tutorial Kapitel 1 Lernen
Rails Tutorial Kapitel 2 Lernen
Rails Tutorial 4. Ausgabe: Kapitel 1 Von Null bis Bereitstellung
Schienen-Tutorial Kapitel 6
Schienen-Tutorial Kapitel 1
Schienen-Tutorial Kapitel 7
Schienen-Tutorial Kapitel 5
Schienen-Tutorial Kapitel 10
Schienen-Tutorial Kapitel 9
Rails Tutorial Kapitel 0: Vorbereitende Grundkenntnisse 5
[Rails] Lernen mit Rails Tutorial
Rails Tutorial Memorandum (Kapitel 3, 3.1)
[Rails Tutorial Kapitel 4] Ruby mit Rails-Geschmack
[Rails Tutorial Kapitel 5] Erstellen Sie ein Layout
Tutorial zum Kauen der Schienen [Kapitel 2 Spielzeuganwendung]
Schienen Tutry
Schienen Tutorial
Schienen Tutry
Schienen Tutry
Schienen Tutorial
Schienen Tutorial
Nur Zusammenfassung zum Einrichten des Rails-Tutorials
Rails Tutorial Test
Rails Tutorial Memorandum 1
Rails Tutorial Kapitel 1 Von Null bis Bereitstellung [Try]
Rails Lerntag 3
Rails Tutorial Memorandum 2
Rails Lerntag 4
Rails 6.0-Routing-Zusammenfassung
Schienen lernen Tag 2
Kauen der Schienen Tutorial [Kapitel 3 Erstellen fast statischer Seiten]
Schienen db: 〇〇 Zusammenfassung
[Anfänger] Rails Tutorial
[Lernnotiz] Metaprogramming Ruby 2. Ausgabe: Kapitel 3: Methode
Schienen Lerntag 1
Beheben Sie Gem :: FilePermissionError, wenn Sie Gem Install Rails ausführen (Rails Tutorial Kapitel 1).