Guida Ruby on Rails: creiamo il carrello

Ruby on Rails: creiamo il carrello

Commenti disabilitati su Guida Ruby on Rails: creiamo il carrello

Bentornato a questo nuovo appuntamento con la guida Ruby on Rails.

Nel corso della scorsa lezione abbiamo abbellito la nostra applicazione aggiungendo un layout. Quest’oggi, invece, ci occuperemo della funzionalità che ci permette di aggiungere una parte fondamentale al nostro store: il carrello!

Basta tergiversare: rimbocchiamoci le maniche ed iniziamo!

Troviamo il carrello

Nella logica della nostra applicazione vogliamo che l’utente, dopo aver visionato gli articoli che offriamo, aggiunga quelli che desidera ad un cartello. Questo carrello deve essere modificabile e ovviamente accessibile fino al momento del checkout durante il quale sarà possibile procedere al pagamento e quindi alla chiusura del carrello stesso.

Per questo motivo abbiamo bisogno di conservare il carrello nel nostro database e il suo identificativo unico, cart.id, all’interno della sessione. In questo modo, ogni volta che l’utente lo richiede, possiamo risalire al carrello relativo alla giusta identità.

Apriamo, come al solito, il terminale e digitiamo:

rails generate scaffold Cart

Seguito dal comando per la migrazione del database:

rake db:migrate

Poiché Rails fa apparire, al controller, la sessione attuale come un hash, dobbiamo memorizzare l’ID del carrello all’interno della sessione riferendoci ad esso con il simbolo :cart_id.

Apriamo quindi il file app/controllers/concerns/current_cart.rb ed aggiungiamo il seguente codice:

module CurrentCart
 extend ActiveSupport::Concern
 private
 def set_cart
   @cart = Cart.find(session[:cart_id])
 rescue ActiveRecord::RecordNotFound
   @cart = Cart.create
   session[:cart_id] = @cart.id
 end 
end

Come puoi vedere, il metodo set_cart(), prima cerca il simbolo :cart_id all’interno della sessione, e subito dopo il carrello corrispondente proprio a quell’ID. Nel caso in cui la ricerca risulti vana, procederà alla creazione di un nuovo carrello, memorizzando l’ID del carrello appena creato proprio all’interno della sessione e restituendo il carrello stesso.

 

Colleghiamo i libri al carrello

Ovviamente, affinché il nostro carrello serva veramente a qualcosa, dobbiamo prevedere la possibilità di aggiungere ad esso dei prodotti, selezionandoli dal nostro catalogo online.

Ancora una volta, l’operazione è semplice ed è sintetizzabile in questo comando da terminale:

rails generate scaffold LineItem book:references cart:belongs_to

seguito dal consueto:

rake db:migrate

Adesso il nostro database avrà uno spazio dedicato in cui memorizzare i collegamenti tra le voci del carrello, il carrello e i prodotti. Per capire meglio il tipo di relazione che lega questi tre oggetti, apriamo il file line_item.rb dalla cartella app/models. Questo è quello che vedremo:

class LineItem < ActiveRecord::Base
 belongs_to :book
 belongs_to :cart
end

Possiamo facilmente intuire che la chiamata del metodo belongs_to() impone un importante legame di “parentela”: le righe nella tabella line_items sono figlie delle righe nella tabella carts così come di quella books. In poche parole, non può esistere una voce del carrello (una line item) senza una corrispondenza con il relativo carrello e libro.

Tuttavia, la corrispondenza deve anche essere inversa. Apriamo quindi il file app/models/cart.rb e specifichiamo che:

class Cart < ActiveRecord::Base
 has_many :line_items, dependent: :destroy
end

Dove:

  • has_many :line_items indica che per ogni carrello possono esistere una ma anche più voci;
  • dependent: :destroy indica che l’esistenza delle voci all’interno del carrello dipende, come impone la logica, proprio dall’esistenza del carrello stesso;

Infine, come ultimo step, è opportuno modificare il model di book (app/models/book.rb) affinché più voci di carrello possano riferirsi ad un singolo libro (immagina più utenti con più carrelli aperti che comprano lo stesso libro) e affinché, prima di procedere alla distruzione di un libro, si abbia la certezza che non esistano carrelli pendenti che hanno proprio quel libro come voce. Quindi, il nostro file models/book.rb diventerà:

class Book < ActiveRecord::Base
 has_many :line_items
 before_destroy :check_not_used

 # qui c’è il resto del codice...
 
 private
   def check_not_used
     if line_items.empty?
       return true
     else
       errors.add(:base, 'Line Item(s) with this book exist(s)!')
       return false
     end
   end
end

 

Aggiungiamo un pulsante

Ricapitolando: abbiamo creato il carrello con un ID univoco e le sue voci, collegandole in modo reciproco all’elenco di libri e al carrello stesso. Cosa resta da fare? Aggiungere il pulsante “Add to Cart” al nostro elenco di libri!

