Sessions
Antes de poder construir un carrito de compras para que un usuario pueda seleccionar productos debemos aprender a utilizar las sessions dentro de Ruby on Rails; cuando un usuario está navegando nuestra tienda virtual posiblemente irá seleccionando productos, lo que normalmente se utiliza para este tipo de aplicaciones es que lo subamos a un carrito de compras virtual, donde mantendremos el producto, el precio, el costo total de la compra y la cantidad de los productos, esto hasta que haya un eventual checkout que es cuando el usuario decide concretar la compra.
Para poder cumplir con esto que estamos proponiendo debemos mantener los productos que el usuario elija en nuestra aplicación, para ello utilizaremos las sessions, con esta implementación que hace rails podemos mantener la data disponible sin necesidad de almacenarla en bases de datos y será accesible por el usuario que la inició desde el navegador que establece la conexión a la aplicación, con lo que las combinaciones keyàvalue se almacenaran y las tendremos disponibles.
Veamos un ejemplo de como este código luce, vamos a crear un nuevo método en nuestra aplicación en el controlador de store:
private def find_cart session[:cart] ||= Cart.new end
A pesar de ser unas 4 líneas de código, estas conllevan una complejidad bastante elevada, primero hacemos el método privado, de esta forma evitamos que rails lo haga disponible como una acción en el controlador, luego vemos que utilizamos el operador de asignación condicional ||=.
Este operador en el método que nos permite realizar la siguiente funcionalidad, si hay un hash de sesiones que corresponde al key : cart entonces devolvemos su contenido, de lo contrario construimos un nuevo objeto Cart y lo asignamos al sessionn, es allí cuando devolvemos su valor.
Creando las Tablas necesarias
Ahora que ya dominamos un poco la parte teórica del planteamiento vamos a ir un poco más en profundidad en la funcionalidad que debemos construir, una vez que hagamos nuestro carrito de compras sabemos que cada venta que se haga debe mantener el precio al cual se realizó por lo que vamos a crear una tabla que se llame line_items, esta lo que hará es almacenar la línea de la selección del comprador, veamos el código que tenemos que colocar en nuestra base de datos:
drop table if exists line_items; create table line_items ( id int product_id int quantity int unit_price decimal(10,2) constraint fk_items_product primary key (id) ); not null auto_increment, not null, not null default 0, not null, foreign key (product_id) references products(id), primary key (id) );
Como podemos ver en esta definición de nuestra nueva tabla hemos agregado una referencia para un foreign key que nos asocia el campo product_id con el campo id de la tabla product, esta relación nos servirá cuando generemos el modelo.
Generar el modelo
Ya que tenemos la tabla podemos interactuar con ella, para ello debemos generar un nuevo modelo para que podamos utilizarla dentro de nuestra aplicación. Utilizaremos el siguiente comando desde nuestra consola de comandos de Ruby on Rails.
depot> ruby script/generate model LineItem Una vez generado nuestro modelo, vamos a agregar lo siguiente al mismo: [i]app/models/line_item.rb[/i], como no todas las bases de datos soportan relaciones rails, el manejo de las mismas es de forma explícita. class LineItem < ActiveRecord::Base belongs_to :product end
Luego de haber creado nuestro modelo y las tablas para nuestra aplicación, sólo nos queda en la parte 2 del mismo finalizar con el desarrollo del mismo y poder tener un carrito de compras funcional y que nos sirva de trampolín para saltar a aplicaciones mucho más avanzadas.
Continuamos con la construcción del carrito de compras para nuestra aplicación, en Ruby on Rails, para ello sigamos viendo el modelo que hemos construido y veamos un poco la explicación detrás del tema. Rails maneja una convención que le permite inferir como tratar las relaciones entre tablas una vez que las hemos declarado explícitamente, al decirle que nuestro modelo LineItem tiene esta línea de código: belongs_to :product, ya el motor de rails sabe que dentro de la tabla debe existir un campo que se llame product_id.
Creación del Carrito de Compra
Ahora vamos a generar el código necesario para construir nuestro carrito de compras, primero debemos implementar el método en el controlador de nuestro store para que agregue elementos al carrito. Primero ubicaremos este controlador: app/controllers/store_controller.rb y dentro crearemos el método add_to_cart con el siguiente código en él.
def add_to_cart product = Product.find(params[:id]) @cart = find_cart @cart.add_product(product) redirect_to(:action => 'display_cart') end
Ahora debemos generar nuestra clase Cart, esta clase en particular no está ligada al modelo ActiveRecord debido a que no interactúa con la Base de Datos, para facilitarnos las cosas vamos a generarla manualmente en nuestro directorio app/models, ahí crearemos el archivo cart.rb.
Dentro nuestro nuevo archivo colocaremos lo siguiente:
class Cart attr_reader :items attr_reader :total_price def initialize @items = [] @total_price = 0.0 end def add_product(product) @items << LineItem.for_product(product) @total_price += product.price end end
Ahora con esto completado vayamos a nuestro modelo LineItem y coloquemos lo que nos falta:
class LineItem < ActiveRecord::Base belongs_to :product def self.for_product(product) item = self.new item.quantity = 1 item.product = product item.unit_price = product.price item end end
Hagamos un breve resumen de que tenemos hasta ahora. Ya tenemos el método que nos permite agregar un ítem al carrito, este es add_to_cart, luego tenemos el contenido de nuestra clase Cart que nos permite agregar un producto y por último en nuestra clase LineItem podemos extraer los valores de dichos productos que agreguemos. Sólo nos falta implementar unos pocos elementos más para que nuestra aplicación esté funcionando, primero debemos agregar una acción que nos permita mostrar la vista y en su defecto generarla, para ello agregaremos lo siguiente:
def display_cart @cart = find_cart @items = @cart.items end
Este método irá en nuestro controlador, ahora, en nuestra vista: app/views/store, crearemos un archivo display_cart.rhtml y dentro colocaremos el siguiente código:
<h1>Display Cart</h1> <p> Tu carrito contiene <%= @items.size %> cosas. </p>
Por supuesto esto aún no funciona aún debemos agregar un último paso y esto es definir nuestros nuevos modelos dentro del contexto de la aplicación para ello iremos a app/controllers y veremos un archivo llamado application.rb en el cual debemos colocar lo siguiente:
class ApplicationController < ActionController::Base model :cart model :line_item end
Con esto ya tendríamos nuestro Carrito de Compras básico pero que nos acercara a implementar un producto final con una funcionalidad totalmente extendida. Con esto finalizamos este tutorial de Ruby on Rails y es importante mencionar que debemos analizar bien el código que hemos colocado para poder entender la razón por la cual funciona y de esta manera generar conocimiento de calidad.
echo en falta la identación en el código pero gracies