<%= note.content %> "> [editar]
/ completar ">?
Creado: <%= note.created_at %>
Bienvenido a la Pista 2 de Cantando con Sinatra. En la primera parte, revisamos las rutas, cómo trabajar con los parámetros de URI, cómo trabajar con los formularios y cómo Sinatra diferencia las rutas por el método HTTP por el que fueron solicitadas. Hoy, vamos a ampliar nuestro conocimiento de Sinatra mediante la creación de una pequeña aplicación basada en bases de datos, "Recall", para tomar notas / hacer una lista de tareas pendientes..
Vamos a utilizar una base de datos SQLite para almacenar las notas, y usaremos el DataMapper RubyGem para comunicarnos con la base de datos. Ejecuta lo siguiente dentro de un shell para instalar las gemas relevantes:
gema instalar sqlite3 datamapper dm-sqlite-adapter
Dependiendo de cómo haya configurado RubyGems en su sistema, es posible que necesite un prefijo instalación de gemas
con sudo
.
Comencemos de inmediato creando un nuevo directorio para el proyecto y creando el archivo de la aplicación., recordar.rb
. Comience por requerir las gemas relevantes:
requieren 'rubygems' requieren 'sinatra' requieren 'datamapper'
Nota: Si está ejecutando Ruby 1.9 (que debería ser), puede eliminar la línea de "requeridos 'rubygems'", ya que Ruby carga automáticamente RubyGems de todos modos.
Y configura la base de datos con lo siguiente:
DataMapper :: setup (: predeterminado, "sqlite3: // # Dir.pwd /recall.db") clase Nota incluye DataMapper :: Resource property: id, Serial property: content, Text,: required => true property: complete, Boolean,: required => true,: default => false property: created_at, DateTime property: updated_at, DateTime final DataMapper.finalize.auto_upgrade!
En la primera línea, estamos configurando una nueva base de datos SQLite3 en el directorio actual, llamada memoria.db
. Debajo de eso, en realidad estamos configurando una tabla de 'Notas' en la base de datos.
Mientras llamamos a la clase 'Nota', DataMapper creará la tabla como 'Notas'. Esto está en consonancia con una convención que Ruby on Rails y otros marcos y módulos ORM siguen.
Dentro de la clase, estamos configurando el esquema de base de datos. La tabla 'Notas' tendrá 5 campos. Un carné de identidad
campo que será una clave principal entera y un incremento automático (esto es lo que significa 'Serie'). UNA contenido
campo que contiene texto, un booleano completar
campo y dos campos de fecha y hora, Creado en
y updated_at
.
La última línea le indica a DataMapper que actualice automáticamente la base de datos para que contenga las tablas y los campos que hemos establecido, y que vuelva a hacerlo si realizamos cambios en el esquema..
Ahora, vamos a crear nuestra página de inicio:
En la parte superior hay un formulario para agregar una nueva nota, y debajo se encuentran todas las notas en la base de datos. Para comenzar, agregue lo siguiente al archivo de la aplicación, recordar.rb
:
get '/' do @notes = Note.all: .order =>: id.desc @title = 'All Notes' erb: home end
Nota IMPORTANTE: Retire el punto ('.
') en :.orden
. (WordPress está interfiriendo con el ejemplo de código.)
En la segunda línea puede ver cómo recuperamos todas las notas de la base de datos. Si ha usado ActiveRecord (el ORM usado en Rails) anteriormente, la sintaxis de DataMapper se sentirá muy familiar. Las notas están asignadas a la @notes
Instancia variable. Es importante usar variables de instancia (las variables que comienzan con una @
) para que sean accesibles desde el archivo de vista.
Establecemos el @título
variable de instancia, y cargar el vistas / home.erb
ver archivo a través del analizador ERB.
Crear el vistas / home.erb
Ver archivo y comenzar con lo siguiente:
<% # display notes %>
Tenemos un formulario simple que se envía a la página de inicio ('/'
), y debajo de eso hay un código ERB que sirve como un marcador de posición por ahora.
El lote de estándares HTML entre ustedes puede haber sufrido un golpe menor después de ver que nuestro archivo de vista de inicio no contiene ningún tipo de documento ni otras etiquetas HTML. Bueno, hay una razón para eso. Crear un layout.erb
archivo en tu puntos de vista/
directorio que contiene lo siguiente:
<%= @title + ' | Recall' %> Recordar
porque estas muy ocupado para recordar
<%= yield %>
Las dos partes interesantes aquí son las líneas 5 y 18. En la línea 5 verá el primer uso del <%=? %>
Etiquetas ERB. <%=
es diferente de lo ordinario <%
ya que imprime lo que hay dentro. Así que aquí estamos mostrando lo que hay en el @título
variable de instancia seguida de | Recordar
para la pagina
etiqueta.
En la linea 18 esta <%= yield %>
. Sinatra mostrará esto layout.erb
archivo en todas las rutas. Y el contenido real para esa ruta se insertará donde sea rendimiento
es. rendimiento
es un término que esencialmente significa "para aquí, inserte lo que esté esperando, luego continúe".
Inicia el servidor con recuerdo de escopeta.rb
en el shell, y eche un vistazo a la página de inicio en el navegador. Debería ver el contenido del archivo de diseño y la forma del archivo real. home.erb
ver.
En el archivo de diseño incluimos dos archivos CSS. Sinatra puede cargar archivos estáticos (por ejemplo, su CSS, JS, imágenes, etc.) desde una carpeta llamada público/
en el directorio raíz. Así que crea ese directorio, y dentro de él dos archivos: reset.css
y style.css
. El reinicio contiene el reinicio de HTML5 Boilerplate CSS:
/ * HTML5? Boilerplate style.css contiene un restablecimiento, la normalización de la fuente y algunos estilos básicos. el crédito se deja donde el crédito es debido. se tomó mucha inspiración de estos proyectos: yui.yahooapis.com/2.8.1/build/base/base.css camendesign.com/design/ praegnanz.de/weblog/htmlcssjs-kickstart * / / * html5doctor.com Restablecer Stylesheet ( Eric Meyer Reset Reloaded + HTML5 baseline) v1.6.1 2010-09-17 | Autores: Eric Meyer y Richard Clark html5doctor.com/html-5-reset-stylesheet/ * / html, body, div, span, object, iframe, h1, h2, h3, h5, h5, h6, p, blockquote, pre , abbr, dirección, cite, código, del, dfn, em, img, ins, kbd, q, samp, pequeño, fuerte, sub, sup, var, b, i, dl, dt, dd, ol, ul, li fieldset, formulario, etiqueta, leyenda, tabla, título, tbody, tfoot, thead, tr, th, td, artículo, aparte, lienzo, detalles, figcaption, figura, pie de página, encabezado, hgroup, menú, navegación, sección, resumen , tiempo, marca, audio, video margen: 0; relleno: 0; borde: 0; tamaño de letra: 100%; fuente: heredar; alineación vertical: línea de base; artículo, aparte, detalles, figcaption, figura, pie de página, encabezado, hgroup, menu, nav, section display: block; blockquote, q quotes: none; blockquote: before, blockquote: after, q: before, q: after content: "; content: none; ins background-color: # ff9; color: # 000; text-decoration: none; mark background -color: # ff9; color: # 000; font-style: cursiva; font-weight: bold; del text-decoration: line-through; abbr [title], dfn [title] border-bottom: 1px punteado; cursor: help; table border-collapse: collapse; border-spacing: 0; hr display: block; altura: 1px; border: 0; border-top: 1px solid #ccc; margin: 1em 0; padding: 0; input, seleccione vertical-align: middle; / * END RESET CSS * / / * normalización de fuentes inspirada en las fuentes de la Biblioteca YUI.css: developer.yahoo.com/yui/ * / body font : 13px / 1.231 sans-serif; * font-size: small; / * truco retenido para preservar la especificidad * / select, input, textarea, button font: 99% sans-serif; / * normalize monospace sizing * en. wikipedia.org/wiki/MediaWiki_talk:Common.css/Archive_11#Teletype_style_fix_for_Chrome * / pre, code, kbd, samp font-family: monospace, sans-serif; / * * minimal b Los estilos ase * / body, select, input, textarea / * # 444 se ve mejor que el negro: twitter.com/H_FJ/statuses/11800719859 * / color: # 444; / * establezca su fuente base aquí, para aplicar uniformemente * / / * font-family: Georgia, serif; Los encabezados * / / * (h1, h2, etc.) no tienen un tamaño o margen de fuente predeterminado. definir esos a ti mismo. * / h1, h2, h3, h4, h5, h6 font-weight: negrita; / * forzar siempre una barra de desplazamiento que no sea IE: * / html overflow-y: scroll; / * tratamiento de enfoque accesible: people.opera.com/patrickl/experiments/keyboard/test * / a: hover, a: active outline: none; a, a: activo, a: visitado color: # 607890; a: hover color: # 036; ul, ol margen izquierdo: 2em; ol tipo de estilo de lista: decimal; / * eliminar márgenes para las listas de navegación * / nav ul, nav li margin: 0; estilo de lista: ninguno; list-style-image: none; pequeño font-size: 85%; fuerte, th font-weight: negrita; td vertical-align: top; / * establecer sub, sup sin afectar la altura de la línea: gist.github.com/413930 * / sub, sup font-size: 75%; línea de altura: 0; posición: relativa; sup arriba: -0.5em; sub inferior: -0.25em; pre / * www.pathf.com/blogs/2008/05/formatting-quoted-code-in-blog-posts-css21-white-space-pre-wrap/ * / white-space: pre; espacio en blanco: pre-envoltura; espacio en blanco: línea previa; ajuste de palabra: palabra de descanso; relleno: 15px; textarea desbordamiento: auto; / * www.sitepoint.com/blogs/2010/08/20/ie-remove-textarea-scrollbars/ * / .ie6 legend, .ie7 legend margin-left: -7px; / * thnx ivannikolic! * / / * alinear casillas de verificación, radios, entradas de texto con su etiqueta por: Thierry Koblentz tjkdesign.com/ez-css/css/base.css * / input [type = "radio"] vertical-align: text-bottom; input [type = "checkbox"] vertical-align: bottom; .ie7 input [type = "checkbox"] vertical-align: baseline; entrada .ie6 vertical-align: text-bottom; / * cursor de la mano en los elementos de entrada en los que se puede hacer clic * / label, input [type = "button"], input [type = "submit"], input [type = "image"], button cursor: pointer; / * los navegadores webkit agregan un margen de 2px fuera del cromo de los elementos del formulario * / button, input, select, textarea margin: 0; / * colores para la validez de formulario * / input: valid, textarea: valid input: invalid, textarea: invalid border-radius: 1px; -moz-box-shadow: 0px 0px 5px rojo; -webkit-box-shadow: 0px 0px 5px rojo; cuadro de sombra: 0px 0px 5px rojo; entrada de .no-boxshadow: no válido, .no-boxshadow textarea: inválido fondo-color: # f0dddd; / * Estas declaraciones de selección tienen que ser separadas. Sin texto de sombra: twitter.com/miketaylr/status/12228805301 También: rosa intenso. * / :: - moz-selection background: # FF5E99; color: #fff; texto-sombra: ninguno; :: selection background: # FF5E99; color: #fff; texto-sombra: ninguno; / * j.mp/webkit-tap-highlight-color * / a: link -webkit-tap-highlight-color: # FF5E99; / * hacer que los botones funcionen bien en IE: www.viget.com/inspire/styling-the-button-element-in-internet-explorer/ * / button width: auto; desbordamiento: visible; / * redimensionamiento bicúbico para IMG de tamaño no nativo: code.flickr.com/blog/2008/11/12/on-ui-quality-the-little-things-client-side-image-resizing/ * / .ie7 img -ms-modo-interpolación: bicúbico;
Y style.css
contiene un estilo básico para que la aplicación se vea bonita:
cuerpo margen: 35px auto; ancho: 640px; header text-align: center; margen: 0 0 20px; header h1 display: inline; tamaño de fuente: 32px; encabezado h1 a: enlace, encabezado h1 a: visitado color: # 444; texto-decoración: ninguno; header h2 font-size: 16px; estilo de letra: cursiva; color: # 999; #main margin: 0 0 20px; #add margen: 0 0 20px; #add textarea altura: 30 px; ancho: 510px; relleno: 10px; borde: 1px sólido #ddd; #add input altura: 50 px; ancho: 100px; margen: -50px 0 0; borde: 1px sólido #ddd; fondo: blanco; #edit textarea altura: 30 px; ancho: 480px; relleno: 10px; borde: 1px sólido #ddd; #edit input [type = submit] height: 50px; ancho: 100px; margen: -50px 0 0; borde: 1px sólido #ddd; fondo: blanco; #edit input [type = checkbox] height: 50px; ancho: 20px; article border: 1px solid #eee; borde superior: ninguno; relleno: 15px 10px; artículo: primero de tipo borde: 1px sólido #eee; artículo: nth-child (even) background: #fafafa; article.complete background: # fedae3; artículo span font-size: 0.8em; p margen: 0 0 5px; .meta font-size: 0.8em; estilo de letra: cursiva; color: # 888; .links font-size: 1.8em; altura de la línea: 0.8em; flotar derecho; margen: -10px 0 0; .links a display: block; texto-decoración: ninguno;
Actualiza la página en tu navegador y todo debería estar más estilizado. No te preocupes demasiado por este CSS; solo hace que las cosas se vean un poco más bonitas!
Ahora mismo, si intenta enviar el formulario en la página de inicio, obtendrá un error de ruta. Vamos a crear la ruta POST para la página de inicio ahora:
post '/' do n = Note.new n.content = params [: content] n.created_at = Time.now n.updated_at = Time.now n.save redirect '/' end
Entonces, cuando se realiza una solicitud de publicación en la página de inicio, creamos un nuevo objeto Note en norte
(Gracias al DataMapper ORM, Nota.nuevo
representa una nueva fila en el notas
tabla en la base de datos). los contenido
campo se establece en los datos enviados desde el área de texto y la Creado en
y updated_at
Los campos de fecha y hora se establecen en la marca de tiempo actual.
La nueva nota se guarda y el usuario vuelve a dirigir a la página de inicio donde se mostrará la nueva nota..
Así que hemos agregado una nueva nota, pero aún no podemos verla en la página de inicio ya que no hemos escrito el código para ella. Dentro de vistas / home.erb
ver archivo, reemplazar el <%# display notes %>
linea con:
<% @notes.each do |note| %>> <% end %><%= note.content %> "> [editar]
/ completar ">?
Creado: <%= note.created_at %>
En la primera línea comenzamos un bucle a través de cada uno de los @notes
(Alternativamente, podríamos haber escrito para nota en @notes
, pero usar un bloque, como estamos aquí, es una mejor práctica). En la línea 2, le damos la una clase de
completar
si la nota actual se establece en completar
. El resto debe ser bastante sencillo..
Así que podemos agregar y ver notas. Ahora solo necesitamos la posibilidad de editarlos y borrarlos..
Usted puede haber notado que en nuestro home.erb
vista establecemos un [editar]
enlace para cada nota a lo que es esencialmente /:carné de identidad
, Así que vamos a crear esa ruta ahora:
get '/: id' do @note = Note.get params [: id] @title = "Edit note ## params [: id]" erb: edit end
Recuperamos la nota solicitada de la base de datos utilizando el ID proporcionado, configuramos un @título
variable, y cargar el vistas / edit.erb
ver archivo a través del analizador ERB.
Ingrese lo siguiente para el vistas / edit.erb
ver:
<% if @note %>
/ eliminar "> Eliminar
<% else %>Nota no encontrada.
<% end %>Esta es una vista bastante simple. Un formulario que apunta a la página actual, un área de texto que contiene el contenido de la nota y una casilla de verificación que se comprueba si la nota está configurada para completar
.
Pero mira la tercera línea. Misterioso. Para explicar esto, tenemos que desviarnos un poco..
Has oído hablar de los dos términos GET y POST..
Pero GET y POST no son los únicos "verbos HTTP"; hay dos más que debe conocer: PUT y DELETE.
Técnicamente, POST solo debe usarse para crear algo, como crear una nueva nota en su nueva aplicación web, por ejemplo.
PUT es el verbo para modificar algo. Y BORRAR, lo has adivinado, es para borrar algo.
Tener estos cuatro verbos es una excelente manera de separar una aplicación. Es logico Desafortunadamente, los navegadores web no admiten las solicitudes PUT o DELETE, por lo que es probable que nunca haya oído hablar de ellas antes..
Entonces, volviendo al camino aquí, si queremos dividir nuestra aplicación de manera lógica (lo que Sinatra recomienda), tenemos que falsificar estas solicitudes PUT y DELETE. Verás nuestros formularios acción
se establece en enviar
. Lo oculto _método
campo de entrada que hemos establecido para poner
en la tercera línea le permite a Sinatra falsificar esta solicitud PUT, mientras que en realidad usa un POST. Los rieles, entre otros marcos, hacen las cosas de manera similar..
Ahora que hemos falsificado nuestra solicitud PUT, podemos crear una ruta para ella:
poner '/: id' do n = Note.get params [: id] n.content = params [: content] n.complete = params [: complete]? 1: 0 n.updated_at = Time.now n.save redirect '/' end
Todo es bastante simple. Obtenemos la nota relevante utilizando el ID en el URI, configuramos los campos a los nuevos valores, guardamos y redirigimos el inicio. Observe cómo en la cuarta línea estamos usando un operador ternario para configurar npleta
a 1
Si params [: completo]
existe, o 0
de otra manera. Esto se debe a que el valor de una casilla de verificación solo se envía con un formulario si está marcado, por lo que simplemente estamos comprobando su existencia.
En nuestro edit.erb
vista, agregamos un enlace 'Eliminar' a lo que es esencialmente la ruta /: id / delete
. Agregue esto a su archivo de aplicación:
get '/: id / delete' do @note = Note.get params [: id] @title = "Confirmar la eliminación de la nota ## params [: id]" erb: delete end
En esta página, recibiremos una confirmación del usuario de que realmente desea eliminar esta nota. Crea el archivo de vista en vistas / borrar.erb
con lo siguiente:
<% if @note %><% else %>¿Estás seguro de que deseas eliminar la siguiente nota: "<%= @note.content %>"?
Nota no encontrada.
<% end %>Tenga en cuenta que al igual que en la forma en que falsificamos una solicitud PUT estableciendo un oculto _método
campo de entrada, ahora estamos falsificando una solicitud DELETE.
Estoy seguro de que ya te has acostumbrado a esto. La ruta de borrado es:
delete '/: id' do n = Note.get params [: id] n.destroy redirect '/' end
¡Pruébalo! Ahora debería poder ver, agregar, editar y eliminar notas. Hay solo una cosa mas?
Ahora mismo si quieres configurar una nota como completar
tienes que ir a la vista Editar y marcar la casilla en esa página. Vamos a hacer ese proceso un poco más simple.
Cuando configuramos la página de inicio principal, incluimos un /: id / complete
enlace en cada nota. Hagamos esa ruta ahora, que simplemente establecerá una nota como completa (o incompleta si ya estaba configurada para completar):
get '/: id / complete' do n = Note.get params [: id] n.complete = n.complete? 0: 1 # voltearlo n.updated_at = Time.now n.save redirect '/' end
¡Tú y Sinatra sacáis un buen dúo! Has escrito muy rápidamente una aplicación web simple que realiza todas las operaciones de CRUD que esperas que haga una aplicación. Está escrito en código Ruby súper sexy y limpio, y está separado en sus partes lógicas.
En la parte final de Singing with Sinatra, el Encore, mejoraremos el manejo de errores, aseguraremos la aplicación de XSS y crearemos una fuente RSS para las notas.
Nota: Puede navegar por los archivos de proyecto finales para este tutorial en GitHub.