Come creare risorse nidificate per un’applicazione Ruby on Rails

Introduzione

Ruby on Rails è un framework per applicazioni web scritto in Ruby che offre agli sviluppatori un approccio opinabile allo sviluppo delle applicazioni. Lavorare con Rails offre agli sviluppatori:

  • Convenzioni per gestire cose come il routing, i dati in stato di sessione e la gestione delle risorse.
  • A firm grounding in the model-view-controller (MCV) architectural pattern, which separates an application’s logic, located in models, from the presentation and routing of application information.

All’aumentare della complessità delle tue applicazioni Rails, è probabile che lavorerai con più modelli, che rappresentano la logica di business della tua applicazione e interagiscono con il tuo database. Aggiungere modelli correlati significa stabilire relazioni significative tra di essi, che poi influenzano il modo in cui le informazioni vengono trasmesse attraverso i controller della tua applicazione e come vengono catturate e presentate agli utenti attraverso le viste.

In questo tutorial, ti baserai su un’applicazione Rails esistente che offre agli utenti informazioni sui squali. Questa applicazione ha già un modello per gestire i dati sugli squali, ma aggiungerai una risorsa nidificata per i post su singoli squali. Questo permetterà agli utenti di sviluppare un’ampia gamma di pensieri e opinioni sugli squali singoli.

Prerequisiti

Per seguire questo tutorial, avrai bisogno di:

  • A local machine or development server running Ubuntu 18.04. Your development machine should have a non-root user with administrative privileges and a firewall configured with ufw. For instructions on how to set this up, see our Initial Server Setup with Ubuntu 18.04 tutorial.
  • Node.js e npm installati sul tuo computer locale o server di sviluppo. Questo tutorial utilizza la versione di Node.js 10.16.3 e la versione di npm 6.9.0. Per istruzioni sull’installazione di Node.js e npm su Ubuntu 18.04, segui le istruzioni nella sezione “Installazione tramite un PPA” di Come Installare Node.js su Ubuntu 18.04.
  • Ruby, rbenv, e Rails installati sul tuo computer locale o server di sviluppo, seguendo i Passaggi 1-4 in Come Installare Ruby on Rails con rbenv su Ubuntu 18.04. Questo tutorial utilizza Ruby 2.5.1, rbenv 1.1.2, e Rails 5.2.3.
  • SQLite installato e un’applicazione di informazioni base sugli squali creata, seguendo le indicazioni in Come Costruire un’Applicazione Ruby on Rails.

Passaggio 1 — Costruzione del Modello Nidificato

La nostra applicazione sfrutterà le associazioni di Active Record per creare una relazione tra i modelli Squalo e Post: i post apparterranno a squali specifici e ogni squalo potrà avere più post. I modelli Squalo e Post saranno quindi correlati tramite le associazioni belongs_to e has_many.

Il primo passo per sviluppare l’applicazione in questo modo sarà creare un modello Post e le risorse correlate. Per fare ciò, possiamo utilizzare il comando rails generate scaffold, che ci fornirà un modello, una migrazione del database per modificare lo schema del database, un controller, un set completo di viste per gestire le operazioni standard di Create, Read, Update e Delete (CRUD), e modelli per parziali, helper e test. Dovremo modificare queste risorse, ma utilizzando il comando scaffold risparmieremo del tempo ed energia poiché genera una struttura che possiamo utilizzare come punto di partenza.

Innanzitutto, assicurati di trovarti nella directory sharkapp del progetto Rails che hai creato nei prerequisiti:Crea le tue risorse Post con il seguente comando:

  1. cd sharkapp

Crea i tuoi Post resources con il seguente comando:

rails generate scaffold Post body:text shark:references

Con body:text, stiamo dicendo a Rails di includere un campo body nella tabella posts del database — la tabella che si riferisce al modello Post. Stiamo anche includendo la parola chiave :references, che stabilisce un’associazione tra i modelli Shark e Post. Specificamente, questo garantirà che una chiave esterna che rappresenta ogni voce squalo nel database sharks venga aggiunta al database posts.

Una volta eseguito il comando, vedrai l’output che conferma i resources che Rails ha generato per l’applicazione. Prima di procedere, puoi controllare il file di migrazione del database per esaminare la relazione che ora esiste tra i tuoi modelli e le tabelle del database. Usa il seguente comando per visualizzare il contenuto del file, assicurandoti di sostituire il timestamp del tuo file di migrazione con quello mostrato qui:

  1. cat db/migrate/20190805132506_create_posts.rb

