November 3rd, 2008 por CaDs

La idea detrás de la metodología MVC (Modelo Vista Controlador) consiste en separar en 3 capas independientes, pero interconectadas entre sí aspectos comunes a cualquier aplicación web.
De este modo tenemos las siguientes capas:

  • Modelo:Se encarga de encapsular la entidad que queremos representar y persistirla en memoria de alguna manera (habitualmente una base de datos).
  • Vista:Se encarga de proporcionar al usuario una interfaz para visualizar e introducir información.
  • Controlador:Contiene la lógica que se usará para administrar la información que circulará por el sistema. Es decir, se encargará de realizar las operaciones necesarias para proporcionar información de salida o se encagará de administrar la información que el usuario haya introducido.

La idea detrás de esto es mantener estos tres aspectos de cualquier aplicación independientes entre sí, de manera que un diseñador web pueda trabajar en la interfaz de nuestra aplicación mientras que un equipo de programadores desarrollan la lógica y tal vez un administrador de bases de datos define la mejor manera de almacenar nuestros objetos.

Hasta aquí a teoría, vayamos a la práctica. (Este ejemplo supone que tienes Ruby y Rails instalados)
Rails incorpora esta metodología como parte de su diseño, de manera que trabajando con Rails automáticamente estamos usando MVC.
Comencemos creando un nuevo proyecto de Rails. Abrimos una terminal nueva e introducimos:
rails bookstore
Esto nos generará el esqueleto de una aplicación Rails lista para trabajar.
Ahora para generar nuestros componentes basta con entrar al nuevo directorio que Rails ha creado:
cd bookstore
y escribir el siguiente comando:
./script/generate model book
o
ruby script/generate model book
Según la plataforma que uses y rails se encargará de crear varios archivos:

exists app/models/
exists test/unit/
exists test/fixtures/
create app/models/book.rb
create test/unit/book_test.rb
create test/fixtures/books.yml
create db/migrate
create db/migrate/20081103140957_create_books.rb

En concreto nos interesan los dos archivos resaltados: book.rb y 20081103140957_create_books.rb
Si abrimos con cualquier editor book.rb veremos algo así:


class Book < ActiveRecord::Base
end

Esta aparentemente inofensiva clase incorpora un montón de funciones encapsuladas dentro de ActiveRecord::Base que importa todas las funciones de la clase ActiveRecord.
Dentro de esta clase incorporaremos todas las restricciones y lógica aplicada al modelo, de manera que podemos diseñar independientemente nuestro modelo.

El otro archivo que nos interesa 20081103140957_create_books.rb veremos algo así:


class CreateBooks < ActiveRecord::Migration
  def self.up
    create_table :books do |t|

      t.timestamps
    end
  end

  def self.down
    drop_table :books
  end
end

Donde podemos definir las columnas que formarán parte del objeto que persistiremos en nuestra base de datos. Ej:

 create_table :books do |t|
      t.column :title, :string
      t.column :ISBN, :string
      t.column :author, :string 
      t.timestamps
    end

Con esto tenemos nuestros modelos perfectamente controlados y listos para trabajar.

Ahora, si queremos generar un controlador basta con introducir el siguiente comando en nuestra terminal:
./script/generate controller bookstore

Lo cual al igual que antes, nos generará algunos archivos:

exists app/controllers/
exists app/helpers/
create app/views/bookstore
exists test/functional/
create app/controllers/bookstore_controller.rb
create test/functional/bookstore_controller_test.rb
create app/helpers/bookstore_helper.rb

Como antes el archivo que nos interesa es el llamado bookstore_controller.rb


class BookstoreController < ApplicationController
end

Al igual que antes vemos que esta clase, aparentemente vacía hereda de ApplicationController, lo cual nos permite hace bastantes cosas, entre ellas definir código que va a controlar las vistas que vamos a generar.
Por ejemplo podemos escribir algo como:


class BookstoreController < ApplicationController
  
  def index
    #Codigo para la página bookstore/index.html.erb
  end
  
  def add
    #Codigo para la pagina bookstore/add.html.erb
  end
  
  def remove
    #Codigo para la pagina bookstore/remove.html.erb
  end
  
end

Como podéis ver, los métodos que definimos dentro del controlador tienen efecto sobre ciertas páginas. La idea que hay tras ruby on rails es que este framework se encarga de realizar “todo el cableado interno” entre el controlador y las vistas.

