Está en la página 1de 43

v7

.0
Más en rubyonrails.org: More Ruby on Rails

.4
.2
Primeros pasos con Rails
Esta guía cubre cómo ponerse en marcha con
Ruby on Rails.

Después de leer esta guía, sabrás:

Cómo instalar Rails, crear una nueva


aplicación de Rails y conectar su
Aplicación a una base de datos.

El diseño general de una aplicación


Rails.

Los principios básicos de MVC


(Modelo, Vista, Controlador) y diseño
RESTful.

Cómo generar rápidamente las piezas


de partida de una aplicación Rails.

Capítulos
1. Supuestos de guía

2. ¿Qué es Rails?

3. Creación de un nuevo proyecto de rieles


Instalación de rieles

Creación de la aplicación de blog

4. ¡Hola, Rails!
Inicio del servidor web

Di "Hola", Rails

Configuración de la página principal de la aplicación

5. Carga automática

6. MVC y usted
Generación de un modelo

Migraciones de bases de datos

Uso de un modelo para interactuar con la base de


datos

Mostrar una lista de artículos

7. CRUDit donde CRUDit se debe


v7
v7
Mostrar un solo artículo

.0
.4
Enrutamiento ingenioso

.2
Crear un nuevo artículo

Actualizar un artículo

Eliminar un artículo

8. Agregar un segundo modelo


Generación de un modelo

Asociación de modelos

Agregar una ruta para comentarios

Generación de un controlador

9. Refactorización
Representación de colecciones parciales

Representación de un formulario parcial

Uso de preocupaciones

10. Eliminar comentarios


Eliminación de objetos asociados

11. Seguridad
Autenticación básica

Otras consideraciones de seguridad

12. ¿Qué sigue?

13. Configuración Gotchas

1 Guía de supuestos
Esta guía está diseñada para principiantes que desean comenzar a crear un Rails. Aplicación desde cero.
No asume que usted tiene alguna experiencia previa con Rails.

Rails es un marco de aplicación web que se ejecuta en el lenguaje de programación Ruby. Si no tienes
experiencia previa con Ruby, encontrarás un aprendizaje muy empinado. curva buceando directamente en
Rails. Hay varias listas curadas de recursos en línea para aprender Ruby:

Sitio web oficial de Ruby Programming Language


Lista de libros de programación gratuitos

Tenga en cuenta que algunos recursos, aunque siguen siendo excelentes, cubren versiones anteriores de
Ruby, y puede que no incluya alguna sintaxis que verá en el día a día desarrollo con Rails.

2 ¿Qué es Rails?
Rails es un framework de desarrollo de aplicaciones web escrito en el lenguaje de programación Ruby.
Está diseñado para facilitar la programación de aplicaciones web haciendo suposiciones. sobre lo que
todo desarrollador necesita para empezar. Te permite escribir menos Codifique mientras logra más que
muchos otros lenguajes y marcos. Los desarrolladores experimentados de Rails también informan que
hace que la aplicación web desarrollo más divertido.

Rails es un software obstinado. Hace la suposición de que hay un "mejor" forma de hacer las cosas, y
está diseñado para fomentar de esa manera, y en algunos casos para Desalentar las alternativas. Si
v7
v7
aprendes "The Rails Way" probablemente descubrirás un Tremendo aumento de la productividad. Si

.0
persistes en traer viejos hábitos de otros lenguajes para su desarrollo de Rails, y tratando de usar

.4
patrones que Aprendido en otro lugar, puede tener una experiencia menos feliz.

.2
La filosofía de Rails incluye dos principios rectores principales:

No te repitas: DRY es un principio de desarrollo de software que establece que "Cada pieza de
conocimiento debe tener una pieza única, inequívoca y autorizada. representación dentro de un
sistema". Al no escribir la misma información una y otra vez Una vez más, nuestro código es más
fácil de mantener, más extensible y con menos errores.
Convención sobre configuración: Rails tiene opiniones sobre la mejor manera de hacer
muchos cosas en una aplicación web, y de forma predeterminada a este conjunto de
convenciones, en lugar de requieren que especifique minucias a través de archivos de
configuración interminables.

3 Creación de un nuevo proyecto de rieles


La mejor manera de leer esta guía es seguirla paso a paso. Todos los pasos son esencial para ejecutar
esta aplicación de ejemplo y no hay código o pasos adicionales necesario.

Al seguir esta guía, creará un proyecto de Rails llamado , un blog (muy) simple. Antes de empezar a crear
la aplicación, debe asegurarse de tener instalado Rails. blog

Los siguientes ejemplos se utilizan para representar el indicador de terminal en un sistema operativo
similar a UNIX, aunque puede haber sido personalizado para que parezca diferente. Si está utilizando
Windows, El mensaje tendrá un aspecto similar al de . $ C:\source_code>

3.1 Instalación de rieles


Antes de instalar Rails, debe comprobar que su sistema tiene el Requisitos previos adecuados instalados.
Estos incluyen:

Rubí
SQLite3

3.1.1 Instalación de Ruby

Abra un símbolo de la línea de comandos. En macOS, abre Terminal.app; en Windows, elija "Ejecutar" en
el menú Inicio y escriba . Cualquier comando precedido por un El signo de dólar debe ejecutarse en la
línea de comandos. Compruebe que tiene un versión actual de Ruby instalada: cmd.exe $

$ ruby --version
ruby 2.7.0
Copiar

Rails requiere Ruby versión 2.7.0 o posterior. Es preferible utilizar la última versión de Ruby. Si el número
de versión devuelto es menor que ese número (como 2.3.7 o 1.8.7), tendrás que instalar una copia nueva
de Ruby.

Para instalar Rails en Windows, primero deberá instalar Ruby Installer.


v7
v7
Para obtener más métodos de instalación para la mayoría de los sistemas operativos, eche un vistazo a

.0
ruby-lang.org.

.4
.2
3.1.2 Instalación de SQLite3

También necesitará una instalación de la base de datos SQLite3. Muchos sistemas operativos populares
similares a UNIX se suministran con una versión aceptable de SQLite3. Otros pueden encontrar
instrucciones de instalación en el sitio web de SQLite3.

Verifique que esté correctamente instalado y en su carga: PATH

$ sqlite3 --version
Copiar

El programa debe informar su versión.

3.1.3 Instalación de rieles

Para instalar Rails, use el comando proporcionado por RubyGems: gem install

$ gem install rails


Copiar

Para verificar que tiene todo instalado correctamente, debería poder Ejecute lo siguiente en un nuevo
terminal:

$ rails --version
Copiar

Si dice algo como "Rails 7.0.0", está listo para continuar.

3.2 Creación de la aplicación de blog


Rails viene con una serie de scripts llamados generadores que están diseñados para hacer Tu vida de
desarrollo más fácil creando todo lo necesario para comenzar trabajando en una tarea en particular. Uno
de ellos es el nuevo generador de aplicaciones, que le proporcionará la base de una nueva aplicación
Rails para que No tienes que escribirlo tú mismo.

Para usar este generador, abra un terminal, navegue a un directorio donde tenga Derechos para crear
archivos y ejecutar:

$ rails new blog


Copiar

Esto creará una aplicación de Rails llamada Blog en un directorio y Instale las dependencias GEM que ya
se mencionan en Uso de . blog Gemfile bundle install

Puede ver todas las opciones de línea de comandos que la aplicación Rails El generador acepta
ejecutando . rails new --help
v7
v7
Después de crear la aplicación de blog, cambie a su carpeta:

.0
.4
.2
$ cd blog
Copiar

El directorio tendrá una serie de archivos y carpetas generados que hacen hasta la estructura de una
aplicación Rails. La mayor parte del trabajo en este tutorial sucede en la carpeta, pero aquí hay un
resumen básico de la función de cada de los archivos y carpetas que Rails crea de forma
predeterminada: blog app

Archivo/Carpeta Propósito

Contiene los controladores, modelos, vistas, ayudantes, correos, canales,


.app/ trabajos y activos de la aplicación. Se centrará en esta carpeta durante el resto
de esta guía.

Contiene el script que inicia la aplicación y puede contener otros scripts que use
.bin/
para configurar, actualizar, implementar o ejecutar la aplicación.rails

Contiene la configuración de las rutas, la base de datos y mucho más de la


config/ aplicación. Esto se trata con más detalle en Configuración de aplicaciones de
rieles.

Configuración de rack para servidores basados en rack utilizados para iniciar la


config.ru aplicación. Para obtener más información acerca de Rack, consulte el sitio web
de Rack.

Contiene el esquema de base de datos actual, así como las migraciones de


.db/
base de datos.

Estos archivos le permiten especificar qué dependencias de gemas son


Gemfile necesarias para su aplicación Rails. Estos archivos son utilizados por la gema
Gemfile.lock Bundler. Para obtener más información acerca de Bundler, consulte el sitio web
de Bundler.

Lib/ Módulos extendidos para su aplicación.

.log/ Archivos de registro de la aplicación.

Contiene archivos estáticos y activos compilados. Cuando la aplicación se esté


público/
ejecutando, este directorio se expondrá tal cual.