Per fare ciò scegliamo di utilizzare il metodo button_to() specificando il testo che vogliamo mostrare sul nostro pulsante e, soprattutto, specificando l’URL che dovrà essere aperto. Poiché nel momento in cui clicchiamo sul pulsante stiamo creando una voce all’interno del carrello, il nostro interlocutore sarà LineItem ed il metodo create() che invocheremo corrisponderà proprio a quello specificato nel suo controller. Recupereremo, quindi, il percorso da LineItem utilizzando ancora una volta la magia di Rails e semplicemente utilizzando il metodo line_items_path e passando tra parentesi l’ID del libro al quale ci stiamo riferendo.

La spiegazione può sembrare contorta, ma l’esecuzione è sfacciatamente semplice. All’interno di app/views/store/index.html.erb, aggiungeremo esclusivamente questa singola linea di codice subito dopo il tag span relativo al prezzo:

<%= button_to 'Add to Cart', line_items_path(book_id: book) %>

Adesso è il turno di modificare proprio il controller LineItems per accertarsi di trovare il giusto carrello associato alla sessione o crearne uno nuovo qualora ancora non ce ne fosse uno. Apriamo quindi app/controllers/line_items_controller.rb e all’inizio del file digitiamo:

class LineItemsController < ApplicationController
 include CurrentCart
 before_action :set_cart, only: [:create]
 # qui c’è il resto del codice…
end

Andando oltre, all’interno dell’azione create() dobbiamo aggiungere la variabile book alla quale assoceremo il parametro book_id utilizzato dalla request creata poco fa. Inoltre, proprio attraverso quest’ultima variabile, costruiremo una nuova voce nel carrello. Ecco, quindi, come appare adesso l’azione create() modificata:

def create
 book = Book.find(params[:book_id])
 @line_item = @cart.line_items.build(book: book)

 respond_to do |format|
   if @line_item.save
     format.html { redirect_to @line_item.cart, notice: 'Line item was created'}
     format.json { render action: show, status: :created, location: @line_item }
     else
       format.html { render :new }
       format.json { render json: @line_item.errors, status: :unprocessable_entity }
     end
   end
end

Non ci resta che cambiare la view relativa all’azione show di cart. Apriamo app/views/carts/show.html.erb e sostituiamo il contenuto predefinito con:

<% if notice %>
 <p id="notice"><%= notice %></p>
<% end %>
<h2>Carrello</h2>
<ul>
 <% @cart.line_items.each do |item| %>
   <li><%= item.book.title %></li>
 <% end %>
</ul>

Il risultato finale sarà:

Carrello
 
Carrello

 

Conclusioni

Come puoi vedere dalle ultime due immagini il carrello sviluppato non è il massimo né in termini di layout né, soprattutto, in termini di funzionalità visto che per due voci dello stesso elemento visualizziamo il titolo ripetuto invece di utilizzare ed incrementare un indicatore di quantità. Nel corso del prossimo articolo ci dedicheremo proprio a rendere più funzionale il nostro carrello e utilizzando, più avanti ancora, tecniche AJAX per dare quel pizzico di dinamicità!

In attesa del prossimo capitolo, puoi scaricare l’intero codice sorgente aggiornato dell’applicazione tramite questo link.

GUIDA RUBY ON RAILS: INDICE LEZIONI
1) Introduzione
2) L’ambiente di lavoro e la nostra prima app
3) Un assaggio di dinamicità
4) Architettura di un’applicazione
5) Il linguaggio Ruby – Parte 1
6) Il linguaggio Ruby – Parte 2
7) Creiamo c-Bookcase
8) Convalida e test
9) Guida Ruby on Rails: page layout
10) Guida Ruby on Rails: creiamo il carrello

Tag:

L'autore

Da sempre appassionato di nuove tecnologie, guadagno il pane quotidiano scrivendo fiumi di funzioni, tonnellate di script, sciami di variabili: insomma un infinità di codice! Amante dei viaggi e del viaggio, scompongo le mie esperienze lontano da casa in complesse logiche procedurali e in stupendi design. Ancora in cerca del tag giusto per descrivere la mia vita.

Altri articoli scritti da

Articoli correlati

Potresti essere interessato anche ai seguenti articoli:

  • Guida Ruby on Rails: page layout

    Nello scorso articolo abbiamo accantonato momentaneamente lo sviluppo della nostra applicazione cbookcase per dare spazio alla fase della convalida e...

  • Guida Ruby on Rails: convalida e test

    Nel corso del precedente articolo abbiamo finalmente creato l’applicazione che ci accompagnerà per tutto il resto della guida. Nello specifico,...

  • Guida Ruby on Rails: creiamo c-Bookcase

    Eccoci finalmente pronti ad affrontare la parte più interessante della guida: la creazione di una vera e propria web app dedita a gestire un catalogo...