Kurs Ruby on Rails

Kurs Ruby on Rails – Lekcja 5 – Formularze aplikacji

Czego się nauczycie?

  • Tworzyć formularze
  • Tworzyć, aktualizować oraz usuwać obiekty przy ich wykorzystaniu
  • Wyświetlania prostych powiadomień

Niezbędnik kursu:

1. Wyświetlanie tabeli z danymi

Po ostatniej lekcji powinniśmy mieć już utworzone wszystkie potrzebne nam pliki z widokami. Teraz musimy je uzupełnić czymś ciekawym, ale zanim to zrobimy wytłumaczymy sobie ich rozszerzenia. Jak możemy zauważyć nasze pliki z widokami posiadają rozszerzenie .html.erb. Rozszerzenie .html pozwala nam pisać w pliku korzystając ze składni języka HTML. Rozszerzenie .erb pozwala nam zawierać w klamrach <%=%> kod napisany w Ruby.

Zacznijmy od widoku users/index.html.erb, odpowiada on za wyświetlanie grupy obiektów. Do wyświetlania naszych danych wykorzystamy tabelę.

 <h1>Users</h1>
 <table>
   <tr>
     <th>User ID</th>
     <th>User Name</th>
   </tr>
   <% @users.each do |user| %>
     <tr>
       <td><%= user.id %></td>
       <td><%= user.name %></td>
     </tr>
   <% end %>
 </table>

Dla istniejących obiektów klasy User, będziemy wyświetlać wiersz z jego ID i imieniem.

Musimy jeszcze przekazać nasze obiekty do tej tabeli, więc cofnijmy się kontrolera UsersController.

 def index
   @users = User.all
 end

W ten sposób pod zmienną @users, będziemy mieli wszystkie rekordy User. Tylko, że jeszcze nie mamy jak dodać rekdorów do bazy danych.

CZAS TO ZMIENIĆ!

Dodajmy więc przycisk kierujący nas do tworzenia nowego obiektu.

 <%= link_to 'Add New User', new_user_path %>

link_to jest to metoda pomocnicza, która tworzy nam link z podaną nazwą, do podanego miejsca. new_user_path jest to metoda pomocnicza, która kieruje nas do akcji new kontrolera Users. Dla przypomnienia, dostępne ścieżki możemy podejrzeć używając w terminalu komendy rails routes.

Teraz po zapisaniu wszystkich plików, wystartowaniu serwera rails s oraz wejściu na link localhost:3000/users powinniśmy zobaczyć naszą tablice i link.

2. Tworzenie obiektu

Formularz tworzenia obiektu

Przejdźmy do widoku users/new.html.erb, który to odpowiada za tworzenie nowego obiektu. Do stworzenia sobie tego formularza wykorzystamy metody które dostarcza nam biblioteka Action View.

 <%= form_with model: @object do |form| %>
   <%= form.submit %>
 <% end %>

Metoda form_with tworzy formularz dla obiektu podanego w kluczu model. Aktualny formularz nie udostępnia nam żadnych pól do edycji. W lekcji o modelach stworzyliśmy model o nazwie User z polem name. Tak więc dodajmy je do formularza.

 <%= form_with model: @object do |form| %>
   <%= form.text_field :name %>
   <%= form.submit %>
 <% end %>

Teraz będziemy mogli edytować pole name w formularzu. Action View pozwala dodawać nam pola o różnych wartościach.

 form.text_area
 form.hidden_field
 form.password_field
 form.number_field
 form.range_field
 form.date_field
 form.time_field
 form.datetime_local_field
 form.month_field
 form.week_field
 form.search_field
 form.email_field
 form.telephone_field
 form.url_field
 form.color_field

Ostatnią rzeczą jaką musimy zrobić, to powiedzieć naszemu formularzowi jaki w ogóle obiekt chcemy tworzyć. Dlatego musimy wrócić na chwilę do kontrolerów.

Musimy przekazać do widoku obiekt klasy User, który nie został jeszcze utworzony.

 def new
   @user = User.new
 end

User.new zainicjalizuje nam obiekt klasy User i poprzez użycie zmiennej instancji będziemy mogli przekazać go do widoku. Jedyne co nam pozostało to zaktualizować nasz formularz by korzystał z naszej nowej zmeinnej.

 <%= form_with model: @user do |form| %>
   <%= form.text_field :name %>
   <%= form.submit %>
 <% end %>