Este archivo localiza y carga tareas que se pueden ejecutar desde la línea de
comandos. Las definiciones de tareas se definen en todos los componentes de
Rakefile
Rails. En lugar de cambiar , debe agregar sus propias tareas agregando
archivos al directorio de la aplicación.Rakefilelib/tasks

Este es un breve manual de instrucciones para su aplicación. Debe editar este


README.md
archivo para indicar a otros lo que hace la aplicación, cómo configurarla, etc.
v7
v7
.0
Archivo/Carpeta Propósito

.4
.2
Archivos de almacenamiento activo para el Servicio de disco. Esto se trata en
almacenamiento/
Información general sobre almacenamiento activo.

Pruebas unitarias, accesorios y otros aparatos de prueba. Estos están cubiertos


prueba/
en Aplicaciones de rieles de prueba.

.tmp/ Archivos temporales (como archivos cache y pid).

Un lugar para todo el código de terceros. En una aplicación típica de Rails, esto
vendedor/
incluye gemas de proveedores.

Este archivo define metadatos para rutas específicas en un repositorio git. Estos
metadatos pueden ser utilizados por git y otras herramientas para mejorar su
.gitattributes
comportamiento. Consulte la documentación de gitattributes para obtener
más información.

Este archivo le dice a git qué archivos (o patrones) debe ignorar. Consulte
.gitignore GitHub - Ignorar archivos para obtener más información sobre cómo ignorar
archivos.

.ruby-version Este archivo contiene la versión predeterminada de Ruby.

4 ¡Hola, Rails!
Para empezar, vamos a poner un poco de texto en la pantalla rápidamente. Para hacer esto, necesitas
ponga en marcha su servidor de aplicaciones Rails.

4.1 Inicio del servidor web


De hecho, ya tiene una aplicación Rails funcional. Para verlo, necesitas Inicie un servidor web en el
equipo de desarrollo. Puede hacerlo ejecutando el comando siguiente comando en el directorio: blog

$ bin/rails server
Copiar

Si está utilizando Windows, debe pasar los scripts debajo de la carpeta directamente al intérprete de
Ruby, por ejemplo. bin ruby bin\rails server

La compresión de activos JavaScript requiere que tener un tiempo de ejecución de JavaScript disponible
en su sistema, en ausencia de un tiempo de ejecución, verá un error durante la compresión de activos.
Por lo general, macOS y Windows vienen con un tiempo de ejecución de JavaScript instalado. es el
tiempo de ejecución recomendado para los usuarios de JRuby y es agregado por de forma
predeterminada en las aplicaciones generadas en JRuby. Puedes investigar todos los tiempos de
ejecución soportados en ExecJS. execjs therubyrhino Gemfile

Esto iniciará Puma, un servidor web distribuido con Rails por defecto. Ver Su aplicación en acción, abra
una ventana del navegador y navegue hasta http://localhost:3000. Debería ver la página de información
predeterminada de Rails:
v7
v7
.0
.4
.2
Cuando desee detener el servidor web, presione Ctrl + C en la ventana del terminal donde se está
ejecutando. En el entorno de desarrollo, Rails generalmente no requerir que reinicie el servidor; Los
cambios que realice en los archivos serán recogido automáticamente por el servidor.

La página de inicio de Rails es la prueba de humo para un nuevo Rails Aplicación: Se asegura de que
tiene su software configurado correctamente suficiente para servir una página.

4.2 Di "Hola", rieles


Para que Rails diga "Hola", debe crear al menos una ruta, un controlador con una acción y una vista. Una
ruta asigna una solicitud a un Acción del controlador. Una acción del controlador realiza el trabajo
necesario para controlar el y prepara los datos para la vista. Una vista muestra los datos en un formato.

En términos de implementación: Las rutas son reglas escritas en un DSL Ruby (Lenguaje específico del
dominio). Los controladores son clases Ruby y sus métodos públicos son acciones. Y vistas son
plantillas, generalmente escritas en una mezcla de HTML y Ruby.

Comencemos agregando una ruta a nuestro archivo de rutas, , en el Parte superior del
bloque: config/routes.rb Rails.application.routes.draw

Rails.application.routes.draw do
get "/articles", to: "articles#index"

# For details on the DSL available within this file, see


https://guides.rubyonrails.org/routing.html
end
Copiar

La ruta anterior declara que las solicitudes se asignan a la acción de . GET


/articles index ArticlesController
v7
v7
Para crear y su acción, ejecutaremos el controlador generador (con la opción porque ya tenemos un Ruta

.0
adecuada): ArticlesController index --skip-routes

.4
.2
$ bin/rails generate controller Articles index --skip-routes
Copiar

Rails creará varios archivos para usted:

create app/controllers/articles_controller.rb
invoke erb
create app/views/articles
create app/views/articles/index.html.erb
invoke test_unit
create test/controllers/articles_controller_test.rb
invoke helper
create app/helpers/articles_helper.rb
invoke test_unit
Copiar

El más importante de ellos es el archivo del controlador, . Echemos un


vistazo: app/controllers/articles_controller.rb

class ArticlesController < ApplicationController


def index
end
end
Copiar

La acción está vacía. Cuando una acción no representa explícitamente una vista (o de lo contrario
desencadenará una respuesta HTTP), Rails renderizará automáticamente una vista que coincida con el
nombre del controlador y la acción. Convención Terminada ¡Configuración! Las vistas se encuentran en el
directorio. Por lo tanto, la acción se renderizará de forma
predeterminada. index app/views index app/views/articles/index.html.erb

Abramos , y reemplacemos su contenido con: app/views/articles/index.html.erb

<h1>Hello, Rails!</h1>
Copiar

Si anteriormente detuvo el servidor web para ejecutar el generador del controlador, Reiniciarlo con . Ahora
visite http://localhost:3000/articles, y vea nuestro texto mostrado! bin/rails server

4.3 Configuración de la página de inicio de la aplicación


Por el momento, todavía http://localhost:3000 muestra una página con el logotipo de Ruby on Rails.
Vamos a mostrar nuestro texto "Hello, Rails!" en http://localhost:3000 también. Para hacer Por lo tanto,
agregaremos una ruta que mapea la ruta raíz de nuestra aplicación a la Controlador y acción apropiados.
v7
v7
Abramos , y agreguemos la siguiente ruta a la parte superior de El

.0
bloque: config/routes.rb root Rails.application.routes.draw

.4
.2
Rails.application.routes.draw do
root "articles#index"

get "/articles", to: "articles#index"


end
Copiar

Ahora podemos ver nuestro texto "Hello, Rails!" cuando visitamos http://localhost:3000, confirmando que
la ruta también está asignada a la acción de . root index ArticlesController

Para obtener más información sobre el enrutamiento, consulte Enrutamiento de rieles de afuera hacia
adentro.

5 Carga automática
Las aplicaciones Rails no se utilizan para cargar el código de la aplicación. require

Es posible que haya notado que hereda de , pero no tiene nada


como ArticlesController ApplicationController app/controllers/articles_controller.rb

require "application_controller" # DON'T DO THIS.


Copiar

Las clases y módulos de aplicación están disponibles en todas partes, no necesita y no debe cargar nada
con . Esta característica se denomina carga automática y puede obtener más información al respecto en
Constantes de carga automática y recarga. app require

Solo necesita llamadas para dos casos de uso: require

Para cargar archivos en el directorio. lib


Para cargar las dependencias gema que tienen en el archivo . require: false Gemfile

6 MVC y tú
Hasta ahora, hemos discutido rutas, controladores, acciones y vistas. Todos estos son piezas típicas de
una aplicación web que sigue el patrón MVC (Modelo-Vista-Controlador). MVC es un patrón de diseño
que divide las responsabilidades de una aplicación en Haz que sea más fácil razonar. Rails sigue este
patrón de diseño por convención.

Ya que tenemos un controlador y una vista con la que trabajar, generemos el siguiente Pieza: un modelo.

6.1 Generación de un modelo


Un modelo es una clase Ruby que se utiliza para representar datos. Además, los modelos puede
interactuar con la base de datos de la aplicación a través de una característica de Rails llamada Active
Record.

Para definir un modelo, usaremos el generador de modelos:


v7
v7
.0
$ bin/rails generate model Article title:string body:text

.4
Copiar

.2
Los nombres de modelo son singulares, porque un modelo con instancias representa un Registro único
de datos. Para ayudar a recordar esta convención, piense en cómo lo haría Llame al constructor del
modelo: queremos escribir , no . Article.new(...) Articles.new(...)

Esto creará varios archivos:

invoke active_record
create db/migrate/<timestamp>_create_articles.rb
create app/models/article.rb
invoke test_unit
create test/models/article_test.rb
create test/fixtures/articles.yml
Copiar

Los dos archivos en los que nos centraremos son el archivo de migración () y el archivo de modelo
(). db/migrate/<timestamp>_create_articles.rb app/models/article.rb

6.2 Migraciones de bases de datos


Las migraciones se utilizan para alterar la estructura de la base de datos de una aplicación. En
Aplicaciones de rieles, las migraciones están escritas en Ruby para que puedan ser Independiente de la
base de datos.

Echemos un vistazo al contenido de nuestro nuevo archivo de migración:

class CreateArticles < ActiveRecord::Migration[7.0]


