La prima volta che sono stato introdotto a Ruby on Rails sono rimasto piuttosto colpito. È stato il primo framework di programmazione che ho imparato e devo dire che mi sono un po’ innamorato. Avevo appena imparato a costruire applicazioni usando Sinatra e pensavo fosse uno strumento fantastico, ma poi ho visto cosa poteva fare Rails…
Una caratteristica principale di Rails che mi è piaciuta molto era il From Helpers. Mi ha permesso di evitare di scrivere tutto l’HTML per costruire un modulo, e a sua volta mi ha dato la possibilità di fare funzioni più complesse. In questo articolo ho intenzione di analizzare i diversi helper di form forniti in Rails e anche di toccarne uno nuovo che è stato lanciato nella release 5.1 di Rails.
Creare form con l’HTML può essere una seccatura a volte, specialmente quando sono molto lunghi con troppi campi di input. Possono diventare ancora più complicati quando è necessario che il modulo invii i dati a un endpoint api specifico o che sia associato a un modello di database. Ecco un modulo html per creare un utente:
<form class="new_user" action="/users" method="post">
<label for="user_name">Name</label>
<input type="text" name="user">
<br>
<label for="user_password">Password</label>
<input type="password" name="user">
<br>
<input type="submit" name="commit" value="Create User" data-disable-with="Create User">
</form>
Come potete vedere, scrivere tutto questo può diventare complesso abbastanza velocemente. Se guardate attentamente il modulo, potete vedere che stiamo passando un attributo azione e un metodo al nostro modulo per creare un nuovo utente. Questo è fantastico e tutto il resto, ma Rails è super pignolo quando si tratta di inviare i form. Questo particolare modulo non riuscirebbe a fare il taglio quando viene inviato. È qui che gli helper dei form vengono in soccorso.
Form Helpers
Quando ho imparato per la prima volta ad usare gli helper dei form, onestamente non potevo credere a quello che facevano. Come avete visto dal precedente modulo che abbiamo fatto, ci vuole un po’ di tempo e complessità per realizzarlo. Tuttavia, con gli helper dei form questo può essere ottenuto con molto meno lavoro e con un bel po’ di “magia”.
Ci sono tre diversi helper che ci aiutano a costruire form veloci e utili in Rails, form_tag
, form_for
e form_with
. L’ultimo, form_with
, è stato introdotto nel rilascio di Rails 5.1 ed essenzialmente combina i precedenti due helper.
form_tag
Il form_tag
è il più basilare degli helper e fa meno “magia” per voi. Costruirà ancora il form per te, ma dovrai essere più esplicito nel dichiarare i percorsi degli url ed è usato principalmente quando il form non è collegato ad un Controller#action. Usiamo un modulo di ricerca di base come esempio:
<%= form_tag("/search", method: "get") do %>
<%= label_tag(:q, "Search for:") %>
<%= text_field_tag(:q) %>
<%= submit_tag("Search") %>
<% end %>
Questo genererà il seguente HTML:
<form accept-charset="UTF-8" action="/search" method="get">
<input name="utf8" type="hidden" value="✓" />
<label for="q">Search for:</label>
<input name="q" type="text" />
<input name="commit" type="submit" value="Search" />
</form>
Come potete vedere, stiamo dichiarando il percorso che vogliamo che i parametri del modulo vengano passati nel form_tag
. Puoi vedere che questo avviene nella linea <%= form_tag("/search", method: "get") do %>
e puoi anche vedere che specifichiamo la richiesta http. Questo è ancora piuttosto impressionante e potete vedere che Rails si prende cura di molte cose per noi anche nell’helper di base del form, ma Rails ha una versione più potente di questo…
form_for
Form_for è il vero affare. Questo helper ci permette di legare un form ad un oggetto, permettendoci di creare/modificare un oggetto. Come abbiamo visto nell’esempio form_tag
, dovevamo essere espliciti nel percorso dell’url da usare per inviare i parametri del modulo, ma form_for
ci permette di astrarre questo. Ecco un esempio:
<%= form_for @user do |f| %> <%= f.label :name %>
<%= f.text_field :name %>
<%= f.label :password %>
<%= f.password_field :password %>
<%= f.submit %><% end %>
Questo produrrà lo stesso codice che abbiamo visto nel nostro primo esempio di un modulo html.
<form class="new_user" action="/users" accept-charset="UTF-8" method="post">
<input name="utf8" type="hidden" value="✓">
<input type="hidden" name="authenticity_token"
value="QPJXa5iS/XNvodHhpcwV5q42RoGFWsmZkwL3ATHFfeKqxZ8IQsLs1QjJvcrdO3BwCaOfQ4TxNLDD0b6VbxiACg=="> <label for="user_name">Name</label>
<input type="text" name="user">
<br>
<label for="user_password">Password</label>
<input type="password" name="user">
<br>
<input type="submit" name="commit" value="Create User" data-disable-with="Create User"></form>
Puoi vedere immediatamente quanto sia più pulito questo codice usando form_for
. Onestamente è un po’ sconvolgente che un codice così piccolo possa creare tutto quell’html, ma lo fa davvero! Potete vedere nella prima linea di form_for
che stiamo passando una variabile di istanza dell’utente che collegherà questo modulo a quell’oggetto. L’altra cosa bella del passaggio di questa variabile è che Rails cercherà il percorso dell’url appropriato, rispetto al form_tag
dove dovevamo dirgli esplicitamente dove inviare i dati.
form_with
- Forse parlate di form_with e del suo utilizzo
- Utilizzate frammenti di codice per esempio
Se guardate le Ruby on Rails 5.1 Release Notes, c’è una nota che form_for e form_tag si stanno unificando in form_with. Il più grande beneficio con questo nuovo helper è form_with
possibile generare tag di form basati su URL, scope o modelli
Controlliamo!
form_with usando gli URL
Utilizziamo lo stesso esempio che abbiamo usato in form_for
e applichiamolo con form_with
usando solo un URL:
<%= form_with url: user_path do |f| %>
<%= f.label :first_name %>
<%= f.text_field :first_name %>
<%= f.label :last_name %>
<%= f.text_field :last_name %>
<%= f.submit %>
<% end %>
Come potete vedere è molto simile al form_tag
dove specifichiamo un URL specifico (user_path
)
form_with usando modelli
La cosa veramente bella di form_with
è che può anche essere usato per passare oggetti modello, simile a form_for
.
<%= form_with model: @user do |f| %>
<%= f.label :first_name %>
<%= f.text_field :first_name %>
<%= f.label :last_name %>
<%= f.text_field :last_name %>
<%= f.submit %>
<% end %>
Questo creerà lo stesso HTML che è stato prodotto usando form_for
.
Il nostro più grande vantaggio di form_with
è che non dobbiamo più preoccuparci di decidere tra form_tag
e form_for
. Abbiamo un simpatico helper che ci permette di fare entrambi i lavori con un semplice switch nella prima riga del modulo dichiarato.
Conclusione
Gli helper dei moduli Rails sono fantastici e la nuova aggiunta di form_with
riunisce davvero tutti i benefici di entrambi form_tag
e form_for
. Ora avete uno strumento che vi permetterà di costruire un modulo in base alle vostre esigenze. Che si tratti di un modulo di ricerca o di un modulo per persistere i dati nel vostro database, potete occuparvene con gli helper dei moduli di Rails.
Vorrei anche suggerire di consultare le guide di Rails per imparare a creare moduli più complessi. Avete un bel po’ di opzioni che vanno dal permettere ad un modello di accettare attributi annidati, all’avere attributi annidati, e altri helper di form per creare campi di input personalizzati. C’è così tanto con cui giocare quando si va in queste guide, quindi approfittatene!
Happy Coding!