Metoda form_with automatycznie na podstawie podanego obiektu, generuje sobie odpowiedni route, na który ma się kierować.

Wejdźmy na localhost:3000/users i klikniemy przycisk Add New User. Zostaniemy przekierowani na localhost:3000/users/new i zobaczymy nasz formularz.

Zapisywanie obiektu do bazy danych

Mamy nasz formularz, lecz gdy klikniemy przycisk Submit to nic się nie zadzieje. A to dlatego, że metoda create w UsersController nic nie wykonuje.

 def create
   @user = User.new(user_params)
   if @user.save
     redirect_to users_path
   else
     render :new
   end
 end

 private

 def user_params
   params.require(:user).permit(:name)
 end

Po kolei teraz wytłumaczymy sobie co tutaj się zadziało.

 @user = User.new(user_params)

W tej linijce utworzyliśmy sobie nowy obiekt klasy User, przekazując mu parametry które dostaliśmy z naszego metody user_params.

 private

 def user_params
   params.require(:user).permit(:name)
 end

Metoda user_params zndajuje się w metodach prywatnych (co oznacza nam private), która może być wykorzystana tylko i wyłącznie w naszym kontrolerze. W tej metodzie na naszych parametrach wywołujemy require oraz permit. Metoda require wymaga by w naszych parametrach znalazł się podany przez nas klucz (co robi dla nas formularz). Metoda permit przepuszcza nam tylko i wyłącznie parametry o takich kluczach jakie mu podaliśmy, w tym wypadku name. Wtedy nasz obiekt zostanie stworzony tylko i wyłącznie z tymi parametrami na jakie pozwoliliśmy.

 if @user.save
   redirect_to users_path
 else
   render :new
 end

Dalej próbujemy zapisać nasz obiekt. W przypadku sukcesu metoda save zwróci nam true, jeżeli zapis się nie uda dostaniemy false.

Nasz warunek patrzy czy zapis się wykonał czy nie. Jeżeli wszystko poszło pomyślnie zostaniemy przekierowani do widoku index dla UsersController. W innym wypadku wyświetlimy znowu nasz formularz. Tutaj jest ważne zawarcie naszego nowego obiektu w zmiennej instancji, byśmy mieli do niej dostęp w widoku oraz by nasz formularz dalej trzymał wpisane przez nas dane.

Kiedy nasz zapis się nie powiedzie? Kiedy dane przez nas dostarczone nie będą spełniały walidacji, które zdefiniowaliśmy w modelu.

I w ten sposób nasz obiekt powinien ukazać się w naszej tabeli.

3. Aktualizacja obiektu

Zacznijmy od dodania linku do edycji istniejących użytkowników.

 <%= link_to 'Add New User', new_user_path %>

 <h1>Users</h1>
 <table>
   <tr>
     <th>User ID</th>
     <th>User ID</th>
     <th>Edit</th>
   </tr>
   <% @users.each do |user| %>
     <tr>
       <td><%= user.id %></td>
       <td><%= user.name %></td>
       <td><%= link_to 'Edit User', edit_user_path(user) %></td>
     </tr>
   <% end %>
 </table>

Formularz edycji obiektu

Tworzenie formularza edycji jest analogiczne do naszego poprzedniego formularza.

Przechodzimy do widoku users/edit.html.erb i dodajemy tam ten sam formularz.

 <%= form_with model: @user do |form| %>
   <%= form.text_field :name %>
   <%= form.submit %>
 <% end %>

Następnie przechodzimy do kontrolera i również przekazujemy obiekt @user, tylko tym razem znajdziemy ten obiekt po id, ponieważ został on zapisany do bazy danych.

 def edit
   @user = User.find(params[:id])
 end

Teraz gdy klikniemy w nasz link w tabeli, powinniśmy zostać przenisieni do formularza edycji.

Aktualizowanie obiektu w bazy danych

I teraz musimy stworzyć akcję update w kontrolerze, analogicznie do akcji create. Tylko w tym wypadku musimy najpierw znaleźć obiekt, który chcemy zaktualizować.

 def update
   @user = User.find(params[:id])
   if @user.update(user_params)
     redirect_to users_path
   else
     render :edit
   end
 end