def change
create_table :articles do |t|
t.string :title
t.text :body

t.timestamps
end
end
end
Copiar

La llamada a especifica cómo debe ser la tabla construido. De forma predeterminada, el método agrega
una columna como Clave principal de incremento automático. Así que el primer registro de la tabla tendrá
un de 1, el siguiente registro tendrá un de 2, y así
sucesivamente. create_table articles create_table id id id

Dentro del bloque para , se definen dos columnas: y . Estos fueron agregados por el generador porque los
incluimos en nuestro Comando generate (). create_table title body bin/rails generate model
Article title:string body:text
v7
v7
En la última línea del bloque hay una llamada a . Este método define dos columnas adicionales

.0
denominadas y . Como veremos, Rails los gestionará por nosotros, estableciendo los valores cuando

.4
creemos o actualicemos un objeto de modelo. t.timestamps created_at updated_at

.2
Ejecutemos nuestra migración con el siguiente comando:

$ bin/rails db:migrate
Copiar

El comando mostrará la salida que indica que se creó la tabla:

== CreateArticles: migrating ===================================


-- create_table(:articles)
-> 0.0018s
== CreateArticles: migrated (0.0018s) ==========================
Copiar

Para obtener más información sobre las migraciones, consulte Migraciones de registros activos.

Ahora podemos interactuar con la tabla usando nuestro modelo.

6.3 Uso de un modelo para interactuar con la base de datos


Para jugar un poco con nuestro modelo, vamos a usar una función de Rails llamada consola. La consola
es un entorno de codificación interactivo al igual que , pero también carga automáticamente Rails y
nuestro código de aplicación. irb

Vamos a iniciar la consola con este comando:

$ bin/rails console
Copiar

Debería ver un mensaje como: irb

Loading development environment (Rails 7.0.0)


irb(main):001:0>
Copiar

En este mensaje, podemos inicializar un nuevo objeto: Article

irb> article = Article.new(title: "Hello Rails", body: "I am on Rails!")


Copiar

Es importante tener en cuenta que solo hemos inicializado este objeto. Este objeto no se guarda en la
base de datos en absoluto. Solo está disponible en la consola en el momento. Para guardar el objeto en la
base de datos, debemos llamar a save :
v7
v7
.0
irb> article.save

.4
(0.1ms) begin transaction

.2
Article Create (0.4ms) INSERT INTO "articles" ("title", "body", "created_at",
"updated_at") VALUES (?, ?, ?, ?) [["title", "Hello Rails"], ["body", "I am
on Rails!"], ["created_at", "2020-01-18 23:47:30.734416"], ["updated_at",
"2020-01-18 23:47:30.734416"]]
(0.9ms) commit transaction
=> true
Copiar

El resultado anterior muestra una consulta de base de datos. Éste indica que el artículo se ha insertado en
nuestra tabla. Y si tomamos un Mire el objeto de nuevo, vemos que algo interesante ha sucedido: INSERT
INTO "articles" ... article

irb> article
=> #<Article id: 1, title: "Hello Rails", body: "I am on Rails!", created_at:
"2020-01-18 23:47:30", updated_at: "2020-01-18 23:47:30">
Copiar

Ahora se establecen los atributos , , y del objeto. Rails hizo esto por nosotros cuando guardamos el
objeto. id created_at updated_at

Cuando queramos obtener este artículo de la base de datos, podemos llamar a find en el modelo y
pasar el como un argumento: id

irb> Article.find(1)
=> #<Article id: 1, title: "Hello Rails", body: "I am on Rails!", created_at:
"2020-01-18 23:47:30", updated_at: "2020-01-18 23:47:30">
Copiar

Y cuando queremos obtener todos los artículos de la base de datos, podemos llamar a todos en el
modelo:

irb> Article.all
=> #<ActiveRecord::Relation [#<Article id: 1, title: "Hello Rails", body: "I
am on Rails!", created_at: "2020-01-18 23:47:30", updated_at: "2020-01-18
23:47:30">]>
Copiar

Este método devuelve un objeto ActiveRecord::Relation que Puede pensar en una matriz
superpoderosa.

Para obtener más información acerca de los modelos, vea Conceptos básicos de Active Record y
Active Record Query Interface.

Los modelos son la pieza final del rompecabezas MVC. A continuación, conectaremos todos los piezas
juntas.
v7
v7
6.4 Mostrar una lista de artículos

.0
.4
Volvamos a nuestro controlador en , y Cambie la acción para recuperar todos los artículos de la base de

.2
datos: app/controllers/articles_controller.rb index

class ArticlesController < ApplicationController


def index
@articles = Article.all
end
end
Copiar

La vista puede acceder a las variables de instancia del controlador. Eso significa que podemos referencia
en . Vamos a abrir eso y sustituya su contenido por: @articles app/views/articles/index.html.erb

<h1>Articles</h1>

<ul>
<% @articles.each do |article| %>
<li>
<%= article.title %>
</li>
<% end %>
</ul>
Copiar

El código anterior es una mezcla de HTML y ERB. ERB es un sistema de plantillas que evalúa el código
Ruby incrustado en un documento. Aquí, podemos ver dos tipos de ERB etiquetas: y . La etiqueta significa
"evaluar el Ruby adjunto" código." La etiqueta significa "evaluar el código Ruby adjunto, y generar el valor
que devuelve". Cualquier cosa que puedas escribir en un programa regular de Ruby puede ir dentro de
estas etiquetas ERB, aunque generalmente es mejor mantener el contenido de las etiquetas ERB corto,
para facilitar la lectura. <% %> <%= %> <% %> <%= %>

Como no queremos generar el valor devuelto por , hemos incluyó ese código en . Pero, dado que
queremos generar el valor devuelto por (para cada artículo), hemos incluido ese código en
. @articles.each <% %> article.title <%= %>

Podemos ver el resultado final visitando http://localhost:3000. (¡Recuerda que debe estar funcionando!)
Esto es lo que sucede cuando hacemos eso: bin/rails server

1. El navegador realiza una solicitud: .GET http://localhost:3000


2. Nuestra aplicación Rails recibe esta solicitud.
3. El router Rails asigna la ruta raíz a la acción de .indexArticlesController
4. La acción utiliza el modelo para recuperar todos los artículos de la base de datos.indexArticle
5. Rails representa automáticamente la vista.app/views/articles/index.html.erb
6. El código ERB de la vista se evalúa para generar HTML.
7. El servidor envía una respuesta que contiene el HTML al navegador.

Hemos conectado todas las piezas MVC juntas, y tenemos nuestro primer controlador ¡acción! A
continuación, pasaremos a la segunda acción.
v7
v7
7 CRUDit donde CRUDit se debe

.0
.4
Casi todas las aplicaciones web implican operaciones CRUD (Crear, Leer, Actualizar y Eliminar). Tú

.2
incluso puede encontrar que la mayoría del trabajo que realiza su aplicación es CRUD. Carriles reconoce
esto y proporciona muchas características para ayudar a simplificar el código que realiza CRUD.

Comencemos a explorar estas características agregando más funcionalidad a nuestro aplicación.

7.1 Mostrar un solo artículo


Actualmente tenemos una vista que enumera todos los artículos de nuestra base de datos. Vamos a
añadir un Nueva vista que muestra el título y el cuerpo de un solo artículo.

Comenzamos agregando una nueva ruta que se asigna a una nueva acción del controlador (que agregará
siguiente). Abra e inserte la última ruta que se muestra aquí: config/routes.rb

Rails.application.routes.draw do
root "articles#index"

get "/articles", to: "articles#index"


get "/articles/:id", to: "articles#show"
end
Copiar

La nueva ruta es otra ruta, pero tiene algo extra en su camino: . Esto designa un parámetro de ruta. Un
parámetro de ruta captura un segmento de la ruta de acceso de la solicitud, y pone ese valor en el Hash,
que es accesible por la acción del controlador. Por ejemplo, al manejar una solicitud como , se capturaría
como el valor de , que sería accesible como en la acción de . get :id params GET
http://localhost:3000/articles/1 1 :id params[:id] show ArticlesController

Agreguemos esa acción ahora, debajo de la acción en


: show index app/controllers/articles_controller.rb

class ArticlesController < ApplicationController


def index
@articles = Article.all
end

def show
@article = Article.find(params[:id])
end
end
Copiar

Las llamadas a la acción (mencionadas anteriormente) con el ID capturado por el parámetro route. El
artículo devuelto se almacena en la variable de instancia, por lo que es accesible por la vista. De forma
predeterminada, la acción representará
. show Article.find @article show app/views/articles/show.html.erb

Vamos a crear , con los siguientes contenidos: app/views/articles/show.html.erb


v7
v7
.0
<h1><%= @article.title %></h1>

.4
.2
<p><%= @article.body %></p>
Copiar

¡Ahora podemos ver el artículo cuando visitemos http://localhost:3000/articles/1!

Para terminar, agreguemos una forma conveniente de llegar a la página de un artículo. Enlazaremos El
título de cada artículo en su página: app/views/articles/index.html.erb

<h1>Articles</h1>

<ul>
<% @articles.each do |article| %>
<li>
<a href="/articles/<%= article.id %>">
<%= article.title %>
</a>
</li>
<% end %>
</ul>
Copiar

