Para comprender correctamente todo lo que hablaremos en esta serie, es conveniente tener un conocimiento básico sobre el lenguaje de Ruby. Podrás conseguir toda la información desees aquí
Estructura de proyecto
Deben recordar que en múltiples ocasiones hemos dicho que Sinatra nos da la completa libertad de ensamblar las aplicaciones como nosotros queramos. Esto ciertamente es muy bueno (para algunos) pero a su misma vez muy confuso (para otros), ya que no hay una “mejor forma” de hacer las aplicaciones sino que todas son buenas. Es en este punto donde empezamos a leer por internet las mil y un distintas formas para ensamblar una aplicación web en Sinatra “correctamente”; pero la pregunta del millón es:
¿Qué es lo que realmente necesitamos?
Ciertamente, casi todos nosotros tendemos a complicar demasiado las cosas en un punto muy temprano del desarrollo cuando en realidad deberíamos fijar las metas a lograr para poder realizarlo de la manera más sencilla posible e ir ajustando en el proceso. Es aquí cuando surge una nueva interrogante:
¿Por qué no realizamos la aplicación de manera convencional/clásica (sencilla)?
La respuesta es simple, si de antemano conocemos que la aplicación final será bastante reducida en tamaño, tranquilamente podemos iniciar con este modelo de aplicación sin tener que pensarlo demasiado. Por el contrario, si conocemos que será de un tamaño final medio/grande, quizás, como recomendación, evaluar si es mejor ir a algo un poco más estructurado como Rails. La misión al realizar aplicaciones grandes siempre será poder reutilizar componentes para hacerla los más DRY que podamos y esto nos obliga de cierto modo a que la aplicación sea modular donde los componentes o módulos de la aplicación sean middleware. Esto de cierta forma es lo que hicimos en el capítulo anterior cuando hablamos de Subclases.
Para continuar con el tema y reafirmar el conocimiento de la semana pasada pero agregándole cierta complejidad; hoy realizaremos una muy pequeña aplicación modular con estructura similar a la de Ruby on Rails (MVC) pero sin los modelos por ahora.
Estructura
tree . . ├── app │ ├── controllers │ │ ├── application_controller.rb │ │ └── users_controller.rb │ ├── helpers │ │ └── application_helper.rb │ └── views │ ├── users.erb │ ├── layout.erb │ └── not_found.erb └── config.ru12345678910111213 tree├──app│ ├──controllers│ │ ├──application_controllerrb│ │ └──users_controllerrb│ ├──helpers│ │ └──application_helperrb│ └──views│ ├──userserb│ ├──layouterb│ └──not_founderb└──configru
-
En los controladores tenemos el
application_controller
que viene siendo nuestro controlador principal y de donde heredarán todos los demás controladores de la aplicación. Elusers_controller
que contiene las rutas de la aplicación relacionadas con los usuarios. -
Los helpers vienen siendo clases que contienen fragmentos de código reusables y asisten en funcionalidad a los controladores y vistas.
-
Las vistas son los archivos referentes a las distintas pantallas de presentación que ve el usuario y que pueda tener nuestra aplicación.
-
config.ru nombre por convención del archivo utilizado por el servidor web de Ruby: Rack.
Echemos un vistazo al contenido de dichos archivos.
# application_helper.rb module ApplicationHelper def title(value = nil) @title = value if value @title ? "#{@title}" : "Título por defecto" end end12345678 # application_helper.rb module ApplicationHelper def title(value=nil) @title=value ifvalue @title?"#{@title}":"Título por defecto" endend
El application_helper
: es el “helper” principal de la aplicación, se encuentra dentro de un módulo y está encargado de establecer un título a las páginas html que se encuentran dentro de la carpeta de las vistas.
1234567891011121314 # application_controller.rb classApplicationController<Sinatra::Base helpers ApplicationHelper # establece la carpeta de vistas a ../views. set:views,Fileexpand_path('../../views',__FILE__) # despliega las páginas 404 not_found do title'Not Found!' erb:not_found endend
Por lo que podemos ver en el archivo application_controller
al ser el controlador principal de Sinatra hereda de Sinatra::Base
incluye el helper ApplicationHelper
que se encuentra en la carpeta de helpers, establece la ruta de donde se encontrarán las vistas y contiene el manejo de errores para las páginas 404.
12345678910111213 # users_controller.rb classUsersController<ApplicationController get'/'do title"Usuarios" erb:users end get'/:number'do title"Usuario #{params[:number]}" erb:users endend
Aquí podemos ver que users_controller
es un controlador que hereda de application_controller
y a su vez contiene dos rutas de tipo get
donde les establece los títulos a dichas páginas y utiliza la vista users
.
12345678910 # layout.erb <\html> <\head> <\title><%=title%><\/title> <\/head> <\body> <%=yield%> <\/body><\/html>
Este es el esqueleto HTML principal de la aplicación; es reusable por el resto de las vistas de la aplicación con la finalidad de no repetir siempre lo mismo. Cuando creamos otra vista se inyectará su contenido dentro de la etiqueta <%= yield %>
. se pueden crear distintos tipos de esqueletos predefinidos pero cuando se deseen utilizar se le debe indicar a Sinatra manualmente cual es el que se debe usar erb :users, :layout => tro_layout
123 # users.erb Página de usuarios!
Este archivo al igual que el not_found.erb
solo contienen texto.
1234567 # config.ru require'sinatra/base'Dirglob('./app/{helpers,controllers}/*.rb')each{|file|require file} map("/users"){run UsersController}map("/") {run ApplicationController}
Por último y para mi, el más importante del post es el archivo config.ru
, ya que es aquí donde Sinatra genera nuestra aplicación. Primero un require 'sinatra/base
para crear nuestra aplicación modular; segundo por medio del uso de Dir.glob
se realiza un require
de cada uno de los archivos que contenga extensión .rb
, y por último se agregan los módulos cómo middleware, definiendo lo siguiente:
- Todas las rutas que se encuentran dentro del controlador
users_controller.rb
se verán precedidas por el slugusers
. - La ruta principal de la aplicación relacionada con
application_controller.rb
no está haciendo nada particular, únicamente nos desplegará la página 404 como ejemplo.
Hagamos una prueba de nuestra pequeña aplicación.
$ rackup -p 3000 $ curl --request GET localhost:3000 <\html> <\head> <\title>Not Found!<\/title> <\/head> <\body> La página no existe 404! <\/body> <\/html>1234567891011 $rackup-p3000 $curl--request GET localhost:3000<\html> <\head> <\title>NotFound!<\/title> <\/head> <\body> Lapágina no existe404! <\/body><\/html>
Aquí podemos apreciar que al acceder por una ruta que no existe dentro de nuestra aplicación la misma nos arroja la vista not_found.erb
que se encuentra definida en application_controller
.
Ahora probemos las rutas de /users
:
12345678910111213141516171819 $curl--request GET localhost:3000/users<\html> <\head> <\title>Usuarios<\/title> <\/head> <\body> Página de usuarios! <\/body><\/html> $curl--request GET localhost:3000/users/1<\html> <\head> <\title>Usuario1<\/title> <\/head> <\body> Página de usuarios! <\/body><\/html>
A diferencia de la anterior observamos que efectivamente ambas rutas de users_controller.rb
están precedidas por el slug users
aunque dichas rutas no estén escritas así dentro del controlador. La semana entrante veremos otras maneras existentes para agregar middleware y realizar el enrutamiento a nuestra aplicación en Siantra.
Conclusión
En este octavo capítulo, hemos empezado a atar los cabos sueltos que tenemos de capítulos anteriores; aprendiendo a estructurar una aplicación en Sinatra de manera modular asemejando la estructura de una aplicación Rails y a su vez hemos puesto a prueba una primera parte de enrutamiento en base a middleware el cual expandiremos la próxima semana. Si te surge algún tipo de duda no te detengas y déjanos un comentario, que gustosamente lo responderemos.
¡Hasta el próximo capítulo!