Vedrai il seguente output:

Output
class CreatePosts < ActiveRecord::Migration[5.2] def change create_table :posts do |t| t.text :body t.references :shark, foreign_key: true t.timestamps end end end

Come puoi vedere, la tabella include una colonna per una chiave esterna di squalo. Questa chiave avrà la forma model_name_id — in questo caso, shark_id.

Rails ha stabilito la relazione tra i modelli anche altrove. Dai un’occhiata al nuovo modello Post generato con il seguente comando:

cat app/models/post.rb
Output
class Post < ApplicationRecord belongs_to :shark end

Il collegamento belongs_to stabilisce una relazione tra modelli in cui una singola istanza del modello dichiarante appartiene a una singola istanza del modello denominato. Nel caso del nostro applicazione, ciò significa che un singolo post appartiene a un singolo squalo.

In aggiunta a impostare questa relazione, il comando rails generate scaffold ha anche creato route e viste per i post, come ha fatto per i nostri resources squalo in Passo 3 di Come Costruire un’Applicazione Ruby on Rails.

Questo è un buon inizio, ma dovremo configurare alcune route aggiuntive e consolidare l’associazione Active Record per il modello Shark al fine di far funzionare la relazione tra i nostri modelli e le route come desiderato.

Passo 2 — Specificare Route Nidificate e Associazioni per il Modello Genitore

Per aggiungere l’associazione has_many al modello Shark, apri app/models/shark.rb usando nano o il tuo editor preferito:

Aggiungi la seguente riga al file per stabilire la relazione tra gli squali e i post:

  1. nano app/models/shark.rb

Una cosa su cui vale la pena riflettere qui è cosa succede ai post una volta che uno specifico squalo viene eliminato. Probabilmente non vogliamo che i post associati a uno squalo eliminato persistano nel database. Per garantire che tutti i post associati a un dato squalo vengano eliminati quando tale squalo viene eliminato, possiamo includere l’opzione dependent con l’associazione.

~/sharkapp/app/models/shark.rb
class Shark < ApplicationRecord
  has_many :posts
  validates :name, presence: true, uniqueness: true
  validates :facts, presence: true
end

Aggiungi il seguente codice al file per assicurarti che l’azione destroy su un determinato squalo elimini tutti i post associati:

Una volta terminato di apportare queste modifiche, salva e chiudi il file. Se stai usando nano, puoi farlo premendo CTRL+X, Y, quindi ENTER.

~/sharkapp/app/models/shark.rb
class Shark < ApplicationRecord
  has_many :posts , dependent: :destroy
  validates :name, presence: true, uniqueness: true
  validates :facts, presence: true
end

Successivamente, apri il tuo file config/routes.rb per modificare la relazione tra le tue route risorse:

Attualmente, il file appare così:

  1. nano config/routes.rb

# Per informazioni sulla DSL disponibile all’interno di questo file, consulta http://guides.rubyonrails.org/routing.htmlIl codice attuale stabilisce una relazione indipendente tra le nostre route, quando quello che vorremmo esprimere è una relazione dipendente tra gli squali e i loro post associati.

~/sharkapp/config/routes.rb
Rails.application.routes.draw do
  resources :posts 
  resources :sharks

  root 'sharks#index'
  # Per ulteriori dettagli sul DSL disponibile all'interno di questo file, consulta http://guides.rubyonrails.org/routing.html
end

Il codice attuale stabilisce una relazione indipendente tra le nostre rotte, ma ciò che vorremmo esprimere è una relazione dipendente tra squali e i loro post associati.

Aggiorniamo la dichiarazione della rotta per rendere :sharks il genitore di :posts. Aggiorna il codice nel file per assomigliare al seguente:

~/sharkapp/config/routes.rb
Rails.application.routes.draw do
  resources :sharks do
    resources :posts
end
  root 'sharks#index'
  # Per ulteriori dettagli sul DSL disponibile all'interno di questo file, consulta http://guides.rubyonrails.org/routing.html
end

Salva e chiudi il file quando hai finito di modificarlo.

Con questi cambiamenti, puoi procedere all’aggiornamento del tuo posts controller.

Passo 3 – Aggiornamento del Posts Controller

L’associazione tra i nostri modelli ci fornisce metodi che possiamo utilizzare per creare nuove istanze di post associati a particolari squali. Per utilizzare questi metodi, dobbiamo aggiungerli al nostro controller dei post.