7.2 Enrutamiento ingenioso


Hasta ahora, hemos cubierto la "R" (Leer) de CRUD. Eventualmente cubriremos la "C" (Crear), "U"
(Actualizar) y "D" (Eliminar). Como habrás adivinado, haremos Por lo tanto, agregando nuevas rutas,
acciones de controlador y vistas. Siempre que tengamos tal combinación de rutas, acciones del
controlador y vistas que funcionan juntas para realizar operaciones CRUD en una entidad, llamamos a
esa entidad un recurso. Para Por ejemplo, en nuestra aplicación, diríamos que un artículo es un recurso.

Rails proporciona un método de rutas denominado resources que asigna todas las rutas convencionales
para una colección de recursos, como Artículos. Entonces, antes de proceder a las secciones "C", "U" y
"D", reemplacemos Las dos rutas en con: get config/routes.rb resources

Rails.application.routes.draw do
root "articles#index"

resources :articles
end
Copiar

Podemos inspeccionar qué rutas están mapeadas ejecutando el comando: bin/rails routes

$ bin/rails routes
Prefix Verb URI Pattern Controller#Action
root GET / articles#index
articles GET /articles(.:format) articles#index
new_article GET /articles/new(.:format) articles#new
v7
v7
article GET /articles/:id(.:format) articles#show

.0
POST /articles(.:format) articles#create

.4
edit_article GET /articles/:id/edit(.:format) articles#edit

.2
PATCH /articles/:id(.:format) articles#update
DELETE /articles/:id(.:format) articles#destroy
Copiar

El método también configura métodos auxiliares de URL y ruta que podemos usar para evitar que nuestro
código dependa de una configuración de ruta específica. Los valores en la columna "Prefijo" anterior más
un sufijo de o forma los nombres de estos ayudantes. Por ejemplo, el ayudante regresa cuando se le da
un artículo. Podemos usarlo para ordenar nuestro Enlaces en
: resources _url _path article_path "/articles/#
{article.id}" app/views/articles/index.html.erb

<h1>Articles</h1>

<ul>
<% @articles.each do |article| %>
<li>
<a href="<%= article_path(article) %>">
<%= article.title %>
</a>
</li>
<% end %>
</ul>
Copiar

Sin embargo, llevaremos esto un paso más allá utilizando el ayudante link_to . El ayudante representa
un vínculo con su primer argumento como el texto del enlace y su segundo argumento como destino del
enlace. Si pasamos un El objeto Model como segundo argumento, llamará a la ruta de acceso adecuada
ayudante para convertir el objeto en una ruta de acceso. Por ejemplo, si pasamos un artículo, llamaremos
a . Así se convierte: link_to link_to link_to article_path app/views/articles/index.html.erb

<h1>Articles</h1>

<ul>
<% @articles.each do |article| %>
<li>
<%= link_to article.title, article %>
</li>
<% end %>
</ul>
Copiar

¡Muy bien!

Para obtener más información sobre el enrutamiento, consulte Enrutamiento de rieles de afuera hacia
adentro.

7.3 Creación de un nuevo artículo


v7
v7
Ahora pasamos a la "C" (Crear) de CRUD. Normalmente, en aplicaciones web, La creación de un nuevo

.0
recurso es un proceso de varios pasos. Primero, el usuario solicita un formulario para rellenar. A

.4
continuación, el usuario envía el formulario. Si no hay errores, entonces el Se crea un recurso y se

.2
muestra algún tipo de confirmación. De lo contrario, el formulario se vuelve a mostrar con mensajes de
error y el proceso se repite.

En una aplicación Rails, estos pasos son manejados convencionalmente por un controlador y acciones.
Agreguemos una implementación típica de estas acciones a , debajo de la
acción: new create app/controllers/articles_controller.rb show

class ArticlesController < ApplicationController


def index
@articles = Article.all
end

def show
@article = Article.find(params[:id])
end

def new
@article = Article.new
end

def create
@article = Article.new(title: "...", body: "...")

if @article.save
redirect_to @article
else
render :new, status: :unprocessable_entity
end
end
end
Copiar

La acción crea una instancia de un nuevo artículo, pero no lo guarda. Este artículo se utilizará en la vista
al crear el formulario. De forma predeterminada, la acción render , que crearemos a
continuación. new new app/views/articles/new.html.erb

La acción crea una instancia de un nuevo artículo con valores para el título y cuerpo, e intenta salvarlo. Si
el artículo se guarda correctamente, la acción Redirige el navegador a la página del artículo en . De lo
contrario, la acción vuelve a mostrar el formulario representando con el código de estado 422 Entidad no
procesable. El título y el cuerpo aquí son valores ficticios. Después de crear el formulario, vendremos
volver y cambiar estos. create "http://localhost:3000/articles/#
{@article.id}" app/views/articles/new.html.erb

redirect_to hará que el navegador realice una nueva solicitud, mientras que render representa la
vista especificada para la solicitud actual. Es importante usarlo después de mutar el estado de la base de
datos o la aplicación. De lo contrario, si el usuario actualiza la página, el navegador realizará la misma
solicitud y se repetirá la mutación. redirect_to
v7
v7
7.3.1 Uso de un creador de formularios

.0
.4
Usaremos una característica de Rails llamada creador de formularios para crear nuestro formulario.

.2
Usando Un generador de formularios, podemos escribir una cantidad mínima de código para generar un
formulario que sea totalmente configurado y sigue las convenciones de Rails.

Vamos a crear con los siguientes contenidos: app/views/articles/new.html.erb

<h1>New Article</h1>

<%= form_with model: @article do |form| %>


<div>
<%= form.label :title %><br>
<%= form.text_field :title %>
</div>

<div>
<%= form.label :body %><br>
<%= form.text_area :body %>
</div>

<div>
<%= form.submit %>
</div>
<% end %>
Copiar

El método auxiliar form_with crea instancias de un generador de formularios. En el bloque llamamos


Métodos como label y text_field en el generador de formularios para generar los elementos de
formulario adecuados. form_with

El resultado de nuestra llamada se verá así: form_with

<form action="/articles" accept-charset="UTF-8" method="post">


<input type="hidden" name="authenticity_token" value="...">

<div>
<label for="article_title">Title</label><br>
<input type="text" name="article[title]" id="article_title">
</div>

<div>
<label for="article_body">Body</label><br>
<textarea name="article[body]" id="article_body"></textarea>
</div>

<div>
<input type="submit" name="commit" value="Create Article" data-disable-
with="Create Article">
v7
v7
</div>

.0
</form>

.4
Copiar

.2
Para obtener más información sobre los creadores de formularios, vea Ayudantes de formularios de
Action View.

7.3.2 Uso de parámetros fuertes

Los datos del formulario enviado se colocan en el hash, junto con la ruta capturada Parámetros. Por lo
tanto, la acción puede acceder al título presentado a través y al cuerpo enviado a través de . Podríamos
pasar estos valores individualmente a , pero eso sería detallado y posiblemente propenso a errores. Y
empeoraría a medida que agreguemos más Campos. params create params[:article]
[:title] params[:article][:body] Article.new

En su lugar, pasaremos un solo Hash que contenga los valores. Sin embargo, debemos aún así
especifique qué valores están permitidos en ese Hash. De lo contrario, un usuario malintencionado podría
enviar campos de formulario adicionales y sobrescribir datos privados. En realidad si pasamos el Hash sin
filtrar directamente a , Los rieles se levantarán para alertarnos sobre el problema. Así que usaremos una
característica de Rails llamada Strong Parameters para filtrar. Piense en ello como una escritura fuerte
para . params[:article] Article.new ForbiddenAttributesError params params

Agreguemos un método privado al final del nombre que filtra . Y cambiemos para usar
eso: app/controllers/articles_controller.rb article_params params create

class ArticlesController < ApplicationController


def index
@articles = Article.all
end

def show
@article = Article.find(params[:id])
end

def new
@article = Article.new
end

def create
@article = Article.new(article_params)

if @article.save
redirect_to @article
else
render :new, status: :unprocessable_entity
end
end

private
def article_params
params.require(:article).permit(:title, :body)
v7
v7
end

.0
end

.4
Copiar

.2
Para obtener más información sobre los parámetros seguros, consulte Información general sobre el
controlador de acciones § Parámetros fuertes.

7.3.3 Validaciones y visualización de mensajes de error

Como hemos visto, crear un recurso es un proceso de varios pasos. Manejo no válido La entrada del
usuario es otro paso de ese proceso. Rails proporciona una función llamada validaciones para ayudarnos
a lidiar con la entrada de usuario no válida. Las validaciones son reglas que se comprueban antes de
guardar un objeto de modelo. Si alguna de las comprobaciones falla, el Se anulará el guardado y se
agregarán los mensajes de error apropiados al atributo del objeto de modelo. errors

Agreguemos algunas validaciones a nuestro modelo en: app/models/article.rb

class Article < ApplicationRecord


validates :title, presence: true
validates :body, presence: true, length: { minimum: 10 }
end
Copiar

La primera validación declara que un valor debe estar presente. Dado que es una cadena, esto significa
que el valor debe contener al menos una Carácter sin espacios en blanco. title title title

