#342 Migrating to PostgreSQL
- Download:
- source codeProject Files in Zip (139 KB)
- mp4Full Size H.264 Video (26.7 MB)
- m4vSmaller H.264 Video (11.9 MB)
- webmFull Size VP8 Video (10.4 MB)
- ogvFull Size Theora Video (28.2 MB)
PostgreSQL es una base de datos cada vez más popular entre los desarrolladores de Rails, y con razón. La multitud de funcionalidades que aporta han hecho que muchos desarrolladores que previamente utilizaban MySQL se hayan pasado a Postgres. Mencionaremos algunas de estas ventajas al final del episodio pero primero veremos cómo configurar Postgres para una aplicación Rails. La página de descargas de la web de PostgreSQL ofrece paquetes para la mayoría de sistemas operativos, e incluso en Mac OS X Lion viene preinstalado. Podemos comprobar la versión de Postgres ejecutando la orden psql
.
$ psql --version psql (PostgreSQL) 9.0.5
Pero aunque ya tengamos una versión instalada es mejor instalar Postgres mediante Homebrew para conseguir la última versión y los ficheros de desarrollo. La siguiente orden nos descargará y compilará Postgres.
$ brew install postgresql
Esto puede ser que lleve un rato. Una vez que haya terminado el proceso veremos algunas instrucciones sobre cómo configurarlo todo. Tendremos que lanzar esta orden para finalizar la creación de la base de datos.
$ initdb /usr/local/var/postgres
Luego tendremos que lanzar el servidor, y una forma de hacerlo es configurando un agente.
$ mkdir -p ~/Library/LaunchAgents $ cp /usr/local/Cellar/postgresql/9.1.3/homebrew.mxcl.postgresql.plist ~/Library/LaunchAgents $ launchctl load -w ~/Library/LaunchAgents/homebrew.mxcl.postgresql.plist
Alternativamente podemos arrancar manualmente el servidor con la siguiente orden.
$ pg_ctl -D /usr/local/var/postgres -l /usr/local/var/postgres/server.log start
Ahora deberíamos tener funcionando la última versión de Postgres, y podemos ver que usamos la versión instalado en /usr/local/bin
con which psql
. Hemos dejado, pues, de utilizar la versión incluida en Lion.
$ psql --version psql (PostgreSQL) 9.1.3 $ which psql /usr/local/bin/psql
Creación de una aplicación Rails con Postgres
Con Postgres instalado podemos crear una aplicación Rails que lo use como base de datos. Podemos utilizar la opción -d
para especificar la base de datos que hay que usar.
$ rails new blog -d postgresql
Bundler instalará automáticamente la gema pg
. Si vemos un error durante esta instalación quiere decir que Postgres no está configurado correctamente. Si la gema ya estaba instalada puede ser que necesitemos desinstalarla y volverla a instalar de forma que la compilación autodetecte y utilice la versión correcta de Postgres.
Si miramos el fichero database.yml
de nuestra aplicación veremos que viene ya configurado para utilizar Postgres.
development: adapter: postgresql encoding: unicode database: blog_development pool: 5 username: blog password:
El nombre de usuario configurado en el fichero tiene por defecto el nombre de la aplicación. Se trata de una buena idea para los entornos de producción porque cada aplicación tiene un nombre de usuario distinto. En desarrollo conviene más tenerlo todo bajo el mismo usuario, que es el usuario con el que accedemos a nuestro sistema. Homebrew se encarga de configurar dicha cuenta en la base de datos durante el proceso de instalación, pero en otras instalaciones puede ser que tengamos que crearlo nosotros. Usaremos este usuario en los entornos de desarrollo y pruebas y eliminaremos la configuración de producción porque esta aplicación nunca pasará de ser un ejemplo.
development: adapter: postgresql encoding: unicode database: blog_development pool: 5 username: eifion password: test: adapter: postgresql encoding: unicode database: blog_test pool: 5 username: eifion password:
Una vez que hayamos configurado el fichero database.yml
correctamente podremos crear las bases de datos de la aplicación usando rake.
$ rake db:create:all
A continuación vamos a generar un andamiaje para la tabla articles
y así podremos hacer pruebas con la aplicación, migrando la base de datos.
$ rails g scaffold article name content:text $ rake db:migrate == CreateArticles: migrating ================================================= -- create_table(:articles) NOTICE: CREATE TABLE will create implicit sequence "articles_id_seq" for serial column "articles.id" NOTICE: CREATE TABLE / PRIMARY KEY will create implicit index "articles_pkey" for table "articles" -> 0.0114s == CreateArticles: migrated (0.0116s) ========================================
Una diferencia que veremos con Postgres es que hay un par de mensajes que nos indican que se ha creado una secuencia y un índice. Al arrancar el servidor podremos navegar en nuestra aplicación y crear, editar y borrar artículos igual que si estuviéramos con una base de datos SQLite.
Cómo acceder directamente con la base de datos
Si queremos interactuar directamente con la base de datos podemos hacerlo con la orden psql
seguida del nombre de la base de datos. También se puede ejecutar rails db
que hace exactamente lo mismo.
$ rails db psql (9.1.3) Type "help" for help. blog_development=#
Aquí podemos lanzar consultas SQL contra la base de datos o utilizar órdenes específicas de Postgres como por ejemplo \D
que lista las tablas de la base de datos en uso.
blog_development=# \d List of relations Schema | Name | Type | Owner --------+-------------------+----------+-------- public | articles | table | eifion public | articles_id_seq | sequence | eifion public | schema_migrations | table | eifion
Si hacemos lo mismo pero pasando el nombre de una tabla obtendremos información acerca de la misma.
blog_development=# \d articles Table "public.articles" Column | Type | Modifiers ------------+-----------------------------+------------------------------------------------------- id | integer | not null default nextval('articles_id_seq'::regclass) name | character varying(255) | content | text | created_at | timestamp without time zone | not null updated_at | timestamp without time zone | not null Indexes: "articles_pkey" PRIMARY KEY, btree (id)
Podemos ver todos las órdenes propias de Postgres con \?
. La orden \h
mostrará además las órdenes SQL, y se le puede incluso pasar el nombre de una orden para ver la documentación disponible acerca de dicha orden. Cuando queramos abandonar la consola de Postgres podemos hacerlo con \q
. El sitio web de Postgres tiene un tutorial que nos será útil si nunca hemos trabajado con SQL.
Migración de una aplicación ya existente
Ahora ya sabemos cómo crear una nueva aplicación Rails que se ejecute con Postgres pero ¿qué tenemos que hacer si tenemos una base de datos ya existente funcionando sobre otro motor como SQLite o MySQL? Debajo se muestra una página de una aplicación que muestra una lista de productos. Los datos de esta aplicación se encuentran almacenados en una base de datos SQLite pero nos interesaría moverlos a Postgres.
El fichero database.yml
de la aplicación tiene el siguiente aspecto:
# SQLite version 3.x # gem install sqlite3 # # Ensure the SQLite 3 gem is defined in your Gemfile # gem 'sqlite3' development: adapter: sqlite3 database: db/development.sqlite3 pool: 5 timeout: 5000 # Warning: The database defined as "test" will be erased and # re-generated from your development database when you run "rake". # Do not set this db to the same as development or production. test: adapter: sqlite3 database: db/test.sqlite3 pool: 5 timeout: 5000 production: adapter: sqlite3 database: db/production.sqlite3 pool: 5 timeout: 5000
Sustituiremos estos valores por la configuración de Postgres.
development: adapter: postgresql encoding: unicode database: store_development pool: 5 username: eifion password: test: adapter: postgresql encoding: unicode database: store_test pool: 5 username: eifion password:
A continuación tenemos que modificar el fichero Gemfile
y reemplazar la gema sqlite3
por pg
y ejecutar bundle
para instarla.
gem 'pg'
Tendremos que crear las dos nuevas bases de datos ejecutando la orden Rake que vimos antes.
$ rake db:create:all
En este punto podríamos lanzar las migraciones para crear la base de datos, pero queremos migrar los contenidos de las tablas (y no sólo recrear el esquema), por lo que tendremos que hacer algo diferente. Por suerte hay una gema Ruby llamada Taps que sirve para esto, permitiéndonos exportar los datos de una base de datos e importarlos en otra utilizando un servidor Sinatra. Para ello primero tendremos que instalar la gema junto con sus dependencias.
$ gem install taps
La gema instala un ejecutable llamado taps
que podemos usar para servir una base de datos y también para extraer datos e insertarlos en otra base de datos. Esta nueva orden la usaremos para servir nuestra base de datos SQLite. Tendremos que pasarle la ruta al fichero de la base de datos, así como un nombre de usuario y clave para protegerla.
$ taps server sqlite://db/development.sqlite3 eifion secret
taps pasará a servir los contenidos la base de datos con Sinatra en el puerto 5000. En otra ventana de terminal podemos extraer los datos e insertarlos en nuestra base de datos Postgres. Tenemos que especificar el nombre de usuario y la base de datos sobre la que queremos insertar los datos importados, así como la URL del servidor Sinatra, incluyendo el usuario y clave definido al arrancar este servidor.
$ taps pull postgres://eifion@localhost/store_development http://eifion:secret@localhost:5000 Receiving schema Schema: 0% | | ETA: --:--:-- Schema: 50% |===================== | ETA: 00:00:00 Schema: 100% |==========================================| Time: 00:00:01 Receiving data 2 tables, 400 records products: 100% |==========================================| Time: 00:00:00 schema_migrat: 100% |==========================================| Time: 00:00:00 Receiving indexes schema_migrat: 0% | | ETA: --:--:-- schema_migrat: 100% |==========================================| Time: 00:00:00
Con esto extraeremos todos los datos de la base de datos SQLite en nuestro servidor Postgres. Ahora podemos intentar ejecutar nuestra aplicación Rails con la nueva base de datos.
Funciona y todo parece estar igual que antes, pero los datos ahora son servidos desde Postgres.
Ahora que hemos migrado a Postgres podemos aprovechar sus funcionalidades, incluyendo la búsqueda de texto completo. Podemos echar un vistazo a las gemas Texticle o PGSearch que sirven para esto. También podemos usar Postgres como una cola de trabajos con la gema queue_classic gem. Si queremos trabajar con un esquema NoSQL con Postgres también podemos hacerlo usando HStore. En esta anotación de blog se explica cómo hacerlo.