Resultado de etiquetas “Tutorial”

Actualmente estamos comenzando un proyecto que consta de unos ajustes a una aplicación en Rails que utiliza una versión vieja de este framework (1.2.3) y por razones de tiempo y costo, no es posible realizar una actualización a una versión mas nueva (2.x).

En mi caso, por ser un desarrollador con Ruby y con Rails, no puedo darme el lujo de hacer un downgrade total a versiones viejas, incluso, Rails 1.2.3 no es compatible con los últimos patchlevel (actualizaciones varias y de seguridad) de Ruby 1.8.6 ni con Ruby 1.8.7 (ni pensar Ruby 1.9). Mi laptop actualmente tiene Ubuntu Jaunty (9.04), por lo que Ruby es de la serie 1.8.7.

Mi solución fue instalar Ruby Enterprise de Phusion, y mantener una instalación paralela en /opt. Pero una de las extensiones que necesitaba instalar era ruby-ldap, que para hacer las cosas más interesantes, la compilación fallaba, las razones se explican aquí.

Para resumir, la versión de libldap2 incluida en Ubuntu Jaunty no es compatible con ruby-ldap 0.9.7 ni con el último ruby-ldap 0.9.8, por lo que la solución era descargar una versión anterior de las librerías de OpenLDAP (la estable del 2008) y compilar ruby-ldap contra estas librerías.

Para agregarle mas interés a todo el embrollo, resulta que la compilación de openldap-2.4.11 (la estable del 2008), también generaba error, ¿la razón?, básicamente, esa versión de OpenLDAP no compila con GCC 4.3. Gracias a la gente de mi antigua y aún muy querida favorita distribución Gentoo, pude compilar las librerías de OpenLDAP gracias a un patch suministrado por ellos, descargable aquí.

Instalación

A continuación los pasos de esta mini-odisea para dejar documentada la solución, tanto para mí como para la comunidad.

El primer paso es instalar Ruby Enterprise (pero primero unas dependencias, que el mismo instalador de Ruby Enterprise solicitará si no se encuentran instaladas)

sudo aptitude install libssl-dev libreadline5-dev

Luego, descomprimir el tarball de Ruby Enterprise e instalar (seguir instrucciones del instalador de línea de comando):

tar xzvf ruby-enterprise-1.8.6-20090520.tar.gz
cd ruby-enterprise-1.8.6-20090520/
sudo ./installer

Ruby Enterprise es instalado por defecto en /opt, para facilitar el acceso a los ejecutables, realizaremos enlaces simbólicos a /usr/bin:

sudo ln -s /opt/ruby-enterprise-1.8.6-20090520/bin/ruby  /usr/bin/rubye
sudo ln -s /opt/ruby-enterprise-1.8.6-20090520/bin/gem  /usr/bin/geme
sudo ln -s /opt/ruby-enterprise-1.8.6-20090520/bin/irb  /usr/bin/irbe

Nótese que los symlinks se llaman igual, pero finalizan con "e" de Enterprise. Por lo tanto para utilizar Ruby Enterprise, desde la línea de comando sólo debemos utilizar rubye, y para instalar gemas utilizamos geme.

Antes de compilar la extensión ruby-ldap, instalar las librerías de OpenLDAP, en este caso utilizaremos como destino /opt/openldap, para evitar conflictos con las librerías existentes en el sistema (Nota: reemplazar openldap_patch.diff por el nombre asignado al momento de descargar el Patch OpenLDAP para GCC 4.3 o superior):

tar xzvf openldap-stable-20080813.tgz 
cp openldap_patch.diff openldap-2.4.11/
cd openldap-2.4.11/
patch -p1 < openldap_patch.diff 
./configure --prefix=/opt/openldap --enable-slapd=no
make depend
make 
sudo make install

Ahora se procede a instalar ruby-ldap 0.9.7, descomprimir el tarball e instalar, indicando las librerías de ldap en /opt/openldap:

tar xzvf libldap-ruby_0.9.7.orig.tar.gz
cd ruby-ldap-0.9.7/
rubye extconf.rb --with-ldap-dir=/opt/openldap
make
sudo make install

Nótese el uso de rubye para la configuración de la extensión.

Instalar las gemas necesarias (nótese el uso de geme y no gem):

sudo geme install rails -v x.x.x
# ...

Adicionalmente, para facilitar el acceso al rake de la instalación de Ruby Enterprise, creé un enlace simbólico a /usr/bin (igual que con rubye, irbe y geme):