La segunda validación declara que un valor también debe estar presente. Además, declara que el valor
debe tener al menos 10 caracteres largo. body body

Es posible que se pregunte dónde se definen los atributos y. Active Record define automáticamente los
atributos del modelo para cada columna de la tabla, por lo que No es necesario declarar esos atributos en
el archivo de modelo. title body

Con nuestras validaciones en su lugar, modifiquemos a Mostrar los mensajes de error para y
: app/views/articles/new.html.erb title body

<h1>New Article</h1>

<%= form_with model: @article do |form| %>


<div>
<%= form.label :title %><br>
<%= form.text_field :title %>
<% @article.errors.full_messages_for(:title).each do |message| %>
<div><%= message %></div>
<% end %>
</div>

<div>
<%= form.label :body %><br>
<%= form.text_area :body %><br>
<% @article.errors.full_messages_for(:body).each do |message| %>
v7
v7
<div><%= message %></div>

.0
<% end %>

.4
</div>

.2
<div>
<%= form.submit %>
</div>
<% end %>
Copiar

El método full_messages_for devuelve una matriz de mensajes de error descriptivos para un atributo.
Si no hay errores para ese atributo, la matriz estará vacía.

Para entender cómo funciona todo esto en conjunto, echemos otro vistazo a las acciones del
controlador: new create

def new
@article = Article.new
end

def create
@article = Article.new(article_params)

if @article.save
redirect_to @article
else
render :new, status: :unprocessable_entity
end
end
Copiar

Cuando visitamos http://localhost:3000/articles/new, la solicitud se asigna a la acción. La acción no


intenta guardar . Por lo tanto, las validaciones no se comprueban y no habrá ningún error Mensajes. GET
/articles/new new new @article

Cuando enviamos el formulario, la solicitud se asigna a la acción. La acción intenta guardar . Por lo tanto
Se comprueban las validaciones. Si alguna validación falla, no será guardado y se procesará con error
Mensajes. POST /articles create create @article @article app/views/articles/new.html.erb

Para obtener más información sobre las validaciones, consulte Validaciones de registros activos. Para
obtener más información sobre los mensajes de error de validación, consulte Validaciones de registros
activos § Trabajo con errores de validación.

7.3.4 Terminando

Ahora podemos crear un artículo visitando http://localhost:3000/articles/new. Para terminar, vamos a


enlazar a esa página desde la parte inferior de : app/views/articles/index.html.erb

<h1>Articles</h1>

<ul>
v7
v7
<% @articles.each do |article| %>

.0
<li>

.4
<%= link_to article.title, article %>

.2
</li>
<% end %>
</ul>

<%= link_to "New Article", new_article_path %>


Copiar

7.4 Actualización de un artículo


Hemos cubierto el "CR" de CRUD. Ahora pasemos a la "U" (Actualización). Actualización Un recurso es
muy similar a crear un recurso. Ambos son de varios pasos Procesos. En primer lugar, el usuario solicita
un formulario para editar los datos. A continuación, el usuario envía el formulario. Si no hay errores, el
recurso se actualiza. Más El formulario se vuelve a mostrar con mensajes de error y se repite el proceso.

Estos pasos son manejados convencionalmente por un controlador y acciones. Agreguemos una
implementación típica de estas acciones a , debajo de la
acción: edit update app/controllers/articles_controller.rb create

class ArticlesController < ApplicationController


def index
@articles = Article.all
end

def show
@article = Article.find(params[:id])
end

def new
@article = Article.new
end

def create
@article = Article.new(article_params)

if @article.save
redirect_to @article
else
render :new, status: :unprocessable_entity
end
end

def edit
@article = Article.find(params[:id])
end

def update
@article = Article.find(params[:id])
v7
v7
if @article.update(article_params)

.0
redirect_to @article

.4
else

.2
render :edit, status: :unprocessable_entity
end
end

private
def article_params
params.require(:article).permit(:title, :body)
end
end
Copiar

Observe cómo las acciones y se parecen a las acciones y. edit update new create

La acción recupera el artículo de la base de datos y lo almacena para que se pueda usar al generar el
formulario. De forma predeterminada, la acción representará
. edit @article edit app/views/articles/edit.html.erb

La acción (re)recupera el artículo de la base de datos e intenta para actualizarlo con los datos del
formulario enviado filtrados por . Si no Las validaciones fallan y la actualización se realiza correctamente,
la acción redirige el navegador a la página del artículo. De lo contrario, la acción vuelve a mostrar el
formulario, con error mensajes: mediante la representación
. update article_params app/views/articles/edit.html.erb

7.4.1 Uso de parciales para compartir código de vista


Nuestra forma se verá igual que nuestra forma. Incluso el código será el Lo mismo, gracias al creador de
formularios Rails y al enrutamiento ingenioso. El generador de formularios configura automáticamente el
formulario para realizar el tipo adecuado de solicitud, basado en sobre si el objeto de modelo se ha
guardado previamente. edit new

Debido a que el código será el mismo, vamos a factorizarlo en un vista llamada parcial. Vamos a crear con
Los siguientes contenidos: app/views/articles/_form.html.erb

<%= form_with model: article do |form| %>


<div>
<%= form.label :title %><br>
<%= form.text_field :title %>
<% article.errors.full_messages_for(:title).each do |message| %>
<div><%= message %></div>
<% end %>
</div>

<div>
<%= form.label :body %><br>
<%= form.text_area :body %><br>
<% article.errors.full_messages_for(:body).each do |message| %>
<div><%= message %></div>
<% end %>
</div>
v7
v7
.0
<div>

.4
<%= form.submit %>

.2
</div>
<% end %>
Copiar

El código anterior es el mismo que nuestro formulario en , excepto que todas las apariciones de han sido
reemplazadas por . Dado que los parciales son código compartido, se recomienda que no dependan de
Variables de instancia específicas establecidas por una acción de controlador. En su lugar, pasaremos el
artículo al parcial como variable local. app/views/articles/new.html.erb @article article

Actualicemos para usar el renderizado parcial vía: app/views/articles/new.html.erb

<h1>New Article</h1>

<%= render "form", article: @article %>


Copiar

El nombre de archivo de un parcial debe ir precedido de un guión bajo, por ejemplo, . Pero al renderizar,
se hace referencia sin el subrayado, por ejemplo, . _form.html.erb render "form"

Y ahora, vamos a crear un muy similar: app/views/articles/edit.html.erb

<h1>Edit Article</h1>

<%= render "form", article: @article %>


Copiar

Para obtener más información sobre los parciales, consulte Diseños y representación en rieles § Uso
Parciales.

7.4.2 Terminando
Ahora podemos actualizar un artículo visitando su página de edición, por ejemplo,
http://localhost:3000/articles/1/edit. Para terminar, vamos a enlazar a la edición desde la parte inferior
de : app/views/articles/show.html.erb

<h1><%= @article.title %></h1>

<p><%= @article.body %></p>

<ul>
<li><%= link_to "Edit", edit_article_path(@article) %></li>
</ul>
Copiar

7.5 Eliminación de un artículo


v7
v7
Finalmente, llegamos a la "D" (Eliminar) de CRUD. Eliminar un recurso es más sencillo que crear o

.0
actualizar. Solo requiere una ruta y un controlador acción. Y nuestro ingenioso enrutamiento () ya

.4
proporciona el ruta, que asigna solicitudes a la acción de . resources :articles DELETE

.2
/articles/:id destroy ArticlesController

Entonces, agreguemos una acción típica a , debajo de la


acción: destroy app/controllers/articles_controller.rb update

class ArticlesController < ApplicationController


def index
@articles = Article.all
end

def show
@article = Article.find(params[:id])
end

def new
@article = Article.new
end

def create
@article = Article.new(article_params)

if @article.save
redirect_to @article
else
render :new, status: :unprocessable_entity
end
end

def edit
@article = Article.find(params[:id])
end

def update
@article = Article.find(params[:id])

if @article.update(article_params)
redirect_to @article
else
render :edit, status: :unprocessable_entity
end
end

def destroy
@article = Article.find(params[:id])
@article.destroy

redirect_to root_path, status: :see_other


end
v7
v7
.0
private

.4
def article_params

.2
params.require(:article).permit(:title, :body)
end
end
Copiar

La acción recupera el artículo de la base de datos y llama a destruirlo . Luego, redirige el navegador a
la ruta raíz con el código de estado 303 Ver Otro. destroy

Hemos elegido redirigir a la ruta raíz porque ese es nuestro acceso principal punto para artículos. Pero, en
otras circunstancias, puede optar por redirigir a p. ej... articles_path

Ahora agreguemos un enlace en la parte inferior de para que Podemos eliminar un artículo de su propia
página: app/views/articles/show.html.erb

<h1><%= @article.title %></h1>

<p><%= @article.body %></p>

<ul>
<li><%= link_to "Edit", edit_article_path(@article) %></li>
<li><%= link_to "Destroy", article_path(@article), data: {
turbo_method: :delete,
turbo_confirm: "Are you sure?"
} %></li>
</ul>
Copiar