Apri il file del controller dei post:

  1. nano app/controllers/posts_controller.rb

Attualmente, il file appare così:

~/sharkapp/controllers/posts_controller.rb
class PostsController < ApplicationController
  before_action :set_post, only: [:show, :edit, :update, :destroy]

  # GET /posts
  # GET /posts.json
  def index
    @posts = Post.all
  end

  # GET /posts/1
  # GET /posts/1.json
  def show
  end

  # GET /posts/new
  def new
    @post = Post.new
  end

  # GET /posts/1/edit
  def edit
  end

  # POST /posts
  # POST /posts.json
  def create
    @post = Post.new(post_params)

    respond_to do |format|
      if @post.save
        format.html { redirect_to @post, notice: 'Post was successfully created.' }
        format.json { render :show, status: :created, location: @post }
      else
        format.html { render :new }
        format.json { render json: @post.errors, status: :unprocessable_entity }
      end
    end
  end

  # PATCH/PUT /posts/1
  # PATCH/PUT /posts/1.json
  def update
    respond_to do |format|
      if @post.update(post_params)
        format.html { redirect_to @post, notice: 'Post was successfully updated.' }
        format.json { render :show, status: :ok, location: @post }
      else
        format.html { render :edit }
        format.json { render json: @post.errors, status: :unprocessable_entity }
      end
    end
  end

  # DELETE /posts/1
  # DELETE /posts/1.json
  def destroy
    @post.destroy
    respond_to do |format|
      format.html { redirect_to posts_url, notice: 'Post was successfully destroyed.' }
      format.json { head :no_content }
    end
  end

  private
    # Utilizzare i callback per condividere la configurazione o i vincoli comuni tra le azioni.
    def set_post
      @post = Post.find(params[:id])
    end

    # Non fidarti mai dei parametri provenienti dal pericoloso internet, permetti solo la whitelist.
    def post_params
      params.require(:post).permit(:body, :shark_id)
    end
end

Come il nostro controller degli squali, i metodi di questo controller lavorano con istanze della classe Post associata. Ad esempio, il metodo new crea una nuova istanza della classe Post, il metodo index recupera tutte le istanze della classe e il metodo set_post utilizza find e params per selezionare un particolare post per id. Tuttavia, se vogliamo che le nostre istanze di post siano associate a particolari istanze di squalo, allora dovremo modificare questo codice, poiché attualmente la classe Post sta operando come un’entità indipendente.

Le nostre modifiche faranno uso di due cose:

  • I metodi che sono diventati disponibili per noi quando abbiamo aggiunto le associazioni belongs_to e has_many ai nostri modelli. In particolare, ora abbiamo accesso al metodo build grazie all’associazione has_many che abbiamo definito nel nostro modello Shark. Questo metodo ci permetterà di creare una collezione di oggetti post associati a un particolare oggetto squalo, utilizzando la chiave esterna shark_id che esiste nel nostro database posts.
  • Le rotte e gli aiutanti di routing che sono diventati disponibili quando abbiamo creato una rotta nidificata posts. Per un elenco completo di esempi di rotte che diventano disponibili quando si creano relazioni nidificate tra risorse, vedere la documentazione di Rails. Per ora, sarà sufficiente sapere che per ogni squalo specifico — diciamo squali/1 — ci sarà una rotta associata per i post relativi a quel squalo: squali/1/posts. Ci saranno anche aiutanti di routing come shark_posts_path(@shark) e edit_sharks_posts_path(@shark) che si riferiscono a queste rotte nidificate.Nel file, inizieremo scrivendo un metodo, get_shark, che verrà eseguito prima di ogni azione nel controller. Questo metodo creerà una variabile di istanza locale @shark trovando un’istanza di squalo per shark_id. Con questa variabile disponibile per noi nel file, sarà possibile relazionare i post a uno squalo specifico negli altri metodi.

Nel file, inizieremo scrivendo un metodo, get_shark, che verrà eseguito prima di ogni azione nel controller. Questo metodo creerà una variabile di istanza locale @shark cercando un’istanza di squalo tramite shark_id. Avendo questa variabile a disposizione nel file, sarà possibile relazionare i post a uno squalo specifico nelle altre metodi.

Sopra gli altri metodi private in fondo al file, aggiungi il seguente metodo:

~/sharkapp/controllers/posts_controller.rb
. . . 
private
  def get_shark
@shark = Shark.find(params[:shark_id])
end
  # Utilizza callback per condividere configurazioni o vincoli comuni tra azioni.