sudo ln -s /opt/ruby-enterprise-1.8.6-20090520/bin/rake  /usr/bin/rakee

Como observación, los scripts de línea de comando de Rails (por ejemplo, script/server), deben invocarse con rubye -S. Ejemplo:

## Iniciar el servidor local de desarrollo
rubye -S script/server

## Iniciar la cónsola de la aplicación
rubye -S script/console --irb=irbe

## Las Tareas rake debe utilizar rakee
rakee db:migrate 

Saludos!

Esta es la segunda parte de una serie de 3 artículos sobre la presentación que realicé en el FLISOL Paraguaná 2009.

Imagen Thumbnail para flisol_todo_borrador_interfaz.png

En la primera parte, explicamos brevemente en qué consistiría la aplicación, generamos el proyecto con Rails, generamos el scaffold para el modelo Tarea y agregamos una que otra validación en el modelo. En esta segunda parte, lo que haremos es darle un poquito de forma, para que parezca al borrador que dibujamos durante la primera parte.

Vemos en el borrador que tenemos claramente separadas las tareas finalizadas de las pendientes, por tanto debemos definir una manera de buscar dichas tareas. ActiveRecord nos brinda muchas opciones para realizar esta labor, en este caso usaremos los named_scopes, aunque esto podría considerarse un overkill es un buen ejemplo de la fantástica semántica que Rails pone a nuestra dispocición. Editamos el modelo Tarea (app/models/tarea.rb), y agregamos al final lo siguiente:

  named_scope :pendientes, :conditions => {:finalizada => false}
  named_scope :finalizadas, :conditions => {:finalizada => true}

Esto nos va a permitir buscar las tareas pendientes y finalizadas de la siguiente manera:

Tarea.pendientes    # => devuelve las tareas pendientes
Tarea.finalizadas   # => devuelve las tareas finalizadas

Sabiendo como buscar las tareas finalizadas y las pendientes, ahora podemos asignarlas tranquilamente a variables de instancia en TareasController#index. Editamos la acción index del controlador TareasController (app/controllers/tareas_controller.rb) para que quede de la siguiente manera:

# GET /tareas
  # GET /tareas.xml
  def index
    @pendientes = Tarea.pendientes
    @finalizadas = Tarea.finalizadas
    @tarea = Tarea.new

    respond_to do |format|
      format.html # index.html.erb
      format.xml  { render :xml => @tareas }
    end
  end

Lo que hicimos fue eliminar la búsqueda original que retornaba todas las tareas, pendientes y finalizadas, y agregamos 2 búsquedas nuevas: Tarea.pendientes y Tarea.finalizadas. Adicionalmente agregamos la variable de instancia @tarea, que contiene una Tarea nueva (vacía), esto se debe a que en nuestra página index (según el borrador), vamos a incluir un formulario en la parte inferior para agregar nuevas tareas.

El siguiente paso es hacerle algunos ajustes a nuestra interfaz para que se parezca mas a nuestro diseño de lápiz y papel. Lo primero, cambiar el markup de la vista, editamos app/views/index.html.erb para que se vea así:

<h1>Mis tareas</h1>

<h2>Pendientes</h2>

<% if @pendientes.any? %>
  <ul class="tareas pendientes">
    <%= render :partial => @pendientes %>
  </ul>
<% else %>
  <p class='sin-tareas'>No hay tareas pendientes</p>
<% end %> 

<% if @finalizadas.any? %>
  <h2>Finalizadas</h2>

  <ul class="tareas finalizadas">
    <%= render :partial => @finalizadas %>
  </ul>
<% end %> 

<hr />

<%= render :partial => "form" %>

¿Qué hicimos? Ya deben haberse dado cuenta que eliminamos la tabla (tag table) para mostrar el listado de tareas, ahora, cada conjunto de tareas se muestran con una "unordered list" (ul). Se agregaron 2 títulos de segundo nivel (h2) para dividir las tareas finalizadas de las pendientes. Adicionalmente, las pendientes y las finalizadas se muestran siempre y cuando existan registros asociados a la misma (if @pendientes.any?, if @finalizadas.any?). Como podrán haberse dado cuenta, en el template aparencen unos fulanos render :partial => algo. El método render, para resumirlo, es uno de los mecanismos con los cuales se envía contenido al usuario (detalles en la api de Rails - Partials).