En el código anterior, usamos la opción para establecer los atributos y HTML del enlace "Destruir". Ambos
atributos enganchados a Turbo, que se incluye por por defecto en aplicaciones nuevas de Rails. causará
el para realizar una solicitud en lugar de una solicitud. hará que aparezca un cuadro de diálogo de
confirmación cuando se hace clic en el vínculo. Si el usuario cancela el cuadro de diálogo, la solicitud será
abortado. data data-turbo-method data-turbo-confirm data-turbo-
method="delete" DELETE GET data-turbo-confirm="Are you sure?"

¡Y eso es todo! ¡Ahora podemos enumerar, mostrar, crear, actualizar y eliminar artículos! ¡InCRUDable!

8 Adición de un segundo modelo


Es hora de agregar un segundo modelo a la aplicación. El segundo modelo manejará comentarios sobre
artículos.

8.1 Generación de un modelo


Vamos a ver el mismo generador que usábamos antes al crear el modelo. Esta vez crearemos un modelo
para mantener un Referencia a un artículo. Ejecute este comando en su terminal: Article Comment

$ bin/rails generate model Comment commenter:string body:text


v7
v7
article:references

.0
Copiar

.4
.2
Este comando generará cuatro archivos:

Archivo Propósito

Migración para crear la tabla de comentarios en


db/migrate/20140120201010_create_comments.rb su base de datos (su nombre incluirá una marca
de tiempo diferente)

app/models/comment.rb El modelo de comentarios

prueba/modelos/comment_test.rb Probar el agente para el modelo de comentarios

Ejemplos de comentarios para su uso en


prueba/accesorios/comentarios.yml
pruebas

Primero, eche un vistazo a: app/models/comment.rb

class Comment < ApplicationRecord


belongs_to :article
end
Copiar

Esto es muy similar al modelo que viste anteriormente. La diferencia es la línea , que establece una
asociación de registro activo. Aprenderá un poco sobre las asociaciones en la siguiente sección de esta
guía. Article belongs_to :article

La palabra clave () utilizada en el comando shell es un tipo de datos especial para modelos. Crea una
nueva columna en la tabla de base de datos con el nombre del modelo proporcionado anexado con un
que puede contener valores enteros. Para obtener una mejor comprensión, analice el archivo después de
ejecutar la migración. :references _id db/schema.rb

Además del modelo, Rails también ha realizado una migración para crear el Tabla de base de datos
correspondiente:

class CreateComments < ActiveRecord::Migration[7.0]


def change
create_table :comments do |t|
t.string :commenter
t.text :body
t.references :article, null: false, foreign_key: true

t.timestamps
end
end
end
Copiar
v7
v7
La línea crea una columna entera llamada , un índice para ello, y una restricción de clave externa que

.0
apunta a la columna de la tabla. Continúe y ejecute la

.4
migración: t.references article_id id articles

.2
$ bin/rails db:migrate
Copiar

Rails es lo suficientemente inteligente como para ejecutar solo las migraciones que aún no se han
ejecutado. Ejecute contra la base de datos actual, por lo que en este caso solo verá:

== CreateComments: migrating
=================================================
-- create_table(:comments)
-> 0.0115s
== CreateComments: migrated (0.0119s)
========================================
Copiar

8.2 Asociación de modelos


Las asociaciones de registros activos le permiten declarar fácilmente la relación entre dos modelos. En el
caso de comentarios y artículos, puede escribir el Relaciones de esta manera:

Cada comentario pertenece a un artículo.


Un artículo puede tener muchos comentarios.

De hecho, esto está muy cerca de la sintaxis que Rails utiliza para declarar esto asociación. Ya has visto
la línea de código dentro del modelo (app/models/comment.rb) que hace que cada comentario pertenezca
a un Artículo: Comment

class Comment < ApplicationRecord


belongs_to :article
end
Copiar

Tendrás que editar para agregar el otro lado del asociación: app/models/article.rb

class Article < ApplicationRecord


has_many :comments

validates :title, presence: true


validates :body, presence: true, length: { minimum: 10 }
end
Copiar

Estas dos declaraciones permiten un buen comportamiento automático. Por ejemplo, si Tiene una variable
de instancia que contiene un artículo, puede recuperar Todos los comentarios pertenecientes a ese
artículo como una matriz usando . @article @article.comments
v7
v7
Para obtener más información sobre las asociaciones de registros activos, consulte el Registro activo

.0
Guía de asociaciones.

.4
.2
8.3 Agregar una ruta para comentarios
Al igual que con el controlador, necesitaremos agregar una ruta para que Rails sabe dónde nos gustaría
navegar para ver. Abra el archivo de nuevo y edítelo de la siguiente
manera: articles comments config/routes.rb

Rails.application.routes.draw do
root "articles#index"

resources :articles do
resources :comments
end
end
Copiar

Esto se crea como un recurso anidado dentro de . Esto es Otra parte de capturar la relación jerárquica
que existe entre Artículos y comentarios. comments articles

Para obtener más información sobre el enrutamiento, consulte la guía de enrutamiento de rieles.

8.4 Generación de un controlador


Con el modelo en la mano, puede centrar su atención en crear una coincidencia controlador. Una vez
más, usaremos el mismo generador que usamos antes:

$ bin/rails generate controller Comments


Copiar

Esto crea tres archivos y un directorio vacío:

Archivo/Directorio Propósito

app/controllers/comments_controller.rb El controlador de comentarios

aplicación/vistas/comentarios/ Las vistas del controlador se almacenan aquí

prueba/controladores/comments_controller_test.rb La prueba para el controlador

app/helpers/comments_helper.rb Un archivo auxiliar de vista

Al igual que con cualquier blog, nuestros lectores crearán sus comentarios directamente después leyendo
el artículo, y una vez que hayan agregado su comentario, serán devueltos al artículo mostrar página para
ver su comentario ahora listado. Debido a esto, nuestro está ahí para proporcionar un método para crear
comentarios y eliminar Comentarios de spam cuando llegan. CommentsController

Entonces, primero, conectaremos la plantilla de presentación de artículos () Para hacer un nuevo


comentario: app/views/articles/show.html.erb
v7
v7
.0
<h1><%= @article.title %></h1>

.4
.2
<p><%= @article.body %></p>

<ul>
<li><%= link_to "Edit", edit_article_path(@article) %></li>
<li><%= link_to "Destroy", article_path(@article), data: {
turbo_method: :delete,
turbo_confirm: "Are you sure?"
} %></li>
</ul>

<h2>Add a comment:</h2>
<%= form_with model: [ @article, @article.comments.build ] do |form| %>
<p>
<%= form.label :commenter %><br>
<%= form.text_field :commenter %>
</p>
<p>
<%= form.label :body %><br>
<%= form.text_area :body %>
</p>
<p>
<%= form.submit %>
</p>
<% end %>
Copiar

Esto agrega un formulario en la página de presentación que crea un nuevo comentario por llamando a la
acción. La llamada aquí utiliza una matriz, que creará una ruta anidada, como
. Article CommentsController create form_with /articles/1/comments

Vamos a conectar el en: create app/controllers/comments_controller.rb

class CommentsController < ApplicationController


def create
@article = Article.find(params[:article_id])
@comment = @article.comments.create(comment_params)
redirect_to article_path(@article)
end

private
def comment_params
params.require(:comment).permit(:commenter, :body)
end
end
Copiar

Verá un poco más de complejidad aquí que en el controlador para Artículos. Ese es un efecto secundario
de la anidación que has configurado. Cada solicitud para un comentario tiene que hacer un seguimiento
v7
v7
del artículo al que se adjunta el comentario, De ahí la llamada inicial al método del modelo para obtener el

.0
artículo en cuestión. find Article

.4
.2
Además, el código aprovecha algunos de los métodos disponibles para un asociación. Usamos el método
on para crear y Guarde el comentario. Esto vinculará automáticamente el comentario para que pertenezca
a ese artículo en particular. create @article.comments

Una vez que hemos hecho el nuevo comentario, enviamos al usuario de vuelta al artículo original usando
el ayudante. Como ya hemos visto, esto llama a La acción de la que a su vez representa la plantilla. Aquí
es donde queremos que se muestre el comentario, así que vamos a Agregue eso al archivo
. article_path(@article) show ArticlesController show.html.erb app/views/articles/show.ht
ml.erb

<h1><%= @article.title %></h1>

<p><%= @article.body %></p>

<ul>
<li><%= link_to "Edit", edit_article_path(@article) %></li>
<li><%= link_to "Destroy", article_path(@article), data: {
turbo_method: :delete,
turbo_confirm: "Are you sure?"
} %></li>
</ul>

<h2>Comments</h2>
<% @article.comments.each do |comment| %>
<p>
<strong>Commenter:</strong>
<%= comment.commenter %>
</p>

<p>
<strong>Comment:</strong>
<%= comment.body %>
</p>
<% end %>

<h2>Add a comment:</h2>
<%= form_with model: [ @article, @article.comments.build ] do |form| %>
<p>
<%= form.label :commenter %><br>
<%= form.text_field :commenter %>
</p>
<p>
<%= form.label :body %><br>
<%= form.text_area :body %>
</p>
<p>
<%= form.submit %>
v7
v7
</p>

.0
<% end %>

