Revista Informática

Sinatra desde Cero: Estructura de proyecto

Publicado el 05 diciembre 2013 por Codehero @codeheroblog

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.ru

12345678910111213 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. El users_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 end

12345678 # 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.

# application_controller.rb class ApplicationController < Sinatra::Base helpers ApplicationHelper # establece la carpeta de vistas a ../views. set :views, File.expand_path('../../views', __FILE__) # despliega las páginas 404 not_found do title 'Not Found!' erb :not_found end end

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.

# users_controller.rb class UsersController < ApplicationController get '/' do title "Usuarios" erb :users end get '/:number' do title "Usuario #{params[:number]}" erb :users end end

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.

# layout.erb <\html> <\head> <\title><%= title %><\/title> <\/head> <\body> <%= yield %> <\/body> <\/html>

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 => :o tro_layout

# users.erb Página de usuarios!

123 # users.erb Página de usuarios!

Este archivo al igual que el not_found.erb solo contienen texto.

# config.ru require 'sinatra/base' Dir.glob('./app/{helpers,controllers}/*.rb').each { |file| require file } map("/users") { run UsersController } map("/") { run ApplicationController }

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 slug users.
  • 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:

$ 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>Usuario 1<\/title> <\/head> <\body> Página de usuarios! <\/body> <\/html>

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!


Volver a la Portada de Logo Paperblog

Dossier Paperblog