Testear ActiveRecord sin Rails

19 de Marzo de 2009

Hace unos días andaba algo ocioso y me puse a probar como escribir un plugin/gema para rails. Este plugin resultó en una muy sencilla extensión para modelos ActiveRecord, que simplemente mantiene una copia de los valores inversos de created_at y updated_at como enteros, con lo que podemos hacer consultas ordenando por estos campos de forma descendente.

Nada sofisticado. Pero a la hora de escribir los tests me encontré con que quería hacer esos tests independientes de Rails, pues solo afectan a ActiveRecord, y sin necesidad de ningún tipo de configuración. Para ello utilicé varios modelos de ActiveRecord y como base de datos sqlite.

Primero definimos un schema con las tablas de nuestros modelos:

ActiveRecord::Schema.define(:version => 0) do
  create_table :with_created_models, :force => true do |t|
    t.column :something, :string
    t.column :created_at, :datetime
    t.column :updated_at, :datetime
    t.column :created_at_inverse, :integer
  end
end

Una vez definido el schema, establecemos nuestro entorno de test, por ejemplo en test_helper.rb:

require 'test/unit'

require 'rubygems'
require 'active_record'
require 'shoulda'

require File.dirname(__FILE__) + '/../lib/inverse_sortable'

ActiveRecord::Base.establish_connection({
    :adapter => "sqlite3",
    :dbfile => "test/test.db"
})

class WithCreatedModel < ActiveRecord::Base
end

load(File.dirname(__FILE__) + "/schema.rb")

En este fichero, le decimos a ActiveRecord que utilice como base de datos un fichero de sqlite (test.db), definimos un modelo correspondiente a la tabla en nuestro schema.rb (declarando una clase que hereda de ActiveRecord::Base y con el nombre de la tabla en singular) y por último cargamos dicho schema.

Con esto ya disponemos de un modelo que podemos usar para testear el comportamiento de la extensión inverse_sortable, por ejemplo en inverse_sortable_test.rb:

require File.join(File.dirname(__FILE__), 'test_helper')

class WithCreatedModel
  acts_as_inverse_sortable
end

class InverseSortableTest < Test::Unit::TestCase
  context "A model that acts as an inverse sortable" do
    should "have the inverse of its created_at time when is created if created_at_inverse is available" do
      with_created = WithCreatedModel.create(:something => "Testing")

      assert_not_nil with_created.created_at_inverse
      assert_equal -with_created.created_at.to_i, with_created.created_at_inverse
    end
    # ...
end

Para quién pueda interesar, tanto el plugin como los tests están en http://github.com/alvarobp/inverse_sortable, donde además hay un pequeño benchmark, sobre lo cual quizá comente en otro post.

Crear un repositorio Git remoto

24 de Enero de 2009

A modo de receta, he aquí la secuencia de comandos necesaria para la creación de un repositorio Git remoto, a través de SSH.

El primer paso es crear el repositorio en sí, para ello o bien creamos un directorio vacío donde empezar a meter el código de nuestra aplicación, o bien vamos al directorio donde tenemos ya nuestro código:

cd appname
git init

Acto seguido añadimos el contenido al repositorio y comiteamos el cambio:

git add .
git commit -m "inicilizacion del repositorio"

El último paso consiste en crear una copia del repositorio la cual subiremos al servidor (o moveremos dentro de la misma máquina, según proceda) y que contiene solamente la información interna de git y no una copia de trabajo:

git clone --bare appname appname.git
scp -r appname.git ssh://user@yourserver/path/to/git/

Por último, para comenzar a trabajar sobre el repositorio tenemos dos opciones, clonarlo desde su ubicación remota:

cd algunsitio
git clone ssh://user@yourserver/path/to/git/appname.git

lo que nos creará un directorio appname en algunsitio con la copia de trabajo, o bien añadimos el repositorio remoto a la copia actual (creada en el primer paso):

git remote add origin ssh://user@yourserver/path/to/git/appname.git

Codeigniter – Framework PHP

8 de Agosto de 2007

He estado probando estos días el framework PHP (a la rails) CodeIgniter. De momento la impresión es buena. En mi línea, pongo un ejemplo.

Modificando un par de ficheros de configuración o tres (un par de líneas en cada uno) y creando los siguientes dos ficheros he obtenido una sencilla aplicación que muestra las entradas de mi blog de wordpress.

El fichero del controlador (controllers/blog.php):


class Blog extends Controller {
  function Blog() {
    parent::Controller();

    $this->load->scaffolding('bb_posts');
  }

  function index() {
    $data['title'] = "BatU's Stack";
    $data['heading'] = "piling up experiences...";
    $this->db->orderby("post_date", "desc");
    $data['query'] = $this->db->get('bb_posts');

    $this->load->view('blog_view', $data);
  }
}

El fichero de la vista correspondiente (views/blog_view.php):

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
  "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html>
<head>
  <meta http-equiv="Content-type" content="text/html;
    charset=utf-8">
  <title>Blog</title>

  <link rel="stylesheet" href="/bblog/css/style.css"
    type="text/css" media="screen"
    title="no title" charset="utf-8">
</head>
<body>
  <div id="box">
    <div id="header">
      <h1><?=$title?></h1>
      <h2><?=$heading?></h2>
    </div>
    <div id="posts">
      <?php foreach($query->result() as $post): ?>
        <div class="post">
          <h3><?=$post->post_title?></h3>

          <div class="post_content">
            <?=$post->post_content?>
          </div>
        </div>
      <?php endforeach; ?>
    </div>
  </div>
</body>
</html>

Dejo aquí la URL del ejemplo: http://testing.inbatu.com/bblog/index.php/blog

imaplib – Ejemplo muy básico

23 de Julio de 2007

Estoy de vuelta con python, que desde antes de exámenes no había tocado nada. Y como estoy llegando al final del Learning Python, donde he visto que existe la librería poplib, me ha dado por probar imaplib.

Dejo aquí un sencillo ejemplo que muestra todos los mensajes de un buzón IMAP.

#!/usr/bin/python

import imaplib, getpass

if __name__ == '__main__':

	host = raw_input('Host: ')
	user = raw_input('User: ')
	passw = getpass.getpass('Password: ')

	mail = imaplib.IMAP4(host)
	mail.login(user,passw)
	mail.select()

	typ, data = mail.search(None, 'ALL')
	for num in data[0].split():
		typ, data = mail.fetch(num, '(RFC822)')
		print '\\n----------------------------------\\n',
		print 'Message %s' % num,
		print '\\n----------------------------------\\n',
		print '\\n%s\\n' % data[0][1]
		raw_input('Next message...')

	mail.close()
	mail.logout()

Mordiendo la manzana

23 de Junio de 2007

Después de unos meses sin escribir nada, señal de que tengo poco que contar y que he estado bastante liado este último cuatrimestre, comunico que hace unos días (4) he adquirido un MacBook 13,3 (2.16GHz).

La experiencia está siendo grata. Quizás demasiado pues de momento estoy tirando con MacOSX (ya me he flagelado por ello :P ) que estoy de exámenes y no es plan de ponerme a trastear para meterle una Ubuntu.

Sobre MacOSX, la verdad la impresión es bastante buena y lo sería aún más si no fuera por el “insignificante detalle” de que su escritorio es software propietario.

Y poco más puedo decir que la mayoría de gente que pueda estar leyendo esto (osea nadie) no sepa sobre estos portátiles. Espero que este nuevo miembro de la familia se porte bien durante su estancia en Irlanda y que haga su papel en mi experiencia erasmus.