Si nos fijamos en la estructuras de carpetas que nos generó el comando rails vemos que existe la siguiente estructura:

app/view/bookstore

Como vemos Rails nos genera una carpeta para almacenar las vistas asociadas al controlador que hemos creado (bookstore), de manera que podemos crear los archivos que serán nuestras vistas dentro de cada carpeta asociada a un controlador. Ej: index.hml.erb


<p> Hola, esta es la vista para la acción Index </p>

Importante, el nombre de la página debe llamarse igual que el nombre de la acción en el controlador.
Ej. Para el método index, debe existir el archivo index.html.erb, para el método add debe existir el archivo add.html.erb y así sucesivamente.

Si os habéis perdido en estos pasos lo mejor que podéis hacer es jugar un poco con vuestra aplicación de Rails.
Para ello arrancad vuestra aplicación con el siguiente comando:
./script/server
E introducid la siguiente dirección en vuestro browser:
http://localhost:3000/bookstore/index
Si todo ha ido bien debierais ver el texto:

Hola, esta es la vista para la acción Index

Como podemos ver las rutas en rails son bastante simples de entender:
Host/Controller/Action

Listo, ya tenéis una pequeña aplicación usando la metodología MVC. Cierto que no hace gran cosa, pero es un buen punto de partida :)

  • Share/Bookmark
October 30th, 2008 por Antonio Touriño
<script>document.writeln("Hello World!");</script>
  • Share/Bookmark
October 30th, 2008 por Antonio Touriño

Administrar un servidor es una tarea algo engorrosa. Debes asegurarte que los recursos de tu máquina estén siendo utilizados de una manera óptima por tu aplicación. Tienes que cuidar tu máquina de intentos hostiles de acceso. Tienes que analizar los errores que generen tus aplicaciones para ver dónde hay posibles fallos, etc. Todo esto consume tiempo y paciencia ya que todos estos datos generalmente se encuentran desperdigados por diferentes directorios de tu máquina. Si tienes varias máquinas, se pone peor la cosa. Pero no te desesperes, ya que existen algunos programas que te pueden ayudar a monitorear y analizar la ruma de datos que existen en tu servidor que resultan difíciles de procesar manualmente. Aquí te hago una lista de algunas de estas herramientas.

  • monit: Te permite monitorear que todos los servicios que configures tu servidor sean reiniciados si se caen. También puedes hacer que monit verifique que tu servidor web esté sirviendo tus páginas correctamente. Lo puedes configurar para que te mande emails si algo llega a pasar.
  • collectd: Es un recopilador de datos estadísticos de muchos procesos. Te permite guardar esta información para poder visualizarla de diferentes maneras. Uno de los formatos es el RRD-File que es el formato que utiliza el RRDtool.
  • splunk: Splunk es una herramienta que consume informes, logs, en fin, todo dato que genere algún programa y lo procesa para que tu puedas buscar cualquier información que necesites. ¿Quieres saber cuales fueron los últimos 10 intentos fallidos de conexión al puerto de tu servidor SSH? ¿Y además quieres agruparlos por IP? ¿Y además lo quieres agruparlos por horas del día?
  • DenyHosts: Este script sencillo analiza los logs de tu servidor SSH continuamente para detectar muchos intentos de acceso fallidos en poco tiempo con el objetivo de neutralizar los ataques de fuerza bruta. Si DenyHosts encuentra más de cierta cantidad de intentos fallidos en una cantidad determinada de tiempo, crea una regla para denegar paquetes provenientes del IP que ha realizado los intentos. Claro que otra posibilidad para neutralizar este tipo de ataques es utilizando login de llaves únicamente (desactivando el login por medio de passwords).
  • Share/Bookmark
October 26th, 2008 por Jorge Yau

El concepto es sencillo, Hoptoad se encarga de recibir todos los mensajes de error que genere tu aplicación, Hoptoad se encargará de archivarlos y enviarte un reporte, incluso detecta si es un error duplicado y evita enviártelo múltiples veces.

Para esto solo necesitas:

  1. Crear una cuenta gratiuta y Crea tu primer proyecto
  2. Instala el plugin
    script/plugin install git://github.com/thoughtbot/hoptoad_notifier.git
  3. Configura tu aplicación

    Crea un initializer llamado hoptoad.rb en config/initializers/hoptoad.rb y copia lo siguiente:

    
    HoptoadNotifier.configure do |config|
      config.api_key = 'TU API KEY'
    end
    

    Luego añade lo siguiente a tu application controller:

    include HoptoadNotifier::Catcher