. . . 

Successivamente, aggiungi il filtro corrispondente alla prima parte del file, prima del filtro esistente:

~/sharkapp/controllers/posts_controller.rb
class PostsController < ApplicationController
  before_action :get_shark

Ciò garantirà che get_shark venga eseguito prima di ogni azione definita nel file.

Successivamente, puoi utilizzare questa istanza @shark per riscrivere il metodo index. Invece di prendere tutte le istanze della classe Post, vogliamo che questo metodo restituisca tutte le istanze di post associate a un’istanza di squalo specifica.

Modifica il metodo index per farlo sembrare così:

~/sharkapp/controllers/posts_controller.rb
. . .
  def index
    @posts = @shark.posts
  end
. . .

Il metodo new avrà bisogno di una revisione simile, poiché vogliamo che una nuova istanza di post sia associata a uno squalo specifico. Per ottenere ciò, possiamo utilizzare il metodo build, insieme alla nostra variabile di istanza locale @shark.

Modifica il metodo new per farlo sembrare così:

~/sharkapp/controllers/posts_controller.rb
. . . 
  def new
    @post = @shark.posts.build
  end
. . . 

Questo metodo crea un oggetto post associato all’istanza di squalo specifica dal metodo get_shark.

Aggiorna il metodo create in questo modo:

Successivamente, dai un’occhiata al metodo update. Questo metodo utilizza una variabile di istanza @post, che non è impostata esplicitamente nel metodo stesso. Da dove proviene questa variabile?

~/sharkapp/controllers/posts_controller.rb
  def create
    @post = @shark.posts.build(post_params)

        respond_to do |format|
         if @post.save  
            format.html { redirect_to shark_posts_path(@shark), notice: 'Post was successfully created.' }
            format.json { render :show, status: :created, location: @post }
         else
            format.html { render :new }
            format.json { render json: @post.errors, status: :unprocessable_entity }
      end
    end
  end

Dai un’occhiata ai filtri in cima al file. Il secondo filtro before_action auto-generato fornisce una risposta:

Il metodo update (come show, edit e destroy) prende una variabile @post dal metodo set_post. Tale metodo, elencato sotto il metodo get_shark insieme agli altri metodi private, attualmente appare così:

~/sharkapp/controllers/posts_controller.rb
class PostsController < ApplicationController
  before_action :get_shark
  before_action :set_post, only: [:show, :edit, :update, :destroy]
  . . .

In linea con i metodi utilizzati altrove nel file, dovremo modificare questo metodo in modo che @post si riferisca a una particolare istanza nella raccolta di post associata a uno squalo specifico. Tieni presente il metodo build qui: grazie alle associazioni tra i nostri modelli e ai metodi (come build) che sono disponibili per noi in virtù di tali associazioni, ciascuna delle nostre istanze di post fa parte di una raccolta di oggetti associata a uno squalo specifico. Quindi ha senso che, quando si richiede un particolare post, si effettui una query nella raccolta di post associata a uno squalo specifico.Aggiorna set_post in questo modo:Invece di trovare una particolare istanza dell’intera classe Post per id, cerchiamo invece un id corrispondente nella raccolta di post associata a uno squalo specifico.

~/sharkapp/controllers/posts_controller.rb
. . . 
private
. . . 
  def set_post
    @post = Post.find(params[:id])
  end
. . .

In conformità con i metodi che abbiamo utilizzato altrove nel file, dovremo modificare questo metodo in modo che @post si riferisca a un’istanza particolare nella raccolta di post associata a uno squalo specifico. Tenete a mente il metodo build qui – grazie alle associazioni tra i nostri modelli e ai metodi (come build) che ci sono disponibili per via di quelle associazioni, ognuna delle nostre istanze di post fa parte di una raccolta di oggetti associati a uno squalo specifico. Quindi ha senso che quando cerchiamo un post particolare, cerchiamo nella raccolta di post associati a uno squalo specifico.

Aggiorna set_post in questo modo:

~/sharkapp/controllers/posts_controller.rb
. . . 
private
. . . 
  def set_post
    @post = @shark.posts.find(params[:id])
  end
. . .

Invece di trovare un’istanza particolare dell’intera classe Post per id, cerchiamo invece un id corrispondente nella raccolta di post associati a uno squalo specifico.

Con quella modifica al metodo, possiamo esaminare i metodi update e destroy.