.4
Copiar

.2
Ahora puede agregar artículos y comentarios a su blog y hacer que aparezcan en el lugares correctos.

9 Refactorización
Ahora que tenemos artículos y comentarios
funcionando, eche un vistazo a la plantilla. Se está
haciendo largo e incómodo. Nosotros Puede usar
parciales para
limpiarlo. app/views/articles/show.html.erb

9.1 Representación de colecciones


parciales
En primer lugar, haremos un comentario parcial
para extraer mostrando todos los comentarios para
el artículo. Cree el archivo y coloque el A
continuación: app/views/comments/_comment.htm
l.erb

<p>
<strong>Commenter:</strong>
<%= comment.commenter %>
</p>

<p>
<strong>Comment:</strong>
<%= comment.body %>
</p>
Copiar

Luego puede cambiar para que se parezca al siguiente: app/views/articles/show.html.erb

<h1><%= @article.title %></h1>

<p><%= @article.body %></p>

<ul>
<li><%= link_to "Edit", edit_article_path(@article) %></li>
<li><%= link_to "Destroy", article_path(@article), data: {
turbo_method: :delete,
turbo_confirm: "Are you sure?"
} %></li>
</ul>

<h2>Comments</h2>
<%= render @article.comments %>
v7
v7
<h2>Add a comment:</h2>

.0
<%= form_with model: [ @article, @article.comments.build ] do |form| %>

.4
<p>

.2
<%= form.label :commenter %><br>
<%= form.text_field :commenter %>
</p>
<p>
<%= form.label :body %><br>
<%= form.text_area :body %>
</p>
<p>
<%= form.submit %>
</p>
<% end %>
Copiar

Esto ahora hará que el parcial en una vez para cada comentario que esté en la colección. A medida que el
método itera sobre la colección, asigna cada Comente a una variable local llamada igual que la parcial, en
este caso , que luego está disponible en el parcial para que la
mostremos. app/views/comments/_comment.html.erb @article.comments render @article.commen
ts comment

9.2 Representación de un formulario parcial


Movamos también esa nueva sección de comentarios a su propia parcial. Una vez más, usted Cree un
archivo que contenga: app/views/comments/_form.html.erb

<%= form_with model: [ @article, @article.comments.build ] do |form| %>


<p>
<%= form.label :commenter %><br>
<%= form.text_field :commenter %>
</p>
<p>
<%= form.label :body %><br>
<%= form.text_area :body %>
</p>
<p>
<%= form.submit %>
</p>
<% end %>
Copiar

Luego haces que el aspecto sea el siguiente: app/views/articles/show.html.erb

<h1><%= @article.title %></h1>

<p><%= @article.body %></p>

<ul>
<li><%= link_to "Edit", edit_article_path(@article) %></li>
v7
v7
<li><%= link_to "Destroy", article_path(@article), data: {

.0
turbo_method: :delete,

.4
turbo_confirm: "Are you sure?"

.2
} %></li>
</ul>

<h2>Comments</h2>
<%= render @article.comments %>

<h2>Add a comment:</h2>
<%= render 'comments/form' %>
Copiar

El segundo renderizado solo define la plantilla parcial que queremos renderizar, . Rails es lo
suficientemente inteligente como para detectar la barra diagonal en eso y date cuenta de que quieres
representar el archivo en el directorio. comments/form _form.html.erb app/views/comments

El objeto está disponible para cualquier parcial representado en la vista porque Lo definimos como una
variable de instancia. @article

9.3 Uso de inquietudes


Las preocupaciones son una forma de hacer que los controladores o modelos grandes sean más fáciles
de entender y administrar. Esto también tiene la ventaja de la reutilización cuando varios modelos (o
controladores) comparten las mismas preocupaciones. Las preocupaciones se implementan utilizando
módulos que contienen métodos que representan una porción bien definida de la funcionalidad de la que
es responsable un modelo o controlador. En otros lenguajes, los módulos a menudo se conocen como
mixins.

Puede usar preocupaciones en su controlador o modelo de la misma manera que usaría cualquier
módulo. Cuando creaste tu aplicación por primera vez con , se crearon dos carpetas dentro junto con el
resto: rails new blog app/

app/controllers/concerns
app/models/concerns
Copiar

En el siguiente ejemplo, implementaremos una nueva característica para nuestro blog que se beneficiaría
del uso de una inquietud. Luego, crearemos una preocupación y refactorizaremos el código para usarlo,
haciendo que el código sea más DRY y fácil de mantener.

Un artículo de blog puede tener varios estados, por ejemplo, puede ser visible para todos (es decir, ), o
solo visible para el autor (es decir, ). También puede estar oculto para todos, pero aún recuperable (es
decir, ). Los comentarios también pueden estar ocultos o visibles. Esto podría representarse usando una
columna en cada modelo. public private archived status

Primero, ejecutemos las siguientes migraciones para agregar a y : status Articles Comments

$ bin/rails generate migration AddStatusToArticles status:string


v7
v7
$ bin/rails generate migration AddStatusToComments status:string

.0
Copiar

.4
.2
Y a continuación, actualicemos la base de datos con las migraciones generadas:

$ bin/rails db:migrate
Copiar

Para obtener más información sobre las migraciones, consulte Migraciones de registros activos.

También tenemos que permitir la clave como parte del parámetro strong,
en: :status app/controllers/articles_controller.rb

private
def article_params
params.require(:article).permit(:title, :body, :status)
end
Copiar

y en : app/controllers/comments_controller.rb

private
def comment_params
params.require(:comment).permit(:commenter, :body, :status)
end
Copiar

Dentro del modelo, después de ejecutar una migración para agregar una columna mediante el comando,
agregaría: article status bin/rails db:migrate

class Article < ApplicationRecord


has_many :comments

validates :title, presence: true


validates :body, presence: true, length: { minimum: 10 }

VALID_STATUSES = ['public', 'private', 'archived']

validates :status, inclusion: { in: VALID_STATUSES }

def archived?
status == 'archived'
end
end
Copiar

y en el modelo: Comment
v7
v7
.0
class Comment < ApplicationRecord

.4
belongs_to :article

.2
VALID_STATUSES = ['public', 'private', 'archived']

validates :status, inclusion: { in: VALID_STATUSES }

def archived?
status == 'archived'
end
end
Copiar

Luego, en nuestra plantilla de acción () usaríamos el método para evitar mostrar cualquier artículo que
esté archivado: index app/views/articles/index.html.erb archived?

<h1>Articles</h1>

<ul>
<% @articles.each do |article| %>
<% unless article.archived? %>
<li>
<%= link_to article.title, article %>
</li>
<% end %>
<% end %>
</ul>

<%= link_to "New Article", new_article_path %>


Copiar

Del mismo modo, en nuestra vista parcial de comentarios () usaríamos el método para evitar mostrar
cualquier comentario que esté archivado: app/views/comments/_comment.html.erb archived?

<% unless comment.archived? %>


<p>
<strong>Commenter:</strong>
<%= comment.commenter %>
</p>

<p>
<strong>Comment:</strong>
<%= comment.body %>
</p>
<% end %>
Copiar

Sin embargo, si vuelve a mirar nuestros modelos ahora, puede ver que la lógica está duplicada. Si en el
futuro aumentamos la funcionalidad de nuestro blog, para incluir mensajes privados, por ejemplo,
v7
v7
podríamos encontrarnos duplicando la lógica una vez más. Aquí es donde las preocupaciones son útiles.

.0
.4
Una preocupación solo es responsable de un subconjunto enfocado de la responsabilidad del modelo; Los

.2
métodos en nuestra preocupación estarán todos relacionados con la visibilidad de un modelo. Llamemos
a nuestra nueva preocupación (módulo) . Podemos crear un nuevo archivo dentro llamado , y almacenar
todos los métodos de estado que se duplicaron en los
modelos. Visible app/models/concerns visible.rb

app/models/concerns/visible.rb

module Visible
def archived?
status == 'archived'
end
end
Copiar

Podemos agregar nuestra validación de estado a la preocupación, pero esto es un poco más complejo ya
que las validaciones son métodos llamados a nivel de clase. La (Guía API) nos da una forma más sencilla
de incluirlos: ActiveSupport::Concern

module Visible
extend ActiveSupport::Concern

VALID_STATUSES = ['public', 'private', 'archived']

included do
validates :status, inclusion: { in: VALID_STATUSES }
end

def archived?
status == 'archived'
end
end
Copiar

Ahora, podemos eliminar la lógica duplicada de cada modelo y en su lugar incluir nuestro nuevo
módulo: Visible

En: app/models/article.rb

class Article < ApplicationRecord


include Visible

has_many :comments

validates :title, presence: true


v7
v7
validates :body, presence: true, length: { minimum: 10 }

.0
end

.4
Copiar

.2
y en : app/models/comment.rb

class Comment < ApplicationRecord


include Visible

belongs_to :article
end
Copiar

Los métodos de clase también se pueden agregar a las preocupaciones. Si queremos mostrar un
recuento de artículos públicos o comentarios en nuestra página principal, podemos agregar un método de
clase a Visible de la siguiente manera:

module Visible
extend ActiveSupport::Concern