Y eso es todo, los errores de tu aplicación serán enviados directamente a tu e-mail.

  • Share/Bookmark
October 23rd, 2008 por CaDs

Cuando hice la migración de PC a Mac, en ocasiones echaba de menos la opción de imprimir pantalla (prt scr). Si bien hay varios programas que se encargan de realizar esta función, Leopard (y de hecho esta función está disponible desde OS X v10.2) viene con una utilidad integrada para tomar capturas de pantalla de diversas maneras.

  • Command-shift-3: Toma una captura de todo el escritorio, igual que la función print screen de windows y guarda el archivo en el Desktop.
  • Command-shift-4: Convierte el cursor en una cruz y nos permite seleccionar el área que deseamos capturar. Al igual que antes, guarda este archivo en el Desktop.
  • Command-shift-4 + space: Para entrar en este modo usad la combinación de antes (Command-shift-4) y cuando el cursor se haya convertido en una cruz, pulsad espacio. El cursor se convertirá en una cámara y nos permitirá realizar una captura completa de la ventana sobre la que coloquemos la cámara.
    Este último modo es particularmente útil para aquellos que trabajen con varias ventanas abiertas en su desktop y sólo quiera capturar una de ellas.
  • Share/Bookmark
October 21st, 2008 por CaDs

Cómo poner a dormir tu macbook es una cuestión de gustos.
En lo personal no me gusta apagar mi computadora, generalmente trabajo con varios programas abiertos a la vez y tener que abrirlos todos cada vez que arranco me da pereza.
Por otro lado, no me gusta el sistema de SafeSleep que viene por defecto en las “nuevas” mac (creo que introdujeron este feature como en otoño de 2005), ya que deja una molesta luz parpadeando y aunque sea poco, sigue consumiendo energía.
Así que aquí os dejo un pequeño comando para cambiar la manera de dormir vuestra macbook.

Para ver el modo en el que hiberna vuestra macbook podéis usar este comando:

$ pmset -g | grep hibernatemode

Si nunca habéis tocado esto generalmente la respuesta debiera ser
hibernatemode 3
Ese es el modo por defecto que traen generalmente las macbooks.
Pero podemos elegir entre diversos modos:

  • 0: Mantiene la RAM activa mientras la computadora duerme, desactiva SafeSleep y se “despierta” en el momento.
  • 1: Sleep mode. Escribe el contenido de la RAM en el disco. El sistema se apaga completamente mientras duerme. Tarda más en despertarse ya que debe copiar el contenido de la RAM desde el disco duro.
  • 3: Safe Sleep. Al igual que el modo 1 copia los contenidos de la RAM al disco, pero mantiene la RAM activa. En el caso de que el sistema se quede sin energía entra en modo hibernación total.
  • 5: Igual que el caso 1, pero sirve para los casos en los que se esté usando Secure Virtual Memory.
  • 7: Igual que el caso 3, pero sirve para los casos en los que se esté usando Secure Virtual Memory.

Elegir un modo u otro depende del uso que les déis a vuestras computadoras.
Para cambiar de modo basta con introducir el comando

sudo pmset -a hibernatemode X

Siendo X el modo deseado. (0,1,3,5 o 7)

  • Share/Bookmark
October 21st, 2008 por CaDs

Según la definición oficial Apache Tapestry es un framework open-source para crear aplicaciones dinámicas, robustas y fácilmente escalables en Java. Según mi humilde definición tapestry 5 hace que programar en Java sea menos malo.

Teniendo una curva de aprendizaje relativamente corta, y siendo fácil de usar, tapestry 5, es una buena opción dentro de la miríada de frameworks de los que Java dispone para hacer aplicaciones web de una manera relativamente sencilla y ligera.
Si bien existe cierta polémica sobre la diferencia entre las diversas versiones y la no compatibilidad entre las mismas (Tapestry 4 no es compatible con Tapestry 5, y eso debe joder bastante), hay mucha gente que está haciendo cosas chulas con este framework.