Il metodo update utilizza l’istanziale @post da set_post e lo utilizza con i post_params che l’utente ha inserito nel form edit. Nel caso di successo, vogliamo che Rails rimandi l’utente alla vista index dei post associati a uno squalo specifico. Nel caso di errori, Rails renderà di nuovo il modello edit.

In questo caso, l’unica modifica che dovremo apportare è all’istruzione redirect_to, per gestire gli aggiornamenti riusciti. Aggiornala per reindirizzare a shark_post_path(@shark), che reindirizzerà alla vista index dei post selezionati dello squalo:

~/sharkapp/controllers/posts_controller.rb
. . . 
  def update
    respond_to do |format|
      if @post.update(post_params)
        format.html { redirect_to shark_post_path(@shark), notice: 'Post was successfully updated.' }
        format.json { render :show, status: :ok, location: @post }
      else
        format.html { render :edit }
        format.json { render json: @post.errors, status: :unprocessable_entity }
      end
    end
  end
. . .

Successivamente, apporteremo una modifica simile al metodo destroy. Aggiorna il metodo redirect_to per reindirizzare le richieste a shark_posts_path(@shark) in caso di successo:

~/sharkapp/controllers/posts_controller.rb
. . . 
  def destroy
    @post.destroy
     respond_to do |format|
      format.html { redirect_to shark_posts_path(@shark), notice: 'Post was successfully destroyed.' }
      format.json { head :no_content }
    end
  end
. . .

Questa è l’ultima modifica che faremo. Ora hai un file di controllo dei post che assomiglia a questo:

~/sharkapp/controllers/posts_controller.rb
class PostsController < ApplicationController
  before_action :get_shark
  before_action :set_post, only: [:show, :edit, :update, :destroy]

  # GET /posts
  # GET /posts.json
  def index
    @posts = @shark.posts
  end

  # GET /posts/1
  # GET /posts/1.json
  def show
  end

  # GET /posts/new
  def new
    @post = @shark.posts.build
  end

  # GET /posts/1/edit
  def edit
  end

  # POST /posts
  # POST /posts.json
  def create
    @post = @shark.posts.build(post_params)

        respond_to do |format|
         if @post.save  
            format.html { redirect_to shark_posts_path(@shark), notice: 'Post was successfully created.' }
            format.json { render :show, status: :created, location: @post }
         else
            format.html { render :new }
            format.json { render json: @post.errors, status: :unprocessable_entity }
      end
    end
  end

  # PATCH/PUT /posts/1
  # PATCH/PUT /posts/1.json
  def update
    respond_to do |format|
      if @post.update(post_params)
        format.html { redirect_to shark_post_path(@shark), notice: 'Post was successfully updated.' }
        format.json { render :show, status: :ok, location: @post }
      else
        format.html { render :edit }
        format.json { render json: @post.errors, status: :unprocessable_entity }
      end
    end
  end

  # DELETE /posts/1
  # DELETE /posts/1.json
  def destroy
    @post.destroy
    respond_to do |format|
      format.html { redirect_to shark_posts_path(@shark), notice: 'Post was successfully destroyed.' }
      format.json { head :no_content }
    end
  end

  private

   def get_shark
     @shark = Shark.find(params[:shark_id])
   end
    # Utilizza callback per condividere setup o vincoli comuni tra le azioni.
    def set_post
      @post = @shark.posts.find(params[:id])
    end

    # Non fidarti dei parametri provenienti da internet spaventoso, consenti solo la lista bianca.
    def post_params
      params.require(:post).permit(:body, :shark_id)
    end
end

Il controller gestisce come le informazioni vengono passate dai modelli di visualizzazione al database e viceversa. Il nostro controller ora riflette la relazione tra i nostri modelli Shark e Post, in cui i post sono associati a squali particolari. Possiamo passare alla modifica dei modelli di visualizzazione stessi, che sono dove gli utenti inseriranno e modificheranno le informazioni sui post relativi a squali specifici.

Passo 4 — Modifica delle viste

Le revisioni del nostro modello di vista coinvolgeranno il cambiamento dei modelli che riguardano i post e anche la modifica della nostra vista show dei squali, poiché vogliamo che gli utenti vedano i post associati a squali particolari.

Iniziamo con il modello fondamentale per i nostri post: il parziale form che viene riutilizzato attraverso più modelli di post. Apri ora quel form:

  1. nano app/views/posts/_form.html.erb

Invece di passare solo il modello post al helper di form form_with, passeremo sia il modello shark che post, con post impostato come risorsa figlia.

