Módulo 11-12: Introducción a Ruby on Rails
Desarrollo web con el framework Rails
🛤️ Módulo 11-12: Introducción a Ruby on Rails
Duración: Semanas 11 y 12
Objetivos del Módulo
- Entender qué es Ruby on Rails y por qué es importante
- Conocer el patrón MVC (Modelo-Vista-Controlador)
- Crear una aplicación Rails básica
- Configurar rutas, controladores y vistas
- Conectar con bases de datos usando ActiveRecord
Contenido Teórico
1. ¿Qué es Ruby on Rails?
Ruby on Rails (o simplemente Rails) es un framework web escrito en Ruby que sigue el patrón MVC. Fue creado para hacer el desarrollo web más rápido y eficiente.
Principios de Rails:
- DRY (Don’t Repeat Yourself): No repetir código
- Convention over Configuration: Convenciones sobre configuración
- RESTful Design: Arquitectura REST para APIs
2. Instalación de Rails
# Instalar Rails
gem install rails
# Verificar instalación
rails --version
# Crear nueva aplicación
rails new mi_app
cd mi_app
# Iniciar servidor
rails server
3. Estructura de una aplicación Rails
mi_app/
├── app/
│ ├── controllers/ # Controladores
│ ├── models/ # Modelos
│ ├── views/ # Vistas
│ └── assets/ # CSS, JS, imágenes
├── config/
│ ├── routes.rb # Configuración de rutas
│ └── database.yml # Configuración de BD
├── db/
│ └── migrate/ # Migraciones de BD
├── Gemfile # Dependencias
└── public/ # Archivos estáticos
4. Patrón MVC en Rails
Modelo (Model)
Representa los datos y la lógica de negocio:
# app/models/product.rb
class Product < ApplicationRecord
validates :name, presence: true
validates :price, presence: true, numericality: { greater_than: 0 }
def price_with_tax
price * 1.21
end
end
Vista (View)
Presenta la información al usuario:
<!-- app/views/products/index.html.erb -->
<h1>Lista de Productos</h1>
<% @products.each do |product| %>
<div class="producto">
<h3><%= product.name %></h3>
<p>Precio: €<%= product.price %></p>
<p>Con IVA: €<%= product.price_with_tax %></p>
</div>
<% end %>
Controlador (Controller)
Maneja las peticiones y coordina modelo y vista:
# app/controllers/products_controller.rb
class ProductsController < ApplicationController
def index
@products = Product.all
end
def show
@product = Product.find(params[:id])
end
def new
@product = Product.new
end
def create
@product = Product.new(product_params)
if @product.save
redirect_to @product, notice: 'Producto creado exitosamente.'
else
render :new
end
end
private
def product_params
params.require(:product).permit(:name, :price, :description)
end
end
5. Rutas en Rails
# config/routes.rb
Rails.application.routes.draw do
root 'home#index'
# Rutas RESTful completas
resources :products
# Rutas personalizadas
get 'acerca', to: 'pages#about'
post 'contacto', to: 'pages#contact'
# Rutas anidadas
resources :categories do
resources :products, only: [:index, :show]
end
end
6. ActiveRecord (Modelos)
ActiveRecord es el ORM (Object-Relational Mapping) de Rails:
# Migraciones
class CreateProducts < ActiveRecord::Migration[7.0]
def change
create_table :products do |t|
t.string :name, null: false
t.decimal :price, precision: 8, scale: 2
t.text :description
t.references :category, foreign_key: true
t.timestamps
end
end
end
# Modelo con relaciones
class Product < ApplicationRecord
belongs_to :category
has_many :order_items
has_many :orders, through: :order_items
validates :name, presence: true, length: { minimum: 3 }
validates :price, presence: true, numericality: { greater_than: 0 }
scope :expensive, -> { where('price > ?', 100) }
scope :by_category, ->(cat) { where(category: cat) }
end
7. Comandos Útiles de Rails
# Generar controlador
rails generate controller Products index show new create
# Generar modelo
rails generate model Product name:string price:decimal
# Generar scaffold (completo)
rails generate scaffold Product name:string price:decimal description:text
# Ejecutar migraciones
rails db:migrate
# Rollback migraciones
rails db:rollback
# Consola de Rails
rails console
# Ver rutas
rails routes
8. Formularios en Rails
<!-- app/views/products/_form.html.erb -->
<%= form_with model: @product, local: true do |form| %>
<% if @product.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(@product.errors.count, "error") %> impidieron guardar:</h2>
<ul>
<% @product.errors.full_messages.each do |message| %>
<li><%= message %></li>
<% end %>
</ul>
</div>
<% end %>
<div class="field">
<%= form.label :name %>
<%= form.text_field :name %>
</div>
<div class="field">
<%= form.label :price %>
<%= form.number_field :price, step: :any %>
</div>
<div class="field">
<%= form.label :description %>
<%= form.text_area :description %>
</div>
<div class="actions">
<%= form.submit %>
</div>
<% end %>
9. Helpers en Rails
# app/helpers/application_helper.rb
module ApplicationHelper
def format_price(price)
number_to_currency(price, unit: "€", separator: ",", delimiter: ".")
end
def pretty_date(date)
date.strftime("%d de %B de %Y")
end
def product_status(product)
if product.stock > 10
content_tag :span, "En stock", class: "badge badge-success"
elsif product.stock > 0
content_tag :span, "Poco stock", class: "badge badge-warning"
else
content_tag :span, "Agotado", class: "badge badge-danger"
end
end
end
10. Testing Básico
# test/models/product_test.rb
require 'test_helper'
class ProductTest < ActiveSupport::TestCase
test "debe tener nombre" do
product = Product.new(price: 10.0)
assert_not product.valid?
assert_includes product.errors[:name], "can't be blank"
end
test "precio debe ser positivo" do
product = Product.new(name: "Test", price: -5)
assert_not product.valid?
assert_includes product.errors[:price], "must be greater than 0"
end
test "calcular precio con IVA" do
product = Product.new(name: "Test", price: 100)
assert_equal 121.0, product.price_with_tax
end
end
Ejercicios Prácticos
Ve al archivo ejercicios.md para ejercicios paso a paso.
Proyecto del Módulo
Ve al archivo proyecto_blog_rails.md para completar el proyecto final.