1 ¿Qué son los motores?
Los motores pueden considerarse aplicaciones en miniatura que proporcionan funcionalidad a sus aplicaciones anfitrionas. Una aplicación de Rails es en realidad solo un motor "potenciado", con la clase Rails::Application
heredando gran parte de su comportamiento de Rails::Engine
.
Por lo tanto, los motores y las aplicaciones pueden considerarse casi lo mismo, solo con diferencias sutiles, como verás a lo largo de esta guía. Los motores y las aplicaciones también comparten una estructura común.
Los motores también están estrechamente relacionados con los complementos. Ambos comparten una estructura de directorios común en lib
y se generan utilizando el generador rails plugin new
. La diferencia es que un motor es considerado un "complemento completo" por Rails (como se indica por la opción --full
que se pasa al comando del generador). En esta guía, en realidad estaremos utilizando la opción --mountable
, que incluye todas las características de --full
, y algunas más. Esta guía se referirá a estos "complementos completos" simplemente como "motores". Un motor puede ser un complemento, y un complemento puede ser un motor.
El motor que se creará en esta guía se llamará "blorgh". Este motor proporcionará funcionalidad de blogs a sus aplicaciones anfitrionas, permitiendo la creación de nuevos artículos y comentarios. Al principio de esta guía, trabajarás únicamente dentro del motor mismo, pero en las secciones posteriores verás cómo conectarlo a una aplicación.
Los motores también pueden estar aislados de sus aplicaciones anfitrionas. Esto significa que una aplicación puede tener una ruta proporcionada por un ayudante de enrutamiento como articles_path
y utilizar un motor que también proporciona una ruta llamada articles_path
, y los dos no entrarían en conflicto. Además de esto, los controladores, modelos y nombres de tablas también están en espacios de nombres. Verás cómo hacer esto más adelante en esta guía.
Es importante tener en cuenta en todo momento que la aplicación siempre debe tener prioridad sobre sus motores. Una aplicación es el objeto que tiene la última palabra en lo que sucede en su entorno. El motor solo debería mejorarla, en lugar de cambiarla drásticamente.
Para ver demostraciones de otros motores, echa un vistazo a Devise, un motor que proporciona autenticación para sus aplicaciones principales, o Thredded, un motor que proporciona funcionalidad de foro. También está Spree, que proporciona una plataforma de comercio electrónico, y Refinery CMS, un motor de CMS.
Finalmente, los motores no habrían sido posibles sin el trabajo de James Adam, Piotr Sarnacki, el equipo principal de Rails y muchas otras personas. Si alguna vez los conoces, ¡no olvides darles las gracias!
2 Generando un motor
Para generar un motor, deberás ejecutar el generador de complementos y pasarle las opciones adecuadas según sea necesario. Para el ejemplo de "blorgh", deberás crear un motor "montable", ejecutando este comando en una terminal:
$ rails plugin new blorgh --mountable
La lista completa de opciones para el generador de complementos se puede ver escribiendo:
$ rails plugin --help
La opción --mountable
le indica al generador que deseas crear un motor "montable" y aislado en un espacio de nombres. Este generador proporcionará la misma estructura esqueleto que la opción --full
. La opción --full
le indica al generador que deseas crear un motor, incluyendo una estructura esqueleto que proporciona lo siguiente:
- Un árbol de directorios
app
Un archivo
config/routes.rb
:Rails.application.routes.draw do end
Un archivo en
lib/blorgh/engine.rb
, que es idéntico en función al archivoconfig/application.rb
de una aplicación Rails estándar:module Blorgh class Engine < ::Rails::Engine end end
La opción --mountable
agregará a la opción --full
:
- Archivos de manifiesto de activos (
blorgh_manifest.js
yapplication.css
) - Un esqueleto de
ApplicationController
en un espacio de nombres - Un esqueleto de
ApplicationHelper
en un espacio de nombres - Una plantilla de vista de diseño para el motor
Aislamiento de espacio de nombres en
config/routes.rb
:ruby Blorgh::Engine.routes.draw do end
- Aislamiento de espacio de nombres en
lib/blorgh/engine.rb
:
- Aislamiento de espacio de nombres en
module Blorgh
class Engine < ::Rails::Engine
isolate_namespace Blorgh
end
end
Además, la opción --mountable
le indica al generador que monte el motor dentro de la aplicación de prueba dummy ubicada en test/dummy
agregando lo siguiente al archivo de rutas de la aplicación dummy en test/dummy/config/routes.rb
:
mount Blorgh::Engine => "/blorgh"
2.1 Dentro de un motor
2.1.1 Archivos críticos
En la raíz del directorio de este nuevo motor se encuentra un archivo blorgh.gemspec
. Cuando incluyas el motor en una aplicación más adelante, lo harás con esta línea en el archivo Gemfile
de la aplicación Rails:
gem 'blorgh', path: 'engines/blorgh'
No olvides ejecutar bundle install
como de costumbre. Al especificarlo como una gema dentro del Gemfile
, Bundler lo cargará como tal, analizando este archivo blorgh.gemspec
y requiriendo un archivo dentro del directorio lib
llamado lib/blorgh.rb
. Este archivo requiere el archivo blorgh/engine.rb
(ubicado en lib/blorgh/engine.rb
) y define un módulo base llamado Blorgh
.
require "blorgh/engine"
module Blorgh
end
CONSEJO: Algunos motores eligen usar este archivo para colocar opciones de configuración global para su motor. Es una idea relativamente buena, por lo que si quieres ofrecer opciones de configuración, el archivo donde se define el module
de tu motor es perfecto para eso. Coloca los métodos dentro del módulo y estarás listo para continuar.
Dentro de lib/blorgh/engine.rb
se encuentra la clase base para el motor:
module Blorgh
class Engine < ::Rails::Engine
isolate_namespace Blorgh
end
end
Al heredar de la clase Rails::Engine
, esta gema notifica a Rails que hay un motor en la ruta especificada y montará correctamente el motor dentro de la aplicación, realizando tareas como agregar el directorio app
del motor a la ruta de carga para modelos, mailers, controladores y vistas.
El método isolate_namespace
merece una mención especial aquí. Esta llamada es responsable de aislar los controladores, modelos, rutas y otras cosas en su propio espacio de nombres, lejos de los componentes similares dentro de la aplicación. Sin esto, existe la posibilidad de que los componentes del motor puedan "filtrarse" en la aplicación, causando interrupciones no deseadas, o que los componentes importantes del motor puedan ser anulados por cosas con nombres similares dentro de la aplicación. Uno de los ejemplos de tales conflictos son los helpers. Sin llamar a isolate_namespace
, los helpers del motor se incluirían en los controladores de una aplicación.
NOTA: Se recomienda encarecidamente dejar la línea isolate_namespace
dentro de la definición de la clase Engine
. Sin ella, las clases generadas en un motor pueden entrar en conflicto con una aplicación.
Lo que significa este aislamiento del espacio de nombres es que un modelo generado por una llamada a bin/rails generate model
, como bin/rails generate model article
, no se llamará Article
, sino que se llamará Blorgh::Article
. Además, la tabla para el modelo se pondrá en un espacio de nombres, convirtiéndose en blorgh_articles
, en lugar de simplemente articles
. Similar al espacio de nombres del modelo, un controlador llamado ArticlesController
se convierte en Blorgh::ArticlesController
y las vistas para ese controlador no estarán en app/views/articles
, sino en app/views/blorgh/articles
. Los mailers, jobs y helpers también se ponen en un espacio de nombres.
Finalmente, las rutas también se aislarán dentro del motor. Esta es una de las partes más importantes del espacio de nombres y se discute más adelante en la sección de Rutas de esta guía.
2.1.2 Directorio app
Dentro del directorio app
se encuentran los directorios estándar assets
, controllers
, helpers
, jobs
, mailers
, models
y views
con los que deberías estar familiarizado en una aplicación. Miraremos más en detalle los modelos en una sección futura, cuando estemos escribiendo el motor.
Dentro del directorio app/assets
, hay los directorios images
y stylesheets
que, nuevamente, deberías conocer debido a su similitud con una aplicación. Sin embargo, una diferencia aquí es que cada directorio contiene un subdirectorio con el nombre del motor. Debido a que este motor va a tener un espacio de nombres, sus activos también deberían tenerlo.
Dentro del directorio app/controllers
hay un directorio blorgh
que contiene un archivo llamado application_controller.rb
. Este archivo proporcionará cualquier funcionalidad común para los controladores del motor. El directorio blorgh
es donde irán los otros controladores del motor. Al colocarlos dentro de este directorio con espacio de nombres, evitas que puedan entrar en conflicto con controladores de nombres idénticos dentro de otros motores o incluso dentro de la aplicación.
NOTA: La clase ApplicationController
dentro de un motor se llama igual que una aplicación Rails para facilitar la conversión de aplicaciones en motores.
NOTA: Si la aplicación principal se ejecuta en modo classic
, es posible que te encuentres en una situación en la que el controlador del motor herede del controlador de la aplicación principal y no del controlador de la aplicación del motor. La mejor manera de evitar esto es cambiar al modo zeitwerk
en la aplicación principal. De lo contrario, utiliza require_dependency
para asegurarte de que se cargue el controlador de la aplicación del motor. Por ejemplo:
# SOLO NECESARIO EN MODO `classic`.
require_dependency "blorgh/application_controller"
module Blorgh
class ArticlesController < ApplicationController
# ...
end
end
ADVERTENCIA: No uses require
porque romperá la recarga automática de clases en el entorno de desarrollo; usar require_dependency
asegura que las clases se carguen y descarguen de manera correcta.
Al igual que para app/controllers
, encontrarás un subdirectorio blorgh
en los directorios app/helpers
, app/jobs
, app/mailers
y app/models
que contiene el archivo application_*.rb
asociado para recopilar funcionalidades comunes. Al colocar tus archivos en este subdirectorio y darles un espacio de nombres, evitas que puedan entrar en conflicto con elementos de nombre idéntico en otros motores o incluso en la aplicación.
Por último, el directorio app/views
contiene una carpeta layouts
, que contiene un archivo en blorgh/application.html.erb
. Este archivo te permite especificar un diseño para el motor. Si este motor se va a utilizar como un motor independiente, agregarías cualquier personalización a su diseño en este archivo, en lugar del archivo app/views/layouts/application.html.erb
de la aplicación.
Si no quieres imponer un diseño a los usuarios del motor, puedes eliminar este archivo y hacer referencia a un diseño diferente en los controladores de tu motor.
2.1.3 Directorio bin
Este directorio contiene un archivo, bin/rails
, que te permite utilizar los subcomandos y generadores de rails
como lo harías en una aplicación. Esto significa que podrás generar nuevos controladores y modelos para este motor de manera muy fácil ejecutando comandos como este:
$ bin/rails generate model
Ten en cuenta, por supuesto, que cualquier cosa generada con estos comandos dentro de un motor que tenga isolate_namespace
en la clase Engine
estará en un espacio de nombres.
2.1.4 Directorio test
El directorio test
es donde se colocarán las pruebas para el motor. Para probar el motor, hay una versión reducida de una aplicación de Rails incrustada en él en test/dummy
. Esta aplicación montará el motor en el archivo test/dummy/config/routes.rb
:
Rails.application.routes.draw do
mount Blorgh::Engine => "/blorgh"
end
Esta línea monta el motor en la ruta /blorgh
, lo que lo hará accesible a través de la aplicación solo en esa ruta.
Dentro del directorio de pruebas también se encuentra el directorio test/integration
, donde se deben colocar las pruebas de integración para el motor. También se pueden crear otros directorios en el directorio test
. Por ejemplo, es posible que desees crear un directorio test/models
para las pruebas de tus modelos.
3 Proporcionar funcionalidad del motor
El motor que cubre esta guía proporciona funcionalidad para enviar artículos y comentar, y sigue un hilo similar a la Guía de introducción, con algunas novedades.
NOTA: Para esta sección, asegúrate de ejecutar los comandos en la raíz del directorio del motor blorgh
.
3.1 Generar un recurso de artículo
Lo primero que se debe generar para un motor de blog es el modelo Article
y el controlador relacionado. Para generar esto rápidamente, puedes usar el generador de andamios de Rails.
$ bin/rails generate scaffold article title:string text:text
Este comando mostrará esta información:
invoke active_record
create db/migrate/[timestamp]_create_blorgh_articles.rb
create app/models/blorgh/article.rb
invoke test_unit
create test/models/blorgh/article_test.rb
create test/fixtures/blorgh/articles.yml
invoke resource_route
route resources :articles
invoke scaffold_controller
create app/controllers/blorgh/articles_controller.rb
invoke erb
create app/views/blorgh/articles
create app/views/blorgh/articles/index.html.erb
create app/views/blorgh/articles/edit.html.erb
create app/views/blorgh/articles/show.html.erb
create app/views/blorgh/articles/new.html.erb
create app/views/blorgh/articles/_form.html.erb
invoke test_unit
create test/controllers/blorgh/articles_controller_test.rb
create test/system/blorgh/articles_test.rb
invoke helper
create app/helpers/blorgh/articles_helper.rb
invoke test_unit
Lo primero que hace el generador de andamios es invocar al generador active_record
, que genera una migración y un modelo para el recurso. Sin embargo, ten en cuenta que la migración se llama create_blorgh_articles
en lugar de la habitual create_articles
. Esto se debe al método isolate_namespace
llamado en la definición de la clase Blorgh::Engine
. El modelo aquí también tiene un espacio de nombres, ya que se coloca en app/models/blorgh/article.rb
en lugar de app/models/article.rb
, debido a la llamada a isolate_namespace
dentro de la clase Engine
.
A continuación, se invoca el generador test_unit
para este modelo, generando una prueba de modelo en test/models/blorgh/article_test.rb
(en lugar de test/models/article_test.rb
) y un fixture en test/fixtures/blorgh/articles.yml
(en lugar de test/fixtures/articles.yml
).
Después de eso, se inserta una línea para el recurso en el archivo config/routes.rb
del motor. Esta línea es simplemente resources :articles
, convirtiendo el archivo config/routes.rb
del motor en esto:
ruby
Blorgh::Engine.routes.draw do
resources :articles
end
Tenga en cuenta que las rutas se dibujan en el objeto Blorgh::Engine
en lugar de
la clase YourApp::Application
. Esto se hace para que las rutas del motor estén confinadas
al propio motor y se puedan montar en un punto específico como se muestra en la
sección directorio de pruebas. También hace que las rutas del motor
estén aisladas de aquellas rutas que están dentro de la aplicación. La sección
Rutas de esta guía lo describe en detalle.
A continuación, se invoca el generador scaffold_controller
, que genera un controlador
llamado Blorgh::ArticlesController
(en
app/controllers/blorgh/articles_controller.rb
) y sus vistas relacionadas en
app/views/blorgh/articles
. Este generador también genera pruebas para el
controlador (test/controllers/blorgh/articles_controller_test.rb
y test/system/blorgh/articles_test.rb
) y un ayudante (app/helpers/blorgh/articles_helper.rb
).
Todo lo que ha creado este generador está perfectamente enmarcado. La clase del controlador
se define dentro del módulo Blorgh
:
module Blorgh
class ArticlesController < ApplicationController
# ...
end
end
NOTA: La clase ArticlesController
hereda de
Blorgh::ApplicationController
, no del ApplicationController
de la aplicación.
El ayudante dentro de app/helpers/blorgh/articles_helper.rb
también está enmarcado:
module Blorgh
module ArticlesHelper
# ...
end
end
Esto ayuda a evitar conflictos con cualquier otro motor o aplicación que también pueda tener un recurso de artículo.
Puede ver lo que el motor tiene hasta ahora ejecutando bin/rails db:migrate
en la raíz
de nuestro motor para ejecutar la migración generada por el generador de andamios, y luego
ejecutando bin/rails server
en test/dummy
. Cuando abra
http://localhost:3000/blorgh/articles
verá el andamio predeterminado que se ha
generado. ¡Haz clic! Acabas de generar las primeras funciones de tu primer motor.
Si prefieres jugar en la consola, bin/rails console
también funcionará como
una aplicación de Rails. Recuerda: el modelo Article
está enmarcado, así que para
referenciarlo debes llamarlo como Blorgh::Article
.
irb> Blorgh::Article.find(1)
=> #<Blorgh::Article id: 1 ...>
Una cosa final es que el recurso articles
de este motor debería ser la raíz
del motor. Cuando alguien va a la ruta raíz donde se monta el motor,
debería mostrarse una lista de artículos. Esto se puede lograr si
esta línea se inserta en el archivo config/routes.rb
dentro del motor:
root to: "articles#index"
Ahora las personas solo necesitarán ir a la raíz del motor para ver todos los artículos,
en lugar de visitar /articles
. Esto significa que en lugar de
http://localhost:3000/blorgh/articles
, ahora solo necesitas ir a
http://localhost:3000/blorgh
.
3.2 Generando un recurso de comentarios
Ahora que el motor puede crear nuevos artículos, tiene sentido agregar funcionalidad de comentarios también. Para hacer esto, deberás generar un modelo de comentario, un controlador de comentarios y luego modificar el andamio de artículos para mostrar comentarios y permitir a las personas crear nuevos comentarios.
Desde la raíz del motor, ejecuta el generador de modelos. Indícale que genere un
modelo Comment
, con la tabla relacionada que tiene dos columnas: un entero article_id
y una columna de texto text
.
$ bin/rails generate model Comment article_id:integer text:text
Esto mostrará lo siguiente:
invoke active_record
create db/migrate/[timestamp]_create_blorgh_comments.rb
create app/models/blorgh/comment.rb
invoke test_unit
create test/models/blorgh/comment_test.rb
create test/fixtures/blorgh/comments.yml
Esta llamada al generador generará solo los archivos de modelo necesarios,
enmarcando los archivos en un directorio blorgh
y creando una clase de modelo
llamada Blorgh::Comment
. Ahora ejecuta la migración para crear nuestra tabla de blorgh_comments:
$ bin/rails db:migrate
Para mostrar los comentarios en un artículo, edita app/views/blorgh/articles/show.html.erb
y
agrega esta línea antes del enlace "Editar":
<h3>Comentarios</h3>
<%= render @article.comments %>
Esta línea requerirá que haya una asociación has_many
para comentarios definida
en el modelo Blorgh::Article
, que no existe en este momento. Para definir una, abre
app/models/blorgh/article.rb
y agrega esta línea al modelo:
has_many :comments
El modelo quedará así:
module Blorgh
class Article < ApplicationRecord
has_many :comments
end
end
NOTA: Como has_many
se define dentro de una clase que está dentro del
módulo Blorgh
, Rails sabrá que quieres usar el modelo Blorgh::Comment
para estos objetos, por lo que no es necesario especificarlo usando la
opción :class_name
aquí.
A continuación, debe haber un formulario para que se puedan crear comentarios en un artículo. Para
agregar esto, coloca esta línea debajo de la llamada a render @article.comments
en
app/views/blorgh/articles/show.html.erb
:
<%= render "blorgh/comments/form" %>
A continuación, el parcial que esta línea renderizará debe existir. Crea un nuevo
directorio en app/views/blorgh/comments
y dentro de él un nuevo archivo llamado
_form.html.erb
que tenga este contenido para crear el parcial requerido:
html+erb
<h3>Nuevo comentario</h3>
<%= form_with model: [@article, @article.comments.build] do |form| %>
<p>
<%= form.label :text %><br>
<%= form.text_area :text %>
</p>
<%= form.submit %>
<% end %>
Cuando se envía este formulario, intentará realizar una solicitud POST
a una ruta de /articles/:article_id/comments
dentro del motor. Esta ruta no existe en este momento, pero se puede crear cambiando la línea resources :articles
dentro de config/routes.rb
por estas líneas:
resources :articles do
resources :comments
end
Esto crea una ruta anidada para los comentarios, que es lo que requiere el formulario.
Ahora la ruta existe, pero el controlador al que va esta ruta no existe. Para crearlo, ejecute el siguiente comando desde la raíz del motor:
$ bin/rails generate controller comments
Esto generará las siguientes cosas:
create app/controllers/blorgh/comments_controller.rb
invoke erb
exist app/views/blorgh/comments
invoke test_unit
create test/controllers/blorgh/comments_controller_test.rb
invoke helper
create app/helpers/blorgh/comments_helper.rb
invoke test_unit
El formulario realizará una solicitud POST
a /articles/:article_id/comments
, que corresponderá con la acción create
en Blorgh::CommentsController
. Esta acción debe ser creada, lo cual se puede hacer colocando las siguientes líneas dentro de la definición de clase en app/controllers/blorgh/comments_controller.rb
:
def create
@article = Article.find(params[:article_id])
@comment = @article.comments.create(comment_params)
flash[:notice] = "¡El comentario ha sido creado!"
redirect_to articles_path
end
private
def comment_params
params.require(:comment).permit(:text)
end
Este es el último paso necesario para que el formulario de nuevo comentario funcione. Sin embargo, la visualización de los comentarios aún no es del todo correcta. Si creara un comentario en este momento, vería este error:
Falta la vista parcial blorgh/comments/_comment con {:handlers=>[:erb, :builder],
:formats=>[:html], :locale=>[:en, :en]}. Buscado en: *
"/Users/ryan/Sites/side_projects/blorgh/test/dummy/app/views" *
"/Users/ryan/Sites/side_projects/blorgh/app/views"
El motor no puede encontrar la vista parcial requerida para renderizar los comentarios. Rails busca primero en el directorio app/views
de la aplicación (test/dummy
) y luego en el directorio app/views
del motor. Cuando no puede encontrarlo, arrojará este error. El motor sabe que debe buscar blorgh/comments/_comment
porque el objeto del modelo que recibe es de la clase Blorgh::Comment
.
Esta vista parcial será responsable de renderizar solo el texto del comentario, por ahora. Cree un nuevo archivo en app/views/blorgh/comments/_comment.html.erb
y coloque esta línea dentro de él:
<%= comment_counter + 1 %>. <%= comment.text %>
La variable local comment_counter
nos la proporciona la llamada <%= render @article.comments %>
, que la definirá automáticamente e incrementará el contador a medida que itera a través de cada comentario. Se utiliza en este ejemplo para mostrar un pequeño número junto a cada comentario cuando se crea.
Esto completa la función de comentarios del motor de blogs. Ahora es el momento de usarlo dentro de una aplicación.
4 Integración en una aplicación
Usar un motor dentro de una aplicación es muy fácil. Esta sección cubre cómo montar el motor en una aplicación y la configuración inicial requerida, así como vincular el motor a una clase User
proporcionada por la aplicación para proporcionar propiedad de los artículos y comentarios dentro del motor.
4.1 Montar el motor
Primero, el motor debe especificarse dentro del Gemfile
de la aplicación. Si no hay una aplicación disponible para probar esto, genere una usando el comando rails new
fuera del directorio del motor de esta manera:
$ rails new unicorn
Por lo general, especificar el motor dentro del Gemfile
se haría especificándolo como una gema normal y corriente.
gem 'devise'
Sin embargo, debido a que estás desarrollando el motor blorgh
en tu máquina local, deberás especificar la opción :path
en tu Gemfile
:
gem 'blorgh', path: 'engines/blorgh'
Luego ejecuta bundle
para instalar la gema.
Como se describió anteriormente, al colocar la gema en el Gemfile
, se cargará cuando se cargue Rails. Primero requerirá lib/blorgh.rb
del motor, luego lib/blorgh/engine.rb
, que es el archivo que define las principales funcionalidades del motor.
Para que la funcionalidad del motor sea accesible desde una aplicación, debe montarse en el archivo config/routes.rb
de esa aplicación:
mount Blorgh::Engine, at: "/blog"
Esta línea montará el motor en /blog
en la aplicación. Haciéndolo accesible en http://localhost:3000/blog
cuando la aplicación se ejecute con bin/rails server
.
NOTA: Otros motores, como Devise, manejan esto de manera un poco diferente al hacer que especifiques helpers personalizados (como devise_for
) en las rutas. Estos helpers hacen exactamente lo mismo, montando partes de la funcionalidad del motor en una ruta predefinida que puede ser personalizable.
4.2 Configuración del motor
El motor contiene migraciones para las tablas blorgh_articles
y blorgh_comments
que deben crearse en la base de datos de la aplicación para que los modelos del motor puedan consultarlas correctamente. Para copiar estas migraciones en la aplicación, ejecute el siguiente comando desde la raíz de la aplicación:
$ bin/rails blorgh:install:migrations
Si tiene varios motores que necesitan migraciones copiadas, use railties:install:migrations
en su lugar:
$ bin/rails railties:install:migrations
Puede especificar una ruta personalizada en el motor de origen para las migraciones especificando MIGRATIONS_PATH.
$ bin/rails railties:install:migrations MIGRATIONS_PATH=db_blourgh
Si tiene varias bases de datos, también puede especificar la base de datos de destino especificando DATABASE.
$ bin/rails railties:install:migrations DATABASE=animals
Este comando, cuando se ejecuta por primera vez, copiará todas las migraciones del motor. Cuando se ejecuta la próxima vez, solo copiará las migraciones que aún no se hayan copiado. La primera ejecución de este comando mostrará algo como esto:
Copied migration [timestamp_1]_create_blorgh_articles.blorgh.rb from blorgh
Copied migration [timestamp_2]_create_blorgh_comments.blorgh.rb from blorgh
El primer timestamp ([timestamp_1]
) será la hora actual, y el segundo timestamp ([timestamp_2]
) será la hora actual más un segundo. La razón de esto es para que las migraciones del motor se ejecuten después de cualquier migración existente en la aplicación.
Para ejecutar estas migraciones dentro del contexto de la aplicación, simplemente ejecute bin/rails db:migrate
. Al acceder al motor a través de http://localhost:3000/blog
, los artículos estarán vacíos. Esto se debe a que la tabla creada dentro de la aplicación es diferente de la creada dentro del motor. Adelante, juegue con el motor recién montado. Verá que es igual que cuando solo era un motor.
Si desea ejecutar migraciones solo desde un motor, puede hacerlo especificando SCOPE
:
$ bin/rails db:migrate SCOPE=blorgh
Esto puede ser útil si desea revertir las migraciones del motor antes de eliminarlo. Para revertir todas las migraciones del motor blorgh, puede ejecutar un código como este:
$ bin/rails db:migrate SCOPE=blorgh VERSION=0
4.3 Uso de una clase proporcionada por la aplicación
4.3.1 Uso de un modelo proporcionado por la aplicación
Cuando se crea un motor, es posible que desee utilizar clases específicas de una aplicación para establecer vínculos entre las partes del motor y las partes de la aplicación. En el caso del motor blorgh
, tendría mucho sentido que los artículos y los comentarios tuvieran autores.
Una aplicación típica podría tener una clase User
que se utilizaría para representar autores de un artículo o un comentario. Pero podría haber un caso en el que la aplicación llame a esta clase de manera diferente, como Person
. Por esta razón, el motor no debe codificar asociaciones específicamente para una clase User
.
Para mantenerlo simple en este caso, la aplicación tendrá una clase llamada User
que representa a los usuarios de la aplicación (entraremos en cómo hacer esto configurable más adelante). Puede generarse utilizando este comando dentro de la aplicación:
$ bin/rails generate model user name:string
El comando bin/rails db:migrate
debe ejecutarse aquí para asegurarse de que nuestra aplicación tenga la tabla users
para su uso futuro.
Además, para mantenerlo simple, el formulario de los artículos tendrá un nuevo campo de texto llamado author_name
, donde los usuarios pueden elegir poner su nombre. Luego, el motor tomará este nombre y creará un nuevo objeto User
a partir de él, o encontrará uno que ya tenga ese nombre. Luego, el motor asociará el artículo con el objeto User
encontrado o creado.
Primero, el campo de texto author_name
debe agregarse al parcial app/views/blorgh/articles/_form.html.erb
dentro del motor. Esto se puede agregar encima del campo title
con este código:
<div class="field">
<%= form.label :author_name %><br>
<%= form.text_field :author_name %>
</div>
A continuación, debemos actualizar nuestro método Blorgh::ArticlesController#article_params
para permitir el nuevo parámetro del formulario:
def article_params
params.require(:article).permit(:title, :text, :author_name)
end
El modelo Blorgh::Article
debe tener algún código para convertir el campo author_name
en un objeto User
real y asociarlo como el author
de ese artículo antes de que se guarde el artículo. También deberá tener un attr_accessor
configurado para este campo, para que se definan los métodos setter y getter para él.
Para hacer todo esto, deberá agregar el attr_accessor
para author_name
, la asociación para el autor y la llamada before_validation
en app/models/blorgh/article.rb
. La asociación author
se codificará para la clase User
por el momento.
```ruby
attr_accessor :author_name
belongs_to :author, class_name: "User"
before_validation :set_author
private def set_author self.author = User.find_or_create_by(name: author_name) end ```
Al representar el objeto de la asociación author
con la clase User
, se establece un vínculo entre el motor y la aplicación. Debe haber una forma de asociar los registros en la tabla blorgh_articles
con los registros en la tabla users
. Debido a que la asociación se llama author
, se debe agregar una columna author_id
a la tabla blorgh_articles
.
Para generar esta nueva columna, ejecute el siguiente comando dentro del motor:
$ bin/rails generate migration add_author_id_to_blorgh_articles author_id:integer
NOTA: Debido al nombre de la migración y la especificación de la columna después de él, Rails sabrá automáticamente que desea agregar una columna a una tabla específica y lo escribirá en la migración por usted. No necesita decirle más que esto.
Esta migración deberá ejecutarse en la aplicación. Para hacerlo, primero debe copiarse utilizando este comando:
$ bin/rails blorgh:install:migrations
Observe que aquí solo se copió una migración. Esto se debe a que las dos primeras migraciones se copiaron la primera vez que se ejecutó este comando.
NOTA La migración [timestamp]_create_blorgh_articles.blorgh.rb de blorgh se ha omitido. Ya existe una migración con el mismo nombre.
NOTA La migración [timestamp]_create_blorgh_comments.blorgh.rb de blorgh se ha omitido. Ya existe una migración con el mismo nombre.
Se copió la migración [timestamp]_add_author_id_to_blorgh_articles.blorgh.rb de blorgh
Ejecute la migración usando:
$ bin/rails db:migrate
Ahora, con todas las piezas en su lugar, se llevará a cabo una acción que asociará un autor, representado por un registro en la tabla users
, con un artículo, representado por la tabla blorgh_articles
del motor.
Finalmente, el nombre del autor debe mostrarse en la página del artículo. Agregue este código encima de la salida "Title" dentro de app/views/blorgh/articles/show.html.erb
:
<p>
<b>Author:</b>
<%= @article.author.name %>
</p>
4.3.2 Usando un controlador proporcionado por la aplicación
Por lo general, los controladores de Rails comparten código para cosas como la autenticación y el acceso a variables de sesión, por lo que heredan de ApplicationController
de forma predeterminada. Sin embargo, los motores de Rails están diseñados para ejecutarse de forma independiente de la aplicación principal, por lo que cada motor obtiene un ApplicationController
con un ámbito propio. Este espacio de nombres evita colisiones de código, pero a menudo los controladores del motor necesitan acceder a métodos en el ApplicationController
de la aplicación principal. Una forma sencilla de proporcionar este acceso es cambiar el ApplicationController
con ámbito del motor para que herede del ApplicationController
de la aplicación principal. Para nuestro motor Blorgh, esto se haría cambiando app/controllers/blorgh/application_controller.rb
para que se vea así:
module Blorgh
class ApplicationController < ::ApplicationController
end
end
De forma predeterminada, los controladores del motor heredan de Blorgh::ApplicationController
. Por lo tanto, después de realizar este cambio, tendrán acceso al ApplicationController
de la aplicación principal, como si fueran parte de la aplicación principal.
Este cambio requiere que el motor se ejecute desde una aplicación Rails que tenga un ApplicationController
.
4.4 Configurando un motor
Esta sección cubre cómo hacer que la clase User
sea configurable, seguida de consejos de configuración general para el motor.
4.4.1 Configurando opciones de configuración en la aplicación
El siguiente paso es hacer que la clase que representa a un User
en la aplicación sea personalizable para el motor. Esto se debe a que esa clase no siempre será User
, como se explicó anteriormente. Para hacer que esta configuración sea personalizable, el motor tendrá una opción de configuración llamada author_class
que se utilizará para especificar qué clase representa a los usuarios dentro de la aplicación.
Para definir esta opción de configuración, debe utilizar un mattr_accessor
dentro del módulo Blorgh
del motor. Agregue esta línea a lib/blorgh.rb
dentro del motor:
mattr_accessor :author_class
Este método funciona como sus equivalentes, attr_accessor
y cattr_accessor
, pero proporciona un método setter y getter en el módulo con el nombre especificado. Para usarlo, debe hacer referencia a él utilizando Blorgh.author_class
.
El siguiente paso es cambiar el modelo Blorgh::Article
a esta nueva opción. Cambie la asociación belongs_to
dentro de este modelo (app/models/blorgh/article.rb
) a esto:
belongs_to :author, class_name: Blorgh.author_class
El método set_author
en el modelo Blorgh::Article
también debe utilizar esta clase:
self.author = Blorgh.author_class.constantize.find_or_create_by(name: author_name)
Para evitar tener que llamar a constantize
en el resultado de author_class
todo el tiempo, podría simplemente anular el método getter author_class
dentro del módulo Blorgh
en el archivo lib/blorgh.rb
para que siempre llame a constantize
en el valor guardado antes de devolver el resultado:
ruby
def self.author_class
@@author_class.constantize
end
Esto convertiría el código anterior para set_author
en esto:
self.author = Blorgh.author_class.find_or_create_by(name: author_name)
Resultando en algo un poco más corto y más implícito en su comportamiento. El método author_class
siempre debe devolver un objeto Class
.
Dado que cambiamos el método author_class
para devolver una Class
en lugar de una String
, también debemos modificar nuestra definición de belongs_to
en el modelo Blorgh::Article
:
belongs_to :author, class_name: Blorgh.author_class.to_s
Para configurar esta configuración dentro de la aplicación, se debe utilizar un inicializador. Al utilizar un inicializador, la configuración se establecerá antes de que la aplicación comience y llame a los modelos del motor, que pueden depender de que exista esta configuración.
Cree un nuevo inicializador en config/initializers/blorgh.rb
dentro de la aplicación donde se instala el motor blorgh
y coloque este contenido en él:
Blorgh.author_class = "User"
ADVERTENCIA: Es muy importante aquí usar la versión String
de la clase, en lugar de la clase en sí. Si usara la clase, Rails intentaría cargar esa clase y luego hacer referencia a la tabla relacionada. Esto podría causar problemas si la tabla aún no existiera. Por lo tanto, se debe usar una String
y luego convertirla en una clase usando constantize
en el motor más adelante.
Continúe y trate de crear un nuevo artículo. Verá que funciona exactamente de la misma manera que antes, excepto que esta vez el motor está utilizando la configuración en config/initializers/blorgh.rb
para saber cuál es la clase.
Ahora no hay dependencias estrictas sobre cuál es la clase, solo sobre cuál debe ser la API para la clase. El motor simplemente requiere que esta clase defina un método find_or_create_by
que devuelva un objeto de esa clase, para asociarlo con un artículo cuando se crea. Este objeto, por supuesto, debe tener algún tipo de identificador con el que se pueda hacer referencia.
4.4.2 Configuración general del motor
Dentro de un motor, puede llegar un momento en el que desee utilizar cosas como inicializadores, internacionalización u otras opciones de configuración. La gran noticia es que estas cosas son completamente posibles, porque un motor de Rails comparte gran parte de la misma funcionalidad que una aplicación de Rails. De hecho, la funcionalidad de una aplicación de Rails es en realidad un superconjunto de lo que proporcionan los motores.
Si desea utilizar un inicializador, es decir, código que debe ejecutarse antes de que se cargue el motor, el lugar para ello es la carpeta config/initializers
. La funcionalidad de este directorio se explica en la sección Inicializadores de la guía de configuración, y funciona exactamente de la misma manera que el directorio config/initializers
dentro de una aplicación. Lo mismo ocurre si desea utilizar un inicializador estándar.
Para los locales, simplemente coloque los archivos de localización en el directorio config/locales
, al igual que lo haría en una aplicación.
5 Probando un motor
Cuando se genera un motor, se crea una aplicación simulada más pequeña dentro de él en test/dummy
. Esta aplicación se utiliza como punto de montaje para el motor, para facilitar las pruebas del motor. Puede ampliar esta aplicación generando controladores, modelos o vistas desde el directorio, y luego utilizarlos para probar su motor.
El directorio test
debe tratarse como un entorno de prueba típico de Rails, lo que permite realizar pruebas unitarias, funcionales e integradas.
5.1 Pruebas funcionales
Un aspecto que vale la pena tener en cuenta al escribir pruebas funcionales es que las pruebas se ejecutarán en una aplicación, la aplicación test/dummy
, en lugar de en su motor. Esto se debe a la configuración del entorno de prueba; un motor necesita una aplicación como anfitrión para probar su funcionalidad principal, especialmente los controladores. Esto significa que si hiciera un GET
típico a un controlador en una prueba funcional de controlador como esta:
module Blorgh
class FooControllerTest < ActionDispatch::IntegrationTest
include Engine.routes.url_helpers
def test_index
get foos_url
# ...
end
end
end
Es posible que no funcione correctamente. Esto se debe a que la aplicación no sabe cómo enrutar estas solicitudes al motor a menos que se lo indique explícitamente cómo. Para hacer esto, debe establecer la variable de instancia @routes
en el conjunto de rutas del motor en su código de configuración:
module Blorgh
class FooControllerTest < ActionDispatch::IntegrationTest
include Engine.routes.url_helpers
setup do
@routes = Engine.routes
end
def test_index
get foos_url
# ...
end
end
end
Esto le indica a la aplicación que aún desea realizar una solicitud GET
a la acción index
de este controlador, pero desea utilizar la ruta del motor para llegar allí, en lugar de la de la aplicación.
Esto también asegura que los ayudantes de URL del motor funcionarán como se espera en sus pruebas.
6 Mejorando la funcionalidad del motor
Esta sección explica cómo agregar y/o anular la funcionalidad MVC del motor en la aplicación principal de Rails.
6.1 Anulando modelos y controladores
Los modelos y controladores del motor pueden reabrirse en la aplicación principal para extenderlos o decorarlos.
Las anulaciones se pueden organizar en un directorio dedicado app/overrides
, ignorado por el cargador automático y precargado en un callback to_prepare
:
# config/application.rb
module MyApp
class Application < Rails::Application
# ...
overrides = "#{Rails.root}/app/overrides"
Rails.autoloaders.main.ignore(overrides)
config.to_prepare do
Dir.glob("#{overrides}/**/*_override.rb").sort.each do |override|
load override
end
end
end
end
6.1.1 Reabrir clases existentes usando class_eval
Por ejemplo, para anular el modelo del motor
# Blorgh/app/models/blorgh/article.rb
module Blorgh
class Article < ApplicationRecord
# ...
end
end
solo tienes que crear un archivo que reabra esa clase:
# MyApp/app/overrides/models/blorgh/article_override.rb
Blorgh::Article.class_eval do
# ...
end
Es muy importante que la anulación reabra la clase o el módulo. El uso de las palabras clave class
o module
las definiría si no estuvieran en memoria, lo cual sería incorrecto porque la definición se encuentra en el motor. El uso de class_eval
como se muestra arriba asegura que estás reabriendo.
6.1.2 Reabrir clases existentes usando ActiveSupport::Concern
El uso de Class#class_eval
es excelente para ajustes simples, pero para modificaciones de clase más complejas, es posible que desees considerar el uso de ActiveSupport::Concern
. ActiveSupport::Concern administra el orden de carga de módulos y clases dependientes interconectados en tiempo de ejecución, lo que te permite modularizar significativamente tu código.
Agregando Article#time_since_created
y Anulando Article#summary
:
# MyApp/app/models/blorgh/article.rb
class Blorgh::Article < ApplicationRecord
include Blorgh::Concerns::Models::Article
def time_since_created
Time.current - created_at
end
def summary
"#{title} - #{truncate(text)}"
end
end
# Blorgh/app/models/blorgh/article.rb
module Blorgh
class Article < ApplicationRecord
include Blorgh::Concerns::Models::Article
end
end
# Blorgh/lib/concerns/models/article.rb
module Blorgh::Concerns::Models::Article
extend ActiveSupport::Concern
# `included do` hace que el bloque se evalúe en el contexto
# en el que se incluye el módulo (es decir, Blorgh::Article),
# en lugar de en el módulo en sí.
included do
attr_accessor :author_name
belongs_to :author, class_name: "User"
before_validation :set_author
private
def set_author
self.author = User.find_or_create_by(name: author_name)
end
end
def summary
"#{title}"
end
module ClassMethods
def some_class_method
'some class method string'
end
end
end
6.2 Carga automática y motores
Consulta la guía Carga automática y recarga de constantes para obtener más información sobre la carga automática y los motores.
6.3 Anulando vistas
Cuando Rails busca una vista para renderizar, primero buscará en el directorio app/views
de la aplicación. Si no puede encontrar la vista allí, buscará en los directorios app/views
de todos los motores que tengan este directorio.
Cuando se le pide a la aplicación que renderice la vista para la acción index
del controlador Blorgh::ArticlesController
, primero buscará la ruta app/views/blorgh/articles/index.html.erb
dentro de la aplicación. Si no puede encontrarla, buscará dentro del motor.
Puedes anular esta vista en la aplicación simplemente creando un nuevo archivo en app/views/blorgh/articles/index.html.erb
. Luego puedes cambiar completamente lo que esta vista normalmente mostraría.
Prueba esto ahora creando un nuevo archivo en app/views/blorgh/articles/index.html.erb
y coloca este contenido en él:
<h1>Articles</h1>
<%= link_to "New Article", new_article_path %>
<% @articles.each do |article| %>
<h2><%= article.title %></h2>
<small>By <%= article.author %></small>
<%= simple_format(article.text) %>
<hr>
<% end %>
6.4 Rutas
Las rutas dentro de un motor están aisladas de la aplicación de forma predeterminada. Esto se hace mediante la llamada isolate_namespace
dentro de la clase Engine
. Esto significa esencialmente que la aplicación y sus motores pueden tener rutas con nombres idénticos y no entrarán en conflicto.
Las rutas dentro de un motor se definen en la clase Engine
dentro de config/routes.rb
, de esta manera:
Blorgh::Engine.routes.draw do
resources :articles
end
Al tener rutas aisladas como esta, si deseas enlazar a un área de un motor desde dentro de una aplicación, deberás utilizar el método de proxy de enrutamiento del motor. Las llamadas a métodos de enrutamiento normales como articles_path
pueden terminar yendo a ubicaciones no deseadas si tanto la aplicación como el motor tienen un ayudante definido de esa manera.
Por ejemplo, el siguiente ejemplo iría a articles_path
de la aplicación si esa plantilla se renderizara desde la aplicación, o a articles_path
del motor si se renderizara desde el motor:
erb
<%= link_to "Artículos del blog", articles_path %>
Para que esta ruta siempre use el método auxiliar de enrutamiento articles_path
del motor,
debemos llamar al método en el método de proxy de enrutamiento que comparte el mismo nombre que
el motor.
<%= link_to "Artículos del blog", blorgh.articles_path %>
Si desea hacer referencia a la aplicación dentro del motor de manera similar, use
el ayudante main_app
:
<%= link_to "Inicio", main_app.root_path %>
Si esto se usara dentro de un motor, siempre iría a la
raíz de la aplicación. Si se omite la llamada al método de proxy de enrutamiento main_app
,
potencialmente podría ir a la raíz del motor o de la aplicación,
dependiendo de dónde se haya llamado.
Si una plantilla renderizada desde dentro de un motor intenta usar uno de los
métodos auxiliares de enrutamiento de la aplicación, puede resultar en una llamada a un método no definido.
Si encuentra este problema, asegúrese de no intentar llamar a los
métodos de enrutamiento de la aplicación sin el prefijo main_app
desde dentro del
motor.
6.5 Activos
Los activos dentro de un motor funcionan de la misma manera que en una aplicación completa. Debido a que
la clase del motor hereda de Rails::Engine
, la aplicación sabrá buscar activos en los directorios app/assets
y lib/assets
del motor.
Al igual que todos los demás componentes de un motor, los activos deben estar en un espacio de nombres.
Esto significa que si tiene un activo llamado style.css
, debe colocarse en
app/assets/stylesheets/[nombre del motor]/style.css
, en lugar de
app/assets/stylesheets/style.css
. Si este activo no tiene un espacio de nombres, existe la
posibilidad de que la aplicación principal tenga un activo con el mismo nombre, en
cuyo caso el activo de la aplicación tomaría precedencia y se ignoraría el del motor.
Imaginemos que tiene un activo ubicado en
app/assets/stylesheets/blorgh/style.css
. Para incluir este activo en una
aplicación, simplemente use stylesheet_link_tag
y haga referencia al activo como si estuviera dentro del motor:
<%= stylesheet_link_tag "blorgh/style.css" %>
También puede especificar estos activos como dependencias de otros activos utilizando declaraciones de requerimiento del Asset Pipeline en archivos procesados:
/*
*= require blorgh/style
*/
Recuerde que para usar lenguajes como Sass o CoffeeScript,
debe agregar la biblioteca relevante al archivo .gemspec
de su motor.
6.6 Separar activos y precompilación
Hay algunas situaciones en las que los activos de su motor no son necesarios para la
aplicación principal. Por ejemplo, supongamos que ha creado una funcionalidad de administración
que solo existe para su motor. En este caso, la aplicación principal no necesita
requerir admin.css
o admin.js
. Solo el diseño de administración del motor necesita
estos activos. No tiene sentido que la aplicación principal incluya
"blorgh/admin.css"
en sus hojas de estilo. En esta situación, debe
definir explícitamente estos activos para la precompilación. Esto le indica a Sprockets que agregue
los activos del motor cuando se active bin/rails assets:precompile
.
Puede definir activos para la precompilación en engine.rb
:
initializer "blorgh.assets.precompile" do |app|
app.config.assets.precompile += %w( admin.js admin.css )
end
Para obtener más información, lea la guía del Asset Pipeline.
6.7 Otras dependencias de gemas
Las dependencias de gemas dentro de un motor deben especificarse dentro del archivo .gemspec
en la raíz del motor. La razón es que el motor se puede instalar como una
gema. Si las dependencias se especificaran dentro del Gemfile
, estas no se
reconocerían durante una instalación de gemas tradicional y, por lo tanto, no se instalarían,
lo que causaría un mal funcionamiento del motor.
Para especificar una dependencia que se debe instalar con el motor durante una
instalación tradicional de gemas, especifíquela dentro del bloque Gem::Specification
dentro del archivo .gemspec
del motor:
s.add_dependency "moo"
Para especificar una dependencia que solo se debe instalar como una dependencia de desarrollo de la aplicación, especifíquela de esta manera:
s.add_development_dependency "moo"
Ambos tipos de dependencias se instalarán cuando se ejecute bundle install
dentro de
la aplicación. Las dependencias de desarrollo de la gema solo se utilizarán
cuando se ejecuten el desarrollo y las pruebas del motor.
Tenga en cuenta que si desea requerir inmediatamente dependencias cuando se requiere el motor, debe requerirlas antes de la inicialización del motor. Por ejemplo:
require "other_engine/engine"
require "yet_another_engine/engine"
module MyEngine
class Engine < ::Rails::Engine
end
end
7 Ganchos de carga y configuración
El código de Rails a menudo se puede hacer referencia al cargar una aplicación. Rails es responsable del orden de carga de estos frameworks, por lo que cuando carga frameworks, como ActiveRecord::Base
, prematuramente está violando un contrato implícito que su aplicación tiene con Rails. Además, al cargar código como ActiveRecord::Base
al inicio de su aplicación, está cargando frameworks completos que pueden ralentizar el tiempo de inicio y causar conflictos con el orden de carga y el inicio de su aplicación.
Los hooks de carga y configuración son la API que te permite enganchar en este proceso de inicialización sin violar el contrato de carga con Rails. Esto también mitigará la degradación del rendimiento de arranque y evitará conflictos.
7.1 Evitar la carga de los frameworks de Rails
Dado que Ruby es un lenguaje dinámico, algunos códigos harán que se carguen diferentes frameworks de Rails. Por ejemplo, considera este fragmento de código:
ActiveRecord::Base.include(MyActiveRecordHelper)
Este fragmento significa que cuando se cargue este archivo, encontrará ActiveRecord::Base
. Este encuentro hace que Ruby busque la definición de esa constante y la requiera. Esto hace que se cargue todo el framework de Active Record al arrancar.
ActiveSupport.on_load
es un mecanismo que se puede utilizar para retrasar la carga del código hasta que realmente se necesite. El fragmento anterior se puede cambiar a:
ActiveSupport.on_load(:active_record) do
include MyActiveRecordHelper
end
Este nuevo fragmento solo incluirá MyActiveRecordHelper
cuando se cargue ActiveRecord::Base
.
7.2 ¿Cuándo se llaman los hooks?
En el framework de Rails, estos hooks se llaman cuando se carga una biblioteca específica. Por ejemplo, cuando se carga ActionController::Base
, se llama al hook :action_controller_base
. Esto significa que todas las llamadas a ActiveSupport.on_load
con hooks :action_controller_base
se llamarán en el contexto de ActionController::Base
(eso significa que self
será un ActionController::Base
).
7.3 Modificar el código para usar los hooks de carga
Modificar el código generalmente es sencillo. Si tienes una línea de código que se refiere a un framework de Rails como ActiveRecord::Base
, puedes envolver ese código en un hook de carga.
Modificar las llamadas a include
ActiveRecord::Base.include(MyActiveRecordHelper)
se convierte en
ActiveSupport.on_load(:active_record) do
# self se refiere a ActiveRecord::Base aquí,
# por lo que podemos llamar a .include
include MyActiveRecordHelper
end
Modificar las llamadas a prepend
ActionController::Base.prepend(MyActionControllerHelper)
se convierte en
ActiveSupport.on_load(:action_controller_base) do
# self se refiere a ActionController::Base aquí,
# por lo que podemos llamar a .prepend
prepend MyActionControllerHelper
end
Modificar las llamadas a métodos de clase
ActiveRecord::Base.include_root_in_json = true
se convierte en
ActiveSupport.on_load(:active_record) do
# self se refiere a ActiveRecord::Base aquí
self.include_root_in_json = true
end
7.4 Hooks de carga disponibles
Estos son los hooks de carga que puedes usar en tu propio código. Para enganchar en el proceso de inicialización de una de las siguientes clases, utiliza el hook disponible.
Clase | Hook |
---|---|
ActionCable |
action_cable |
ActionCable::Channel::Base |
action_cable_channel |
ActionCable::Connection::Base |
action_cable_connection |
ActionCable::Connection::TestCase |
action_cable_connection_test_case |
ActionController::API |
action_controller_api |
ActionController::API |
action_controller |
ActionController::Base |
action_controller_base |
ActionController::Base |
action_controller |
ActionController::TestCase |
action_controller_test_case |
ActionDispatch::IntegrationTest |
action_dispatch_integration_test |
ActionDispatch::Response |
action_dispatch_response |
ActionDispatch::Request |
action_dispatch_request |
ActionDispatch::SystemTestCase |
action_dispatch_system_test_case |
ActionMailbox::Base |
action_mailbox |
ActionMailbox::InboundEmail |
action_mailbox_inbound_email |
ActionMailbox::Record |
action_mailbox_record |
ActionMailbox::TestCase |
action_mailbox_test_case |
ActionMailer::Base |
action_mailer |
ActionMailer::TestCase |
action_mailer_test_case |
ActionText::Content |
action_text_content |
ActionText::Record |
action_text_record |
ActionText::RichText |
action_text_rich_text |
ActionText::EncryptedRichText |
action_text_encrypted_rich_text |
ActionView::Base |
action_view |
ActionView::TestCase |
action_view_test_case |
ActiveJob::Base |
active_job |
ActiveJob::TestCase |
active_job_test_case |
ActiveRecord::Base |
active_record |
ActiveRecord::TestFixtures |
active_record_fixtures |
ActiveRecord::ConnectionAdapters::PostgreSQLAdapter |
active_record_postgresqladapter |
ActiveRecord::ConnectionAdapters::Mysql2Adapter |
active_record_mysql2adapter |
ActiveRecord::ConnectionAdapters::TrilogyAdapter |
active_record_trilogyadapter |
ActiveRecord::ConnectionAdapters::SQLite3Adapter |
active_record_sqlite3adapter |
ActiveStorage::Attachment |
active_storage_attachment |
ActiveStorage::VariantRecord |
active_storage_variant_record |
ActiveStorage::Blob |
active_storage_blob |
ActiveStorage::Record |
active_storage_record |
ActiveSupport::TestCase |
active_support_test_case |
i18n |
i18n |
7.5 Hooks de configuración disponibles
Los hooks de configuración no se enganchan en ningún framework en particular, sino que se ejecutan en el contexto de toda la aplicación.
Hook | Caso de uso |
---|---|
before_configuration |
Primer bloque configurable que se ejecuta. Se llama antes de que se ejecuten los inicializadores. |
before_initialize |
Segundo bloque configurable que se ejecuta. Se llama antes de que los frameworks se inicialicen. |
before_eager_load |
Tercer bloque configurable que se ejecuta. No se ejecuta si config.eager_load se establece en false. |
after_initialize |
Último bloque configurable que se ejecuta. Se llama después de que los frameworks se inicialicen. |
Los hooks de configuración se pueden llamar en la clase Engine.
module Blorgh
class Engine < ::Rails::Engine
config.before_configuration do
puts 'Soy llamado antes de cualquier inicializador'
end
end
end
Comentarios
Se te anima a ayudar a mejorar la calidad de esta guía.
Por favor, contribuye si encuentras algún error tipográfico o factual. Para empezar, puedes leer nuestra contribución a la documentación sección.
También puedes encontrar contenido incompleto o desactualizado. Por favor, añade cualquier documentación faltante para main. Asegúrate de revisar Edge Guides primero para verificar si los problemas ya están resueltos o no en la rama principal. Consulta las Directrices de las Guías de Ruby on Rails para el estilo y las convenciones.
Si por alguna razón encuentras algo que corregir pero no puedes solucionarlo tú mismo, por favor abre un problema.
Y por último, cualquier tipo de discusión sobre la documentación de Ruby on Rails es muy bienvenida en el Foro oficial de Ruby on Rails.