Cambia la prima riga del file per riflettere la relazione tra le nostre risorse squalo e post:

~/sharkapp/views/posts/_form.html.erb
<%= form_with(model: [@shark, post], local: true) do |form| %>
. . . 

Successivamente, elimina la sezione che elenca l’shark_id dello squalo correlato, poiché questa non è informazione essenziale nella vista.

Il form finito, completo delle nostre modifiche alla prima riga e senza la sezione shark_id eliminata, sarà simile a questo:

~/sharkapp/views/posts/_form.html.erb
<%= form_with(model: [@shark, post], local: true) do |form| %>
  <% if post.errors.any? %>
    <div id="error_explanation">
      <h2><%= pluralize(post.errors.count, "error") %> prohibited this post from being saved:</h2>

      <ul>
      <% post.errors.full_messages.each do |message| %>
        <li><%= message %></li>
      <% end %>
      </ul>
    </div>
  <% end %>

  <div class="field">
    <%= form.label :body %>
    <%= form.text_area :body %>
  </div>

  <div class="actions">
    <%= form.submit %>
  </div>
<% end %>

Salva e chiudi il file quando hai finito di modificare.

Successivamente, apri la vista index, che mostrerà i post associati a uno squalo particolare:

  1. nano app/views/posts/index.html.erb

Successivamente, cambia il reindirizzamento di Show in modo che indirizzi direttamente gli utenti alla vista show per lo squalo associato, poiché probabilmente vorranno un modo per tornare al squalo originale. Possiamo utilizzare la variabile di istanza @shark che abbiamo impostato nel controller qui, poiché Rails rende disponibili tutte le variabili di istanza create nel controller a tutte le viste. Cambieremo anche il testo del link da Show a Show Shark, in modo che gli utenti comprendano meglio la sua funzione.

Aggiorna questa riga nel modo seguente:

Nella riga successiva, vogliamo assicurarci che gli utenti vengano instradati nel percorso nidificato corretto quando vanno a modificare un post. Ciò significa che anziché essere indirizzati a posts/post_id/edit, gli utenti saranno indirizzati a sharks/shark_id/posts/post_id/edit. Per fare ciò, useremo il routing helper shark_post_path e i nostri modelli, che Rails tratterà come URL. Aggiorneremo anche il testo del link per rendere più chiara la sua funzione.

Aggiorna la riga Edit in modo che assomigli al seguente:

~/sharkapp/app/views/posts/index.html.erb
. . . 
  <tbody>
    <% @posts.each do |post| %>
      <tr>
        <td><%= post.body %></td>
        <td><%= post.shark.name %></td>
. . . 

Successivamente, aggiungiamo una modifica simile al link Destroy, aggiornando la sua funzione nella stringa e aggiungendo le nostre risorse shark e post:

Infine, in fondo al modulo, vorremo aggiornare il percorso di New Post per indirizzare gli utenti al percorso nidificato appropriato quando desiderano creare un nuovo post. Aggiorna l’ultima riga del file per utilizzare il routing helper new_shark_post_path(@shark):Il file finito avrà questo aspetto:

~/sharkapp/app/views/posts/index.html.erb
. . . 
  <tbody>
    <% @posts.each do |post| %>
      <tr>
        <td><%= post.body %></td>
        <td><%= post.shark.name %></td>
        <td><%= link_to 'Show Shark', [@shark] %></td>

Salva e chiudi il file quando hai finito di modificare.

Le altre modifiche che apporteremo alle visualizzazioni dei post non saranno così numerose, poiché le altre viste utilizzano la parziale form che abbiamo già modificato. Tuttavia, vogliamo aggiornare i riferimenti a link_to negli altri modelli di post per riflettere le modifiche apportate alla nostra parziale form.

~/sharkapp/app/views/posts/index.html.erb
. . . 
  <tbody>
    <% @posts.each do |post| %>
      <tr>
        <td><%= post.body %></td>
        <td><%= post.shark.name %></td>
        <td><%= link_to 'Show Shark', [@shark] %></td>
        <td><%= link_to 'Edit Post', edit_shark_post_path(@shark, post) %></td>

Apri app/views/posts/new.html.erb:

~/sharkapp/app/views/posts/index.html.erb
. . . 
  <tbody>
    <% @posts.each do |post| %>
      <tr>
        <td><%= post.body %></td>
        <td><%= post.shark.name %></td>
        <td><%= link_to 'Show Shark', [@shark] %></td>
        <td><%= link_to 'Edit Post', edit_shark_post_path(@shark, post) %></td>
        <td><%= link_to 'Destroy Post', [@shark, post], method: :delete, data: { confirm: 'Are you sure?' } %></td>