VALID_STATUSES = ['public', 'private', 'archived']

included do
validates :status, inclusion: { in: VALID_STATUSES }
end

class_methods do
def public_count
where(status: 'public').count
end
end

def archived?
status == 'archived'
end
end
Copiar

Luego, en la vista, puede llamarlo como cualquier método de clase:

<h1>Articles</h1>

Our blog has <%= Article.public_count %> articles and counting!

<ul>
<% @articles.each do |article| %>
<% unless article.archived? %>
<li>
<%= link_to article.title, article %>
v7
v7
</li>

.0
<% end %>

.4
<% end %>

.2
</ul>

<%= link_to "New Article", new_article_path %>


Copiar

Para terminar, agregaremos un cuadro de selección a los formularios y dejaremos que el usuario
seleccione el estado cuando cree un nuevo artículo o publique un nuevo comentario. También podemos
especificar el estado predeterminado como . En , podemos
añadir: public app/views/articles/_form.html.erb

<div>
<%= form.label :status %><br>
<%= form.select :status, ['public', 'private', 'archived'], selected:
'public' %>
</div>
Copiar

y en : app/views/comments/_form.html.erb

<p>
<%= form.label :status %><br>
<%= form.select :status, ['public', 'private', 'archived'], selected:
'public' %>
</p>
Copiar

10 Eliminación de comentarios
Otra característica importante de un blog es poder eliminar comentarios de spam. Para hacer Esto,
necesitamos implementar un enlace de algún tipo en la vista y una acción en el
. destroy CommentsController

Así que primero, agreguemos el enlace eliminar en el parcial: app/views/comments/_comment.html.erb

<% unless comment.archived? %>


<p>
<strong>Commenter:</strong>
<%= comment.commenter %>
</p>

<p>
<strong>Comment:</strong>
<%= comment.body %>
</p>

<p>
<%= link_to "Destroy Comment", [comment.article, comment], data: {
v7
v7
turbo_method: :delete,

.0
turbo_confirm: "Are you sure?"

.4
} %>

.2
</p>
<% end %>
Copiar

Al hacer clic en este nuevo enlace "Destruir comentario" se disparará un a nuestro , que luego puede Usa
esto para encontrar el comentario que queremos eliminar, así que agreguemos una acción a nuestro
controlador (): DELETE
/articles/:article_id/comments/:id CommentsController destroy app/controllers/comments_
controller.rb

class CommentsController < ApplicationController


def create
@article = Article.find(params[:article_id])
@comment = @article.comments.create(comment_params)
redirect_to article_path(@article)
end

def destroy
@article = Article.find(params[:article_id])
@comment = @article.comments.find(params[:id])
@comment.destroy
redirect_to article_path(@article), status: :see_other
end

private
def comment_params
params.require(:comment).permit(:commenter, :body, :status)
end
end
Copiar

La acción encontrará el artículo que estamos viendo, localice el comentario dentro de la colección y, a
continuación, quítela de la carpeta y envíenos de vuelta a la acción Mostrar para el
artículo. destroy @article.comments

10.1 Eliminación de objetos asociados


Si elimina un artículo, sus comentarios asociados también deberán ser eliminados, de lo contrario
simplemente ocuparían espacio en la base de datos. Rieles permite Usted puede utilizar la opción de una
asociación para lograr esto. Modifique el Modelo de artículo, , según se indica a
continuación: dependent app/models/article.rb

class Article < ApplicationRecord


include Visible

has_many :comments, dependent: :destroy


v7
v7
validates :title, presence: true

.0
validates :body, presence: true, length: { minimum: 10 }

.4
end

.2
Copiar

11 Seguridad

11.1 Autenticación básica


Si publicara su blog en línea, cualquiera podría agregar, editar y Eliminar artículos o eliminar comentarios.

Rails proporciona un sistema de autenticación HTTP que funcionará muy bien en esta situación.

En el necesitamos tener una forma de bloquear el acceso a la varias acciones si la persona no está
autenticada. Aquí podemos utilizar el método Rails, que permite el acceso a lo solicitado si ese método lo
permite. ArticlesController http_basic_authenticate_with

Para usar el sistema de autenticación, lo especificamos en la parte superior de nuestro en . En nuestro


caso, queremos que el usuario se autentique en todas las acciones excepto y , Así que escribimos
que: ArticlesController app/controllers/articles_controller.rb index show

class ArticlesController < ApplicationController

http_basic_authenticate_with name: "dhh", password: "secret", except:


[:index, :show]

def index
@articles = Article.all
end

# snippet for brevity


Copiar

También queremos permitir que solo los usuarios autenticados eliminen comentarios, por lo que en el ()
escribimos: CommentsController app/controllers/comments_controller.rb

class CommentsController < ApplicationController

http_basic_authenticate_with name: "dhh", password: "secret", only: :destroy

def create
@article = Article.find(params[:article_id])
# ...
end

# snippet for brevity


Copiar

Ahora, si intenta crear un nuevo artículo, será recibido con un HTTP básico Desafío de autenticación:
v7
v7
.0
.4
.2
Después de ingresar el nombre de usuario y la contraseña correctos, permanecerá autenticado hasta que
se requiera un nombre de usuario y contraseña diferentes o se cierre el navegador.

Hay otros métodos de autenticación disponibles para las aplicaciones de Rails. Dos populares Los
complementos de autenticación para Rails son el motor de rieles Devise y la joya Authlogic, junto con
varios otros.

11.2 Otras consideraciones de seguridad


La seguridad, especialmente en aplicaciones web, es un área amplia y detallada. Seguridad en su
aplicación Rails se cubre con más profundidad en la Guía de seguridad de Ruby on Rails.

12 ¿Qué sigue?
Ahora que ha visto su primera aplicación de Rails, no dude en Actualízalo y experimenta por tu cuenta.

Recuerde, no tiene que hacer todo sin ayuda. Como necesitas ayuda poniéndose en marcha con Rails, no
dude en consultar estos soportes Recursos:

Las guías de Ruby on Rails


La lista de correo de Ruby on Rails

13 Problemas de configuración
La forma más fácil de trabajar con Rails es almacenar todos los datos externos como UTF-8. Si no lo
haces, las bibliotecas de Ruby y Rails a menudo podrán convertir tu nativo datos en UTF-8, pero esto no
siempre funciona de manera confiable, por lo que es mejor asegurando que todos los datos externos sean
UTF-8.

Si ha cometido un error en esta área, el síntoma más común es un negro Diamante con un signo de
interrogación en el interior que aparece en el navegador. Otro común El síntoma son caracteres como
"Ã8/<>" que aparecen en lugar de "ü". Rails toma un número de pasos internos para mitigar las causas
comunes de estos problemas que pueden ser Detectado y corregido automáticamente. Sin embargo, si
v7
v7
tiene datos externos que son no almacenado como UTF-<>, ocasionalmente puede dar lugar a este tipo

.0
de problemas que Rails no puede detectarlo automáticamente ni corregirlo.

.4
.2
Dos fuentes de datos muy comunes que no son UTF-8:

Su editor de texto: la mayoría de los editores de texto (como TextMate), guardan de forma
predeterminada como UTF-8. Si su editor de texto no lo hace, esto puede resultar en caracteres
que introduce en las plantillas (como é) para que aparezcan como un diamante con un signo de
interrogación dentro del navegador. Esto también se aplica a su i18n archivos de traducción. La
mayoría de los editores que aún no utilizan UTF-8 de forma predeterminada (como algunas
versiones de Dreamweaver) ofrecen una forma de cambiar el valor predeterminado a UTF-8.
Hacer así que.
Su base de datos: Rails convierte de forma predeterminada los datos de su base de datos a
UTF-8 en el límite. Sin embargo, si su base de datos no utiliza UTF-8 internamente, Es posible
que no pueda almacenar todos los caracteres introducidos por los usuarios. Por ejemplo si su
base de datos está utilizando Latin-1 internamente, y su usuario ingresa un ruso, En caracteres
hebreos o japoneses, los datos se perderán para siempre una vez que ingresen. la base de
datos. Si es posible, utilice UTF-8 como almacenamiento interno de la base de datos.

Retroalimentación
Le animamos a ayudar a mejorar la calidad de esta guía.

Por favor, contribuya si ve algún error tipográfico o de hecho. Para comenzar, puede leer nuestra sección
de contribuciones de documentación.

También puede encontrar contenido incompleto o cosas que no están actualizadas. Por favor, agregue
cualquier documentación faltante para main. Asegúrese de revisar primero las guías perimetrales para
verificar si los problemas ya están solucionados o no en la rama principal. Consulte las Pautas de las
guías de Ruby on Rails para conocer el estilo y las convenciones.

Si por alguna razón detecta algo que arreglar pero no puede parchearlo usted mismo, abra un problema.

Y por último, pero no menos importante, cualquier tipo de discusión sobre Ruby on Rails la
documentación es muy bienvenida en el foro oficial de Ruby on Rails.
Esta obra está bajo una licencia Creative Commons Attribution-ShareAlike 4.0 International License

"Rails", "Ruby on Rails" y el logotipo de Rails son marcas comerciales de David Heinemeier Hansson. Todos
los derechos reservados.

También podría gustarte