Aquí voy a escribir los pasos para escribir tu primera aplicación tapestry.
Este pequeño tutorial da por sentado que conoces algo de Java, que conoces Eclipse IDE(un mal necesario), que tienes una ligera noción de lo que es Maven (si no la tienes cuanto antes aprendas mejor, Maven es lo mejor que le ha pasado a Java en mucho tiempo) y que conoces la existencia de Jetty.
Para hacer la cosa más sencilla usaré m2eclipse un plugin que integra Maven con Eclipse a fin de no complicar este tutorial con comandos de consola.
Me salto las instrucciones de instalación del m2eclipse porque es bastante sencillo de instalar y la gente de Apache sin duda lo explica mucho mejor que yo.

Así pues, arrancamos Eclipse, click en New Project, y seleccionamos Maven Project.

Seleccionamos el workspace en el que queramos salvar nuestro proyecto y click en next.

Escribimos tapestry en el Filtro y seleccionamos quickstart

Rellenamos el campo GroupId con el nombre que más os guste, así como el campo ArtifactId que será el nombre de vuestro proyecto (y formarán la estructura básica de los paquetes de la aplicación) y hacemos click en finish.

He aquí el esqueleto de nuestra flamante nueva aplicación:

Si a estas alturas os estáis preguntando que leches es esto no os preocupéis. Maven se encarga de hacer el resto de las cosas. Basta saber que quickstart es el esqueleto de una aplicación que usa tapestry y que viene, entre otras cosas, con un servidor jetty instalado que nos permite arrancar nuestra aplicación en este preciso instante.
Para eso tenemos que configurar nuestro Jetty. Así que vamos a External Tools y hacemos click en External Tools Configurations…

Y rellenamos los siguientes campos:
En la pestaña Main:
Location: La ruta donde se encuentre el ejecutable mvn (generalmente apache-maven-X.Y.Z/bin/mvn)
Working Directory: ${project_loc}
Arguments: jetty:run

En la pestaña Environment:
Creamos una nueva variable llamada MAVEN_OPTS con este valor:
-Xdebug -Xnoagent -Djava.compiler=NONE -Xrunjdwp:transport=dt_socket,address=8080,server=y,suspend=n

Qué hemos hecho hasta ahora? Le estamos diciendo a eclipse cómo arrancar el servidor jetty que trae quickstart usando Maven embebido en el IDE.

Así pues le estamos diciendo que ejecute el comando jetty:run sobre el proyecto seleccionado ${project_loc} con las opciones para Maven -Xdebug -Xnoagent -Djava.compiler=NONE -Xrunjdwp:transport=dt_socket,address=8080,server=y,suspend=n
Hacemos click en Apply y hacemos click en run.
Si os da algún error, es porque estamos usando la variable ${project_loc} y por tanto el comando al arrancar busca un proyecto seleccionado. Así pues seleccionamos nuestro proyecto y volvemos a hacer click en run.
Si todo va bien al introducir http://localhost:8080 en nuestro browser deberíamos ver algo similar a esto:

Hacemos click en el enlace que nos proporciona Jetty y he aquí nuestra primera aplicación Tapestry:

Ok admito que no es precisamente impresionante, pero esta inofensiva pantalla ya es un avance de la potencia de tapestry.
Lo que estamos viendo ahí es un objeto de tipo Date generado cada vez que se recarga la página y presentado en nuestra vista.
Cómo se genera esto?
Simple, cada página en tapestry se compone de una Clase Java y un archivo .tml (Importante, el nombre de la clase java debe ser igual que el del archivo .tml para que tapestry haga la conexión).
En concreto Quickstart viene con la Clase Index.java generada dentro del paquete ${GroupId}.${ArtefactId}.pages y con el archivo Index.tml en la carpeta webapp (src/main/webapp)

Actualmente la clase Index.java contiene lo siguiente:

package com.cadstech.introduction.pages;

import java.util.Date;

/**
 * Start page of application introduction.
 */
public class Index
{
  public Date getCurrentTime() 
  { 
    return new Date(); 
  }
}

Y el contenido de Index.tml es:

<html xmlns:t="http://tapestry.apache.org/schema/tapestry_5_0_0.xsd">
    <head>
        <title>introduction Start Page</title>
    </head>
    <body>
        <h1>introduction Start Page</h1>

        <p> This is the start page for this application, a good place to start your modifications.
            Just to prove this is live: </p>

        <p> The current time is: ${currentTime}. </p>

        <p>
            [<t:pagelink t:page="Index">refresh</t:pagelink>]
        </p>
    </body>
</html>