Aggiorna il riferimento a link_to in fondo al file per utilizzare l’helper shark_posts_path(@shark):

~/sharkapp/app/views/posts/index.html.erb
. . . 
<%= link_to 'New Post', new_shark_post_path(@shark) %>

Salva e chiudi il file quando hai finito di apportare questa modifica.

~/sharkapp/app/views/posts/index.html.erb
<p id="notice"><%= notice %></p>

<h1>Posts</h1>

<table>
  <thead>
    <tr>
      <th>Body</th>
      <th>Shark</th>
      <th colspan="3"></th>
    </tr>
  </thead>

  <tbody>
    <% @posts.each do |post| %>
      <tr>
        <td><%= post.body %></td>
        <td><%= post.shark.name %></td>
        <td><%= link_to 'Show Shark', [@shark] %></td>
        <td><%= link_to 'Edit Post', edit_shark_post_path(@shark, post) %></td>
        <td><%= link_to 'Destroy Post', [@shark, post], method: :delete, data: { confirm: 'Are you sure?' } %></td>
      </tr>
    <% end %>
  </tbody>
</table>

<br>

<%= link_to 'New Post', new_shark_post_path(@shark) %>

Successivamente, apri il modello edit:

Oltre al percorso Back, aggiorneremo Show per riflettere le nostre risorse nidificate. Cambia le ultime due righe del file in questo modo:

Salva e chiudi il file.

  1. nano app/views/posts/new.html.erb

Successivamente, apri il modello show:Effettua le seguenti modifiche ai percorsi Edit e Back in fondo al file:Salva e chiudi il file quando hai finito.Come ultimo passaggio, vogliamo aggiornare la visualizzazione show per i nostri squali in modo che i post siano visibili per gli squali individuali. Apri quel file ora:Le nostre modifiche qui includeranno l’aggiunta di una sezione Posts al modulo e un collegamento Add Post in fondo al file.

~/sharkapp/app/views/posts/new.html.erb
. . . 
<%= link_to 'Back', shark_posts_path(@shark) %>

Salva e chiudi il file quando avrai terminato di apportare questa modifica.

Successivamente, apri il modello edit:

  1. nano app/views/posts/edit.html.erb

Oltre al percorso Back, aggiorneremo Show per riflettere i nostri resources nidificati. Modifica le ultime due righe del file in modo che appaiano così:

~/sharkapp/app/views/posts/edit.html.erb
. . . 
<%= link_to 'Show', [@shark, @post] %> |
<%= link_to 'Back', shark_posts_path(@shark) %>

Salva e chiudi il file.

Successivamente, apri il modello show:

nano app/views/posts/show.html.erb

Effettua le seguenti modifiche ai percorsi Edit e Back in basso nel file:

~/sharkapp/app/views/posts/edit.html.erb
. . .
<%= link_to 'Edit', edit_shark_post_path(@shark, @post) %> |
<%= link_to 'Back', shark_posts_path(@shark) %>

Salva e chiudi il file quando avrai terminato.

Come passo finale, vogliamo aggiornare la visualizzazione show per i nostri squali in modo che i post siano visibili per gli squali individuali. Apri ora quel file:

  1. nano app/views/sharks/show.html.erb

Le nostre modifiche qui includeranno l’aggiunta di una sezione Posts al modulo e un link Add Post in basso nel file.

Sotto le Facts di uno squalo specifico, aggiungeremo una nuova sezione che scorre attraverso ogni istanza nella raccolta di post associati a questo squalo, producendo il body di ogni post.

Aggiungi il seguente codice sotto la sezione Facts del modulo e sopra i reindirizzamenti in basso nel file:

~/sharkapp/app/views/sharks/show.html.erb
. . .
<p>
  <strong>Facts:</strong>
  <%= @shark.facts %>
</p>

<h2>Posts</h2>
<% for post in @shark.posts %>
    <ul>
      <li><%= post.body %></li>
  </ul>
<% end %>

<%= link_to 'Edit', edit_shark_path(@shark) %> |
. . . 

Successivamente, aggiungi un nuovo reindirizzamento per consentire agli utenti di aggiungere un nuovo post per questo particolare squalo:

~/sharkapp/app/views/sharks/show.html.erb
. . .
<%= link_to 'Edit', edit_shark_path(@shark) %> |
<%= link_to 'Add Post', shark_posts_path(@shark) %> |
<%= link_to 'Back', sharks_path %>

Salva e chiudi il file quando avrai terminato di modificare.

Hai ora apportato modifiche al modello, ai controller e alle visualizzazioni dell’applicazione per garantire che i post siano sempre associati a uno squalo specifico. Come passo finale, possiamo aggiungere alcune convalide al nostro modello Post per garantire la coerenza dei dati che vengono salvati nel database.

Passo 5 – Aggiunta di convalide e test dell’applicazione

In Passo 5 di Come creare un’applicazione Ruby on Rails, hai aggiunto convalide al tuo modello Shark per garantire uniformità e coerenza dei dati che vengono salvati nel database sharks. Ora faremo un passo simile per garantire garanzie anche per il database posts.

Apri il file in cui è definito il tuo modello Post:

  1. nano app/models/post.rb

Qui, vogliamo assicurarci che i post non siano vuoti e che non duplicino contenuti che altri utenti possano aver pubblicato. Per ottenere questo, aggiungi la seguente riga al file:

~/sharkapp/app/models/post.rb
class Post < ApplicationRecord
  belongs_to :shark
  validates :body, presence: true, uniqueness: true
end

Salva e chiudi il file quando hai finito di modificare.

Con questa ultima modifica in atto, sei pronto per eseguire le tue migrazioni e testare l’applicazione.

Innanzitutto, esegui le tue migrazioni:

  1. rails db:migrate

Successivamente, avvia il tuo server. Se stai lavorando in locale, puoi farlo eseguendo:

  1. rails s

Se stai lavorando su un server di sviluppo, esegui il seguente comando invece:

  1. rails s --binding=your_server_ip

Vai alla root del tuo applicativo all’indirizzo http://localhost:3000 o http://your_server_ip:3000.

Il tutorial preliminare del progetto Rails ti ha guidato attraverso l’aggiunta e la modifica di un’entrata di Great White shark. Se non hai aggiunto ulteriori squali, la pagina iniziale dell’applicazione apparirà così:

Fai clic su Mostra accanto al nome del Great White. Questo ti porterà alla vista show per questo squalo. Vedrai il nome dello squalo e i suoi fatti, e un Post intestazione senza contenuto. Aggiungiamo un post per popolare questa parte del modulo.

Fai clic su Aggiungi Post sotto l’intestazione Post. Questo ti porterà alla vista index del post, dove avrai l’opportunità di selezionare Nuovo Post:

Grazie ai meccanismi di autenticazione che hai messo in atto in Passo 6 di How To Build a Ruby on Rails Application, potresti essere invitato ad autenticarti con il nome utente e la password che hai creato in quel Passo, a seconda che tu abbia creato una nuova sessione o meno.

Clicca su Nuovo Post, che ti porterà al tuo modello di post nuovo:

Nel campo Corpo, digita, “Queste squali sono spaventosi!”

Clicca su Crea Post. Sarai reindirizzato alla vista indice per tutti i post che appartengono a questo squalo:

Con le nostre risorse post in funzione, ora possiamo testare le nostre convalide dei dati per assicurarci che solo i dati desiderati vengano salvati nel database.

Dalla vista indice, clicca su Nuovo Post. Nel campo Corpo del nuovo modulo, prova ad inserire “Queste squali sono spaventosi!” di nuovo:

Clicca su Crea Post. Vedrai il seguente errore:

Clicca su Indietro per tornare alla pagina principale dei post.

Per testare la nostra altra convalida, clicca di nuovo su Nuovo Post. Lascia il post vuoto e clicca su Crea Post. Vedrai il seguente errore:

Con le tue risorse nidificate e le convalide funzionanti correttamente, ora hai una applicazione Rails funzionante che puoi utilizzare come punto di partenza per ulteriori sviluppi.

Conclusione

Con la tua applicazione Rails in atto, ora puoi lavorare su cose come lo stile e lo sviluppo di altri componenti front-end. Se desideri saperne di più su routing e risorse nidificate, la documentazione di Rails è un ottimo punto di partenza.

Per saperne di più sull’integrazione dei framework front-end con la tua applicazione, dai un’occhiata a Come configurare un progetto Ruby on Rails con un frontend React.

Source:
https://www.digitalocean.com/community/tutorials/how-to-create-nested-resources-for-a-ruby-on-rails-application