Rails es lo suficientemente inteligente para determinar que @pendientes y @finalizadas contienen un conjunto de objetos Tarea (ver RecordIdentifier, por tal razón, tanto render :partial => @pendientes como render :partial => @finalizadas lo que hacen es mostar el partial (fragmento de vista) tarea/_tarea.html.erb para cada uno de los elementos dentro de las variables @pendientes y @finalizadas. Nota: los parials en Rails siempre comienzan con "_". Ej: _tarea.html.erb. Rails determina este nombre gracias a RecordIdentifier#partial_path.

render :partial => "form" lo que hace es mostrar el partial _form.html.erb (Nótese que no es necesario especificar el "_").

Hablamos de varios partials (_tarea.html.erb y _form.html.erb), pero no los hemos creado. Eso es lo que vamos hacer ahora mismo. Primero, creamos el archivo _tarea.html.erb en app/views/tareas y agregamos el siguiente contenido:

<li>
  <% form_for(tarea) do |f| %>
    <%= f.check_box :finalizada, :onchange => 'form.submit();' %>
    <%= h tarea.titulo %>
    <span><%= tarea.notas %></span>
    <%= link_to 'Editar', edit_tarea_path(tarea) %>
    <%= link_to 'Eliminar', tarea, :confirm => 'Seguro que desea eliminar la tarea?', :method => :delete %>
  <% end %>
</li>

Este partial se encargará de mostrar cada elemento (o list item li) de la lista ul. La representación de cada tarea en el navegador es un formulario, que incluye un check_box, el cual al hacerle clic realiza el submit de dicho formulario. El resto es el título y las notas de la tarea, con los links de edición y eliminación.

Ahora, creamos el partial del formulario para agregar nuevas tareas (app/views/tareas/_form.html.erb):

<h2>Agregar nueva tarea</h2>

<% form_for(@tarea) do |f| %>
  <%= f.error_messages %>

  <p>
    <%= f.label :titulo %><br />
    <%= f.text_field :titulo %>
  </p>
  <p>
    <%= f.label :notas %><br />
    <%= f.text_area :notas %>
  </p>
  <p>
    <%= f.submit 'Agregar' %>
  </p>
<% end %>

Este partial es una versión simplificada del template new.html.erb generado por el scaffold en la parte 1. De hecho, ese template original no va a ser utilizado, así que lo podemos eliminar.

Podríamos probar la aplicación en este momento, pero nos daríamos cuenta de que no se parece a nuestro borrador de lapiz y papel. ¿La razón?, debemos agregar una hoja de estilo simple para darle el "look" que deseamos. Creamos el archivo public/stylesheets/todo.css con el siguiente contenido:

/*Hoja de estilos principal de FLISOL todo*/

h1 {
  background-color: #333;
  padding: 10px;
  color: #FFF;
}

h2 {
  padding-top: 20px;
}

hr { margin-top: 20px; margin-bottom: 20px;}

ul.tareas li {
  padding-left: 0;
  padding-top: 15px;
  list-style: none;
  font-weight: bold;
}

ul.tareas li span {
  display: block;
  font-style: italic;
  font-weight: normal;
  padding-bottom: 5px;
}

ul.tareas li a {
  font-size: 10px;
}

ul.pendientes li {
  font-size: 16px;
  margin-top: 8px;
}

ul.pendientes li span {
  color: #333;
  font-size: 14px;
}

ul.finalizadas li {
  color: #999;
  font-size: 12px;
}

ul.finalizadas li span {
  color: #666;
  font-size: 11px;
}

p.sin-tareas {
  color: #338;
  font-style: italic;
  margin-left: 45px;
}

textarea { height: 50px; }

Sólo nos falta hacer referencia a esta hoja de estilo en nuestro layout. Buscamos la línea:

<%= stylesheet_link_tag 'scaffold' %>

y la reempalzamos por:

<%= stylesheet_link_tag 'scaffold', 'todo' %>

Ahora podemos probar la aplicación en http://localhost:3000/tareas.

Después de navegar, nos daremos cuenta de que hay un comportamiento extraño al momento de editar, eliminar o crear una tarea, esto se debe a que en TareasController, estas acciones deben redirigir a index luego de realizar su trabajo:

class TareasController < ApplicationController

  # GET /tareas
  # GET /tareas.xml
  def index
    @pendientes = Tarea.pendientes
    @finalizadas = Tarea.finalizadas
    @tarea = Tarea.new

    respond_to do |format|
      format.html # index.html.erb
      format.xml  { render :xml => (@pendientes + @finalizadas) }
    end
  end

  # GET /tareas/1
  # GET /tareas/1.xml
  def show
    @tarea = Tarea.find(params[:id])

    respond_to do |format|
      format.html # show.html.erb
      format.xml  { render :xml => @tarea }
    end
  end

  # GET /tareas/new
  # GET /tareas/new.xml
  def new
    @tarea = Tarea.new

    respond_to do |format|
      format.html # new.html.erb
      format.xml  { render :xml => @tarea }
    end
  end

  # GET /tareas/1/edit
  def edit
    @tarea = Tarea.find(params[:id])
  end

  # POST /tareas
  # POST /tareas.xml
  def create
    @tarea = Tarea.new(params[:tarea])

    respond_to do |format|
      if @tarea.save
        flash[:notice] = 'La tarea se creó satisfactoriamente.'
        format.html { redirect_to tareas_path }
        format.xml  { render :xml => @tarea, :status => :created, :location => @tarea }
      else
        @pendientes = Tarea.pendientes
        @finalizadas = Tarea.finalizadas
        format.html { render :action => "index" }
        format.xml  { render :xml => @tarea.errors, :status => :unprocessable_entity }
      end
    end
  end

  # PUT /tareas/1
  # PUT /tareas/1.xml
  def update
    @tarea = Tarea.find(params[:id])

    respond_to do |format|
      if @tarea.update_attributes(params[:tarea])
        flash[:notice] = 'La tarea fue actualizada.'
        format.html { redirect_to tareas_path }
        format.xml  { head :ok }
      else
        format.html { render :action => "edit" }
        format.xml  { render :xml => @tarea.errors, :status => :unprocessable_entity }
      end
    end
  end

  # DELETE /tareas/1
  # DELETE /tareas/1.xml
  def destroy
    @tarea = Tarea.find(params[:id])
    @tarea.destroy

    respond_to do |format|
      format.html { redirect_to(tareas_url) }
      format.xml  { head :ok }
    end
  end
end

flisol_todo_con_estilos_aplicados.png

Nótese que las acciones create y update redirigen a index si la operación fue satisfactoria, esto se logra mediante redirect_to tareas_path. Otro pequeño ajuste se realizó para el caso de que la operación de creación de una nueva tarea falla: se debe mostrar el template index.html.erb, pero para evitar un error de que no se encuentran definidas las variables @pendientes y @finalizadas, debemos asignarles los registros tal cual se realizó en la acción index.

Si todo salió bien, debemos ver algo parecido a lo que se muestra en la imagen.

Bueno, eso es todo en esta parte 2, en la siguiente entrega mostraremos las tareas pendientes y finalizadas en el iphone, utilizando mi plugin rails_jqtouch.

Saludos!

Imagen Thumbnail para rails_flisol_paraguana_2009.png En esta serie de 3 artículos, estaré haciendo un resumen de la demostración que realicé en el FLISOL Paraguaná 2009. Después de muchas vueltas, nunca logré ponerle un nombre bueno a la presentación, lo cual es algo que me decepciona. Mis amigos saben que me gusta ponerle nombres o títulos espaciales (si, con a no con e) a las cosas, por ejemplo, mi presentación del FLISOL pasado Entropía en el software, los cursos de Rails (Rails Sensei: Técnicas avanzadas y soluciones elegantes para la web). Pero en fin, aunque no fué el nombre que utilicé, vamos a conformarnos por ahora con Rails + iPhone.

No es usual en mí utilizar mucho texto en las presentaciones, pero si creen que les sirve de algo, o la quieren de recuerdo, pueden descargar la versión en pdf aquí.

Este primer artículo explicará lo que se desea hacer, se creará el proyecto y rápidamente generaremos un scaffold. La segunda parte consistirá en modificar un poco los estilos y ajustar el flujo de navegación, y la tercera parte consistirá en agregarle una interfaz para navegadores Mobile Safari (iPhone o iPod Touch).

Sé que muchos de los presentes ese día eran estudiantes, quizás no muy familiarizados con lo que es un Framework, con el patrón MVC, o con Ruby o Rails. La idea era demostrar lo rápido que era desarrollar una aplicación web con Rails y agregarle una interfaz específica para dispositivos móviles, en este caso un iPhone de Apple.

Después de una breve introducción, pudimos entrar en materia, crear la aplicación FLISOL To - do, una aplicación simple tipo to-do list. Así que entremos en materia nosotros también.

Una manera de definir lo que queremos hacer es diseñar la Interfaz Primero, preferiblemente con papel y lápiz (si, así de simple y barato) e ir planteando un flujo de la aplicación, por ejemplo: "hago clic aquí y se muestra tal cosa...", "clic en Aceptar para enviar los datos, luego se muestra el listado...". La idea es ir reflejando el flujo de trabajo del usuario con la aplicación. Este es el borrador de la interfaz para nuestro pequeño ejemplo.

Imagen Thumbnail para flisol_todo_borrador_interfaz.png Tenemos un título (Mis Tareas), que identifica toda nuestra interfaz, y claramente separamos las tareas Pendientes de las Finalizadas. Al hacer clic sobre un checkbox, indicamos si la tarea se terminó o la devolvemos al listado de pendientes. Adicionalmente incorporamos links para editar o eliminar cada una.

En la parte inferior se puede incorporar un formulario para agregar nuevas tareas. Se puede observar que la información asociada a una tarea incluye un Título y unas Notas. Por ejemplo:

  • Título: Escribir segunda parte del artículo de Rails + iPhone.
  • Notas: La segunda parte consta de aplicar los estilos y aplicar el flujo navegación detallado en la Parte 1.

Esto nos lleva al siguiente paso, definir un modelo inicial de datos para almacenar la información que deseamos mostrar. Al igual que antes, podemos usar lápiz y papel.

Imagen Thumbnail para flisol_todo_borrador_modelo.png Sin mucho análisis, un buen nombre para nuestro modelo sería Tarea (luego veremos que por convenciones de Rails, la tabla asociada a un modelo, por defecto es plural, por eso la imagen muestra tareas). Tanto título como notas son atributos que deben aparecer en este modelo, pero también debemos agregar un mecanismo para determinar si cada tarea ya fue finalizada. Un nombre ideal para este atributo sería finalizada de tipo boolean, que permita indicar con true o false si la tarea en cuestión ya se culminó. Un detalle adicional aquí es que el atributo finalizada debe ser por defecto false (En un to-do list, no tiene sentido crear una tarea ya finalizada).

Con las ideas claras y un bosquejo de lo que queremos hacer, lo siguiente es crear el proyecto en Rails y comenzar a darle forma para que se parezca a nuestros borradores.

Para crear el proyecto, escribimos en la línea de comando:

rails flisol_todolist
cd flisol_todolist

La primera línea utiliza la instrucción de línea de comando rails, la cual nos permite inicializar un proyecto, con todos los directorios básicos y archivos de configuración necesarios para desarrollar la aplicación. rails crea el directorio flisol_todolist, que contiene todo el proyecto. Con la segunda línea, simplemente ingresamos a este directorio.

Ahora, podemos dar un paso rápido y crear un scaffold o bien crear "a mano" un Controlador para procesar los requests, un Modelo para gestionar el acceso a datos y darle persitencia a la información y luego agregar cada una de las vistas que nos permitirán mostrar la información en el navegador. Nos iremos por el camino rápido y crearemos un scaffold, que hará por nosotros todo lo antes mencionado. Antes, vamos a recordar que dijimos que el nombre de nuestro modelo sería Tarea y que tenía los atributos titulo, notas y finalizada.

Nos vamos a una terminal (la misma que teníamos abierta) y dentro del directorio del proyecto (flisol_todo) ejecutamos:

script/generate scaffold Tarea \
  titulo:string \
  notas:text \
  finalizada:boolean

Lo que en realidad hicimos fue decirle al framework que generara un scaffold, es decir, una estructura base (de código fuente) de la cual podemos apoyarnos, para luego darle forma hasta convertirla en lo que realmente se ajusta a nuestras necesidades. Podemos notar que los argumentos son el nombre del modelo (Tarea en este caso) y sus atributos (los atributos son opcionales, pero en este ejemplo los incorporamos para yo no tener que escribir tanto en este artículo!!).

El Scaffold, aparte de crearnos el modelo Tarea (app/models/tarea.rb), el controlador TareasController (app/controllers/tareas_controller.rb) y las vistas principales (app/views/tareas), nos genera un migration, disponible en el directorio db/migrate/nnnn_create_tareas.rb (nnnn representa un timespamp). Por ahora vamos a conformarnos con saber que dicho migration nos permitirá especificar el esquema de la tabla asociada al modelo Tarea, es decir, el nombre de la tabla y sus columnas. Los migrations en Rails son extremadamente útiles, para mas información, pueden dirigirse a Rails Guides - Migrations. Vamos a darle una mirada a nuestro migration:

class CreateTareas < ActiveRecord::Migration
  def self.up
    create_table :tareas do |t|
      t.string :titulo
      t.text :notas
      t.boolean :finalizada

      t.timestamps
    end
  end

  def self.down
    drop_table :tareas
  end
end

Nos enfocaremos solamente en la sección create_table :tareas ... end. En criollo, dice lo siguiente (omitiendo t.timestamps):

Crea la tabla tareas, con el campo titulo de tipo string, el campo notas de tipo text y el campo finalizada como boolean.

Si comparamos eso, con la imagen de nuestro modelo, que discutimos anteriormente, vemos que falta sólo algo, el valor por defecto (default), que debe ser false, para lo cual sólo debemos agregar :default => false al campo finalizada. El migration luego de editarlo queda de la siguiente manera:

class CreateTareas < ActiveRecord::Migration
  def self.up
    create_table :tareas do |t|
      t.string :titulo
      t.text :notas
      t.boolean :finalizada, :default => false

      t.timestamps
    end
  end

  def self.down
    drop_table :tareas
  end
end

Antes de probar la aplicación, sólo nos queda crear la base de datos, la pregunta es ¿Si no hemos hablado si va a ser MySql, PostgreSql, SQLite, etc. Una ganancia de usar un framework (o mejor dicho un ORM) es tener la facilidad de hacer que nuestra aplicación sea en muchos casos database-agnostic, y Rails, o mejor dicho, ActiveRecord de Rails, es una de las cosas que nos permite hacer. Rails incluye una configuración de base de datos por defecto, la cual está basada en SQLite. Un extracto del archivo de configuración (config/database.yml) se muestra a continuación:

...
development:
  adapter: sqlite3
  database: db/development.sqlite3
  pool: 5
  timeout: 5000
...

Brevemente, adapter: sqlite3 indica que usaremos una base de datos SQLite 3.x y database: db/development.sqlite3 que está ubicada en el directorio db, con el nombre development.sqlite3.

Rails incluye un conjunto de tareas que nos permiten facilitar el trabajo con el (ejecutar rake -T para un listado), entre ellas la posibilidad de crear la base de datos y ejecutar los migrations de manera inteligente. Para crear la base de datos, con el esquema definido, ejecutamos en la terminal (si, en el directorio del proyecto) lo siguiente:

rake db:migrate

Listo! nuestra base de datos se creó en el directorio db, con el nombre development.sqlite3 (si no cambiaron el nombre y la ruta!!!). Si se genera algún tipo de error, revisar con tranquilidad los pasos anteriores, y todo el código escrito (:default => false jaja).

Para probar la aplicación, es necesario iniciar el servidor local, yo acostumbro abrir otra terminal (o pestaña) y utilizarla exclusivamente para el servidor de desarrollo, sólo recuerda verificar que estas en el directorio del proyecto. Para iniciar el servidor, ejecutar:

script/server

La salida indicará que el servidor inició y está escuchando en el puerto 3000, sólo nos queda disfrutar de la magia de Rails ingresando la url http://localhost:3000/tareas y jugar un poco agregando, modificando y eliminando tareas.

Si no probaron agregar una tarea con todos los campos en blanco, háganlo ahora, se darán cuenta de que no hay ninguna validación asociada. Como podrán imaginarse, el título debería ser requerido para cualquier tarea. Para lograr esto, editamos el archivo app/models/tarea.rb para que quede de la siguiente forma:

class Tarea < ActiveRecord::Base
  validates_presence_of :titulo
end

Si volvemos a intentar ingresar una tarea sin especificar un título, obtendremos un mensaje de error, indicándonos que el título no puede estar en blanco. Para mas información sobre las validaciones, pueden ingresar en Rails Guides - ActiveRecord Validations and Callbacks.

Con esto, finalizamos la primera parte de esta serie de 3 artículos, en la siguiente entrega, ajustaremos el flujo de navegación y los estilos para que parezca mas un to-do list y en la tercera, mostraremos las tareas en un iPhone, utilizando rails_jqtouch.

Saludos!

1

Sobre COTECSO

Somos un equipo pragmático, desarrollamos software de manera ágil y elegante, nos gusta la tecnología, la simplicidad y las cosas bien hechas.

Comentarios recientes

Cerrar