Aquí es donde podemos comenzar a apreciar algo de la Magia detrás de tapestry.
Nuestro archivo .tml es básicamente código XHTML (ojo, tapestry es bastante pesado con esto, así que al trabajar con vuestras páginas de tapestry tened e cuenta que el código debe ser XML compliant.)

${currentTime} está tratando de obtener el contenido de la variable currentTime para presentarlo en la vista. Como vemos la sintaxis de tapestry es bastante directa.

Sin embargo, Index.java no tiene ninguna variable llamada currentTime, sólo un método con un nombre similar. Bien, realmente al definir ${currentTime} tapestry, al renderizar la página, trata de buscar un get (accedente) para esa variable. Y siguiendo con la tradición java de getters y setters, trata de acceder al método getcurrentTime(), el cual sí está declarado en nuestra clase Java.

El otro elemento perturbador dentro de nuestro archivo .tml es el tag t:
Todos los componentes de tapestry comienzan con t: (tal y como se define en la cabecera xmlns:t=”http://tapestry.apache.org/schema/tapestry_5_0_0.xsd”)
Así pues t:pageLink es un componente de tapestry (algo similar a los helpers en Rails) que nos permite generar html usando simples tags :)

Ya tenemos tapestry 5 funcionando y listo para la acción!

Tapestry 5 dispone de bastantes componentes, podéis revisarlos aqui.
Igualmente dispone de un wiki con bastantes ejemplos prácticos y un par de screencasts.
Para aquellos que le den caña al Java, tapestry 5 viene con integración para Spring (si bien implementa su propio IOC). Permite inyección de Spring Beans dentro de nuestras páginas con una simple notación @Inject (no más líneas de configuración XML) y muchos otros complementos.
Es un framework relativamente joven que comienza a hacerse popular, con una comunidad bastante activa y en general buena documentación.
Si os gusta Java y estáis cansados de los frameworks convencionales probad con tapestry, despues de todo no está nada mal para ser Java ;)

  • Share/Bookmark
October 20th, 2008 por CaDs

Decidir si tu aplicación debe usar UTF-8 encoding es una duda que tarde o temprano asalta a cualquier programador.

Los factores que pueden influir en la decisión de usar o no este tipo de encoding pueden variar, pero en general depende de en dónde vayan a estar localizados los usuarios de tu aplicación.
En el caso de una aplicación web destinado al gran público en general es recomendado habilitar este tipo de encoding para que todo el mundo pueda leer o escribir en cualquier idioma usando cualquier tipografía.
Se podría escribir un libro sobre encoding (de hecho hay bastantes escritos sobre el tema) pero no es el punto de este post.

Supongamos que has decidido construir una aplicación web que revolucionará el mundo y quieres que cualquiera pueda usarla, y has decidido usar Rails para ello (sabia decisión :P ) he aquí los pasos a seguir.

Primero debes indicar a tu browser que tipo de encoding debe interpretar. Para eso basta con insertar un simple tag en la cabezara de tus páginas:

<meta http-equiv="Content-Type" content="text/html; charset=utf-8">

Usar un layout general para toda tu aplicación es en general una manera simple y DRY de hacerlo.

Ahora, suponiendo que tu aplicación use un mecanismo de persistencia (algo bastante habitual) y suponiendo que dicho mecanismo sea una base de datos (bastante habitual tambien) Rails nos permite definir el encoding para nuestra aplicación de una manera bastante simple.
Este ejemplo muestra la configuración para una base de datos mysql.
database.yml:

development:
    adapter: mysql
    database: myapp
    user: root
    host: localhost
    encoding: utf8

Con esto indicamos el encoding para la base de datos, sin embargo en ocasiones y dependiendo de la versión, hay veces que es necesario indicar el encoding de las tablas, las cuales por defecto usan LATIN1.
Para ello basta con agregar en cada migración lo siguiente:
create_users.rb:


   def self.up
    create_table (:users,:options => 'DEFAULT CHARSET=UTF8') do |t|
       ...
   end

Y eso es todo ;)

  • Share/Bookmark
October 18th, 2008 por Jorge Yau