4. Partiale

Warto zauważyć, że oba formularze przez nas utworzone zawierają ten sam kod. Wyciągnijmy go do jednego pliku by nie powtarzać pisanego kodu.

Stwórzmy plik users/_user.html.erb_ przed nazwą oznacza, że tworzymy partial i w tym partial’u umieścimy nasz formularz.

 <%= form_with model: @user do |form| %>
   <%= form.text_field :name %>
   <%= form.submit %>
 <% end %>

Teraz w widokach new oraz edit zamieniamy nasze formularze na tę linijkę.

 <%= render 'user' %>

Powie to naszym widokom, by dalej kierowały się na ten oto partial.

5. Szczegółowy widok obiektu

Dodajmy teraz akcję show dla naszych obiektów.

Dodajemy link do naszej tabeli.

 <%= link_to 'Add New User', new_user_path %>

 <h1>Users</h1>
 <table>
   <tr>
     <th>User ID</th>
     <th>User Name</th>
     <th>Edit</th>
   </tr>
   <% @users.each do |user| %>
     <tr>
       <td><%= user.id %></td>
       <td><%= link_to user.name, user_path(user) %></td>
       <td><%= link_to 'Edit User', edit_user_path(user) %></td>
     </tr>
   <% end %>
 </table>

Tworzymy widok users/show.html.erb, w którym wyświetlimy imię naszego obiektu.

 <%= @user.name %>

Dodajemy akcję w kontrolerze.

 def show
   @user = User.find(params[:id])
 end

6. Usuwanie obiektu

Teraz przejdziemy do ostatniej rzeczy, jaką jest usuwanie obiektu.

Zacznijmy od dodania linku do usuwania w naszej tabeli.

 <%= link_to 'Add New User', new_user_path %>

 <h1>Users</h1>
 <table>
   <tr>
     <th>User ID</th>
     <th>User Name</th>
     <th>Edit</th>
     <th>Delete</th>
   </tr>
   <% @users.each do |user| %>
     <tr>
       <td><%= user.id %></td>
       <td><%= link_to user.name, user_path(user) %></td>
       <td><%= link_to 'Edit User', edit_user_path(user) %></td>
       <td><%= link_to 'Delete User', user_path(user), method: :delete %></td>
     </tr>
   <% end %>
 </table>

Podajemy go jak dla show, tylko określamy go jako metodę delete.

Następnie dodajemy akcję destroy w kontrolerze.

 def destroy
   @user = User.find(params[:id])
   if @user.destroy
     redirect_to users_path
   else
     #rozwinięcie tego warunku w następnym rozdziale
     redirect_to users_path
   end
 end

7. Powiadomienia

Do naszych akcji możemy dodać powiadomienia.

Wchodząc w plik views/layouts/application.html.erb i wrzucając pomiędzy tag <body> następujący kod.

 <%= flash[:notice] %>
 <%= flash[:alert] %>

Tutaj warto go wrzucić przed <%= yield %>, aby nasze powiadomienia pokazywały się na samej górze naszej strony.

Przejdźmy teraz do naszej akcji destroy i dodajmy tam nasze powiadomienia.

 def destroy
   @user = User.find(params[:id])
   if @user.destroy
     flash[:notice] = 'User has been destroyed'
     redirect_to users_path
   else
     flash[:alert] = 'Something went wrong'
     redirect_to users_path
   end
 end

Teraz zależnie od powodzenia naszego usuwania wyświetlimy dwa różne powiadomienia.

8. Praca własna

2. Stowrzyć formularzę dla Post oraz Comment (wraz z partialami)

3. Dodać do każdej akcji powiadomienia

Przydatne linki

http://guides.rubyonrails.org/ 
http://api.rubyonrails.org/ 
https://guides.rubyonrails.org/form_helpers.html 
https://guides.rubyonrails.org/action_controller_overview.html 
https://guides.rubyonrails.org/layouts_and_rendering.html 
https://api.rubyonrails.org/classes/ActionController/Parameters.html 
https://api.rubyonrails.org/classes/ActionDispatch/Flash.html

Przeczytaj również o...

Dołącz do naszego zespołu!

Zobacz oferty pracy