Hace un par de días decidí añadirle la opción de poder publicar anotaciones vía e-mail a una de las aplicaciones en las que estoy trabajando, una opción es tener un proceso automatizado que revise una cuenta de correo cada cierta cantidad de tiempo y luego procesar cualquier correo entrante, la desventaja de esto, es que le estas añadiendo procesos innecesarios a tu servidor, ya que para que funcione en tiempo real, debes revisar la cuenta en un corto intervalo de tiempo, el cual utiliza recursos de tu servidor haya o no mensajes nuevos, hay otras formas, mas complejas que requieren mucha configuración y acceso directo a un servidor SMTP, pero esto no es lo que estaba buscando, lo que necesitaba era una forma rápida y sencilla de procesar correos entrantes de múltiples direcciones de correo, sin sobrecargar mi servidor.

Decidí buscar una alternativa hospedada fuera de mi servidor y que fuera fácil de utilizar sin un alto costo, encontré dos opciones Mailhook.org ($14/año) y smtp2web (gratis), el concepto de ambos, es que se encargan de recibir tu correo, y al recibirlo es reenviado a tu aplicación en forma de POST, este POST incluye todo el mensaje incluyendo ‘headers’ y archivos adjuntos, para ser procesados en tu aplicación de la forma que te plazca. De esta forma tu servidor solo entra en acción cuando un e-mail es recibido.

La decisión no fue muy difícil viendo que ambos servicios son similares, decidí darle una oportunidad a la versión gratuita (smtp2web), además de ser gratuita, el código de la misma aplicación está disponible como código libre. A continuación una breve guia de como utilizar este servicio.

El proceso es sencillo, solo necesitas una cuenta de Google para utilizar el servicio.

Tienes dos opciones, utilizar tu propio dominio o una sola cuenta con el dominio @smtp2web.com, para recibir e-mails con tu propio correo necesitas tener acceso a los ‘MX records’ de tu dominio. 

Para configurar tu dominio en smtp2web, haz click en ‘Add domain mapping’, donde te pedirán el nombre de tu dominio y la dirección en donde vas a recibir el post, el dominio de la dirección de POST debe coincidir con la dirección que utilizas para recibir dominios, por lo tanto debe ser algo como ‘http://post.tudominio.com/emailposting’.

Nota: Todo correo entrante a tudominio.com sera dirigido a smtp2web, si deseas seguir recibiendo correo normal con ese dominio, te recomiendo que utilices un subdominio algo como post.tudominio.com

Luego sigue los pasos para confirmar que el dominio que estas utilizando te pertenece, solo debes subir a tu servidor un archivo vacío con el nombre que smtp2web te va a proporcionar.

El siguiente paso es añadir lo siguiente a tus DNS records:

post.tudominio.com. MX 5 mx1.smtp2web.com.
post.tudominio.com. MX 5 mx2.smtp2web.com.

Si seguiste todos estos pasos correctamente, ya tu aplicación es capaz de recibir e-mails, cualquier e-mail enviado a usuario@post.tudominio.com será automáticamente enviado como un POST a la dirección http://post.tudominio.com/emailposting.

Aún no hemos terminado, tu aplicación necesita entender ese POST.

En PHP es sencillo, solo utiliza el siguiente código.

<?php
$from = htmlentities($_GET['from']);
$to = htmlentities($_GET['to']);
$body = $_POST['body']
/* tu código, insertar a la BD, etc. */
?>

En Ruby on Rails es un poco mas complicado, RoR por motivos de seguridad no permite hacer POST desde otro servidor/aplicación, así que debes añadir lo siguiente al inicio de tu ‘controller’ para pasar por alto esta medida de seguridad en un ‘action’, en este caso, ‘emailposting’.

protect_from_forgery :except => :emailposting

Para analizar esta data correctamente, te recomiendo que utilices una librería llamada TMail, con esta puedes sacar cualquier tipo de información del e-mail, incluyendo cualquier archivo adjunto que tenga.

$ gem install tmail

Luego debes crear un ‘action’ en tu ‘controller’

def emailposting
  mail = TMail::Mail.parse(request.raw_post.to_s)
  from = mail.from.to_s
  to = mail.to.to_s
  subject = mail.subject.to_s
  body = mail.body.to_s
  # tu código, insertar a la BD, etc.
end

El resto, es responsabilidad tuya, espero les haya gustado esta primera guía para Tequilog.

  • Share/Bookmark
October 17th, 2008 por Jorge Yau
<?= "Hello World!"; ?>
<%= "Hello World!" %>
<% Response.Write("Hello World!") %>
<script>document.writeln("Hello World!");</script>
  • Share/Bookmark