Levantar aplicación Rails para producción en Ubuntu con Unicorn y Nginx

Normalmente para levantar una aplicación Rails en producción, utilizamos este esquema:

  • Ubuntu como el Sistema Operativo de nuestro Servidor.
  • Unicorn como Servidor de Aplicaciones Rails.
  • Nginx como Servidor HTTP corriendo como un Front-End Reverse Proxy
  • Postgres como el manejador de nuestra Base de Datos.

En palabras más sencillas, Unicorn se encargará de interpretar todo nuestro código Ruby, Nginx de servir nuestro HTML, CSS, JS e imágenes y Postgres de leer y almacenar nuestra información. Todo esto vivirá en un servidor Ubuntu en la nube que operaremos desde la consola.

  1. Primero necesitas hacerte de un buen servidor e instalarle Ubuntu Server, recomiendo el servicio que da Linode porque el precio es muy accesible, nunca me ha fallado el servicio, son máquinas muy potentes y te dan control completo de tu servidor para instalar y desinstalar lo que tu quieras.
  2. Una vez que tengas tu servidor, necesitas instalarle Ruby, para ello puedes auxiliarte instalando rbenv con esta guía.
  3. Después instalale Nginx con estos comandos:
    sudo apt-get update
    sudo apt-get install nginx

    Por defecto Ubuntu lo activa, intenta visitar tu servidor desde un navegador, de esta forma:
    http://el_dominio_o_IP_de_tu_servidor

    Deberías ver una página como esta:
    nginx inicial

    Si no la ves, puedes iniciar Nginx manualmente desde tu servidor, los comandos para apagar, iniciar o reiniciar Nginx son lo siguientes:

    sudo service nginx stop
    sudo service nginx start
    sudo service nginx restart

    Para arrancarlo al iniciar Ubuntu ejecuta este comando:

    sudo update-rc.d nginx defaults

    En versiones recientes de Ubuntu te puede decir que ya existía el registro para iniciarlo automáticamente.

  4. Ahora instalaremos Unicorn:
    gem install unicorn

    ¡Así de fácil!

  5. Sube el código de tu aplicación al servidor. Puedes usar github, bitbucket o simplemente subir un zip si no tienes un manejador de versiones, normalmente subo mis aplicaciones Rails a un directorio apps en el home del usuario que vamos a usar para hacer los deploys, de esta forma:
    deployer@miservidor:~$ mkdir apps
    deployer@miservidor:~$ cd apps
    deployer@miservidor:~/apps$ pwd
    /home/deployer/apps/

    Para dejarlo así:

    /home/deployer/apps/mi_aplicacion
  6. Vamos a configurar un poco tu aplicación para producción:
    • Asegurate de agregar unicorn a tu Gemfile:
      gem 'unicorn'
    • Si usas Rails 4, asegurate de tener un valor en el archivo config/secrets.yml para el apartado de production, por ejemplo:
      # Do not keep production secrets in the repository,
      # instead read values from the environment.
      production:
        secret_key_base: b1329441746d18...4b14d78d744650450113242c

      La llave fue cortada a propósito, básate en las que trae tu aplicación para development y test; puedes sólo cambiarle un caracter a esas para que sea distinta la de producción.

    • Asegurate de tener configurada la Base de Datos para producción en tu archivo config/database.yml, utiliza el manejador de Base de Datos que más te agrade, por ejemplo:
      production:
        adapter: sqlite3   
        pool: 5
        timeout: 5000
        database: db/production.sqlite3
      Si en lugar de Sqlite deseas usar Postgres, basate en esta guia para instalarlo y configurarlo.
    • Instala las gemas necesarias para tu aplicación con el comando bundle
      bundle install
    • Crea tu Base de Datos, ejecuta las migraciones y corre los seeds para el ambiente de producción:
      rake db:create RAILS_ENV=production
      rake db:migrate RAILS_ENV=production
      rake db:seed RAILS_ENV=production
    • Precompila los assets para que se compriman y optimicen:
      rake assets:precompile RAILS_ENV=production
  7. Ahora vamos a configurar unicorn dentro de tu aplicación, para esto necesitamos crear dos archivos:
    • El primer archivo se ubicará en la ruta config/unicorn_init.sh dentro de tu aplicación, y tendrá el siguiente código:
      #!/bin/sh
      ### BEGIN INIT INFO
      # Provides:          unicorn
      # Required-Start:    $remote_fs $syslog
      # Required-Stop:     $remote_fs $syslog
      # Default-Start:     2 3 4 5
      # Default-Stop:      0 1 6
      # Short-Description: Manage unicorn server
      # Description:       Start, stop, restart unicorn server for a specific application.
      ### END INIT INFO
      set -e
       
      # Feel free to change any of the following variables for your app:
      TIMEOUT=${TIMEOUT-60}
      APP_ROOT=/home/deployer/apps/mi_aplicacion
      PID=$APP_ROOT/tmp/pids/unicorn.pid
      CMD="cd $APP_ROOT; bundle exec unicorn -D -c $APP_ROOT/config/unicorn.rb -E production"
      AS_USER=deployer
      set -u
       
      OLD_PIN="$PID.oldbin"
       
      sig () {
        test -s "$PID" && kill -$1 `cat $PID`
      }
       
      oldsig () {
        test -s $OLD_PIN && kill -$1 `cat $OLD_PIN`
      }
       
      run () {
        if [ "$(id -un)" = "$AS_USER" ]; then
          eval $1
        else
          su -c "$1" - $AS_USER
        fi
      }
       
      case "$1" in
      start)
        sig 0 && echo >&2 "Already running" && exit 0
        run "$CMD"
        ;;
      stop)
        sig QUIT && exit 0
        echo >&2 "Not running"
        ;;
      force-stop)
        sig TERM && exit 0
        echo >&2 "Not running"
        ;;
      restart|reload)
        sig HUP && echo reloaded OK && exit 0
        echo >&2 "Couldn't reload, starting '$CMD' instead"
        run "$CMD"
        ;;
      upgrade)
        if sig USR2 && sleep 2 && sig 0 && oldsig QUIT
        then
          n=$TIMEOUT
          while test -s $OLD_PIN && test $n -ge 0
          do
            printf '.' && sleep 1 && n=$(( $n - 1 ))
          done
          echo
       
          if test $n -lt 0 && test -s $OLD_PIN
          then
            echo >&2 "$OLD_PIN still exists after $TIMEOUT seconds"
            exit 1
          fi
          exit 0
        fi
        echo >&2 "Couldn't upgrade, starting '$CMD' instead"
        run "$CMD"
        ;;
      reopen-logs)
        sig USR1
        ;;
      *)
        echo >&2 "Usage: $0 <start|stop|restart|upgrade|force-stop|reopen-logs>"
        exit 1
        ;;
      esac

      Este archivo se encargará de apagar, encender y reiniciar un proceso de Unicorn para nuestra aplicación, asegúrate de personalizar la ruta que establece el valor de APP_ROOT con la ruta en la cual viva tu aplicación, y de poner tu usuario con el que accedes al servidor en la variable AS_USER.

      Debemos darle permiso de ejecución:

      chmod go+x unicorn_init.sh
    • El siguiente archivo se ubicará en config/unicorn.rb y tendrá la siguiente información:
      root = "/home/deployer/apps/mi_aplicacion"
      working_directory root
      pid "#{root}/tmp/pids/unicorn.pid"
      stderr_path "#{root}/log/unicorn.log"
      stdout_path "#{root}/log/unicorn.log"
       
      listen "/tmp/unicorn.mi_aplicacion.sock"
      worker_processes 2
      timeout 30

      Este archivo define los parámetros que le daremos a Unicorn como el timeout, el numero de workers, etcétera. También se define la ubicación del socket con el que se comunicará con Nginx. Asegúrate de personalizar el root y el listen según tu ambiente.

    • Crea el directorio pids dentro de la carpeta tmp de tu proyecto, porque lo va a necesitar Unicorn, ubicándote en la carpeta de tu aplicación, ejecuta este comando:
      mkdir tmp/pids

      Para que te cree este directorio:

      /home/deployer/apps/mi_aplicacion/tmp/pids/
    • Ahora vamos a crear un acceso directo del primer archivo que creamos para tener a la mano una ubicación desde donde levantar y apagar todos nuestros unicorns, primero nos movemos al siguiente directorio:
      cd /etc/init.d/

      Y creamos un acceso directo a nuestro archivo (puedes escoger el nombre que gustes para el acceso directo, yo tiendo a ponerles unicorn_elnombredelaapp para que sea fácil recordarlo):

      sudo ln -s /home/deployer/apps/mi_aplicacion/config/unicorn_init.sh unicorn_mi_aplicacion

      ¡Y ahora procedemos a levantar Unicorn!

      sudo /etc/init.d/unicorn_mi_aplicacion start

      Recuerda que puedes apagar y reiniciar Unicorn con los siguientes comandos:

      sudo /etc/init.d/unicorn_mi_aplicacion stop
      sudo /etc/init.d/unicorn_mi_aplicacion restart

      Cada que hagas cambios en tu código, deberás reiniciar Unicorn; si llegas a agregar alguna gema, es posible que restart no sea suficiente, sino que necesites darle stop y después start.

  8. Ahora vamos a realizar la conexión entre Nginx y Unicorn, primero nos movemos a nuestra carpeta de la aplicación:
    ~/apps/mi_aplicacion

    Y creamos el archivo config/nginx.conf con el siguiente contenido:

    upstream miapliacion {
      server unix:/tmp/unicorn.mi_aplicacion.sock fail_timeout=0;
    }
     
    server {
      listen 80;
      server_name www.miaplicacion.com miaplicacion.com;
      root /home/deployer/apps/mi_aplicacion/public;
     
      location ^~ /assets/ {
        gzip_static on;
        expires max;
        add_header Cache-Control public;
      }
     
      try_files $uri/index.html $uri @miaplicacion;
      location @miaplicacion {
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header Host $http_host;
        proxy_redirect off;
        proxy_pass http://miaplicacion;
      }
     
      error_page 500 502 503 504 /500.html;
      client_max_body_size 4G;
      keepalive_timeout 10;
    }

    Asegúrate de personalizar el valor de upstream, en el server_name poner los dominios o subdominios a los cuales quieres que responda tu aplicación, en root poner la ruta de la carpeta public de tu aplicación, y en el try_files location y proxy_pass escribir lo mismo que pusiste en upstream agregandole una arroba al inicio.

    Para que funcione tu dominio/subdominio debes apuntarlos primero a la IP de tu servidor; esto lo puedes hacer desde antes de hacer esta guía. Esto quiere decir que en este punto de la guía, al visitar tu dominio o subdominio, deberías ver la pantalla inicial de Nginx; sino, quiere decir que no has configurado dichos dominios con tu proveedor, esto se hace desde su panel de administración, por ejemplo en GoDaddy estableces los NameServers de Linode y en tu Linode agregas dichos dominios/subdominios para que al visitarlos desde tu navegador veas tu servidor.

    Muévete al directorio de los sitios disponibles de Nginx:

    cd /etc/nginx/sites-enabled/

    Crea un acceso directo como lo hicimos con unicorn:

    sudo ln -s /home/deployer/apps/mi_aplicacion/config/nginx.conf mi_aplicacion

    ¡Y reinicia Nginx!

    sudo service nginx restart

    ¡Ya deberías ver tu sitio online en ambiente productivo!

    Si te salen errores no olvides revisar los logs de producción en tu carpeta de la aplicación, los logs de unicorn igualmente dentro de tu carpeta, o los logs de nginx si te has equivocado en la configuración.

Recursos

How To Install Nginx On Ubuntu 14.04lts
How To Deploy Rails Apps Using Unicorn And Nginx On CentOS 6.5

Rails 4: where (first) vs find_by (take)

Normalmente para encontrar un registro, que sabía de antemano era único, usaba algo como:

Usuario.where( email: "hola@correo.com" ).first

Sin embargo, me acabo de enterar que en Rails 4 agregaron un método que lo abrevia:

Usuario.find_by( email: "hola@correo.com" )

Y cuando el elemento a encontrar es forzoso, podemos agregar un “!” para que mande una excepción de ActiveRecord::RecordNotFound si no lo encuentra:

Usuario.find_by!( email: "hola@correo.com" )

Y es que no solo se escribe un poco menos, sino que es más eficiente, ya que viendo la definición de find_by:

# File activerecord/lib/active_record/relation/finder_methods.rb, line 80
def find_by(*args)
  where(*args).take
end

Nos damos cuenta que usa take en lugar de first y la diferencia entre ellos es que first hace un ORDER extra:

First:

SELECT "usuarios".* FROM "usuarios" WHERE "usuarios"."email" = 'hola@correo.com' ORDER BY "usuarios"."id" ASC LIMIT 1

Take:

SELECT "usuarios".* FROM "usuarios" WHERE "usuarios"."email" = 'hola@correo.com' LIMIT 1

Por lo que si lo que necesitamos es obtener un registro único, es mejor utilizar find_by. :)

Configuración de una aplicación Rails 4 tradicional

Aplicación Rails tradicional vs SPA (Single Page Application)

Actualmente existen dos enfoques para desarrollar una aplicación web, el tradicional, que es impulsado por frameworks como Rails 4 y el de las SPA (Single Page Application).

En el enfoque tradicional tenemos todo nuestro código en una aplicación Rails. En ella tenemos toda la lógica de negocios en los modelos, el cómo la operamos en los controladores y la interfaz de usuario en las vistas. Programamos las vistas con Slim, Ruby y Sass, usamos gemas como simple_form para poder describir formularios en Ruby.

El enfoque SPA, por su lado, cuenta con dos aplicaciones, básicamente separadas: Un cliente web para la UI (en Javascript) y la aplicación servidor (Ruby+Rails). Esta separación nos lleva a diseñar la aplicación del servidor con una API JSON enfrente. Programamos las vistas con HTML, CSS y Javascript.

En principio, puede parecer atractiva la idea de hacer las vistas con Ruby y sus amigos, pero la verdad es que no hay como trabajar en el lenguaje del ambiente natural en donde se despliegan nuestras aplicaciones: Javascript.

En principio, también, puede parecer meh trabajar con HTML y amigos, sin embargo cuando descubres cosas como Grunt, Yeoman, Bower y AngularJS y lo que te permiten hacer en cuestión de organización del proceso de desarrollo, simplemente no puedes dar marcha atrás.

El desarrollo de la UI (User Interface) es en sí, un universo propio, requiere de herramientas adecuadas para poderla desarrollar de manera efectiva.

Ambos enfoques me agradan y he hecho buen uso de ellos en algunos proyectos que he desarrollado, sin embargo, me siento mucho más atraído por las SPA debido a la clara separación entre frontend y backend.

Proceso de creación

A continuación viene el comando que utilizo para crear una nueva aplicación Rails:

rails new NuevaAplicacion --skip-test-unit --database=postgresql

TODO: jruby con MS sqlserver

Prefiero minitest a testunit, y PostgreSQL a MySQL.

Inicializa git y realiza el primer commit.

cd NuevaAplicacion
git init
git add .
git commit -m "Commit inicial"

Proceso de configuración

Agrega el directorio de los IDEs de JetBrains a la lista de ignorados.

echo ".idea" >> .gitignore

Modifica Gemfile.

gem 'minitest-rails'
gem 'minitest-reporters'
gem 'pg'
gem 'slim-rails'
gem 'bootstrap-sass', '~> 3.0.0'
gem 'simple_form'

Instala las gemas.

bundle install

Genera configuraciones.

rails g minitest:install
rails g simple_form:install --bootstrap

Modifica config/application.rb

config.i18n.enforce_available_locales = true
config.time_zone = 'Mexico City'
config.i18n.default_locale = "es-MX"
config.sass.preferred_syntax = :sass
config.generators do |g|
  g.stylesheets false
  g.test_framework :minitest, :spec => true, :fixture => true
end

Crea un usuario y una base de datos para esta aplicación, revisa esta guía: Cómo instalar PostgreSQL en Ubuntu

Configura el host y el password en config/database.yml

development:
  host: localhost
  adapter: postgresql
  encoding: unicode
  database: NuevaAplicacion_development
  pool: 5
  username: NuevaAplicacion
  password: MiPalabraSecreta123

(Para las tres configuraciones: development, test & production).

Descarga el archivo es-MX.yml y ponlo en: config/locales/es-MX.yml
Lista de localizaciones para Rails

Modifica config/initializers/inflections.rb

ActiveSupport::Inflector.inflections(:en) do |inflect|
  inflect.clear
 
  inflect.plural(/$/, 's')
  inflect.plural(/([^aeéiou])$/i, '\1es')
  inflect.plural(/([aeiou]s)$/i, '\1')
  inflect.plural(/z$/i, 'ces')
  inflect.plural(/á([sn])$/i, 'a\1es')
  inflect.plural(/é([sn])$/i, 'e\1es')
  inflect.plural(/í([sn])$/i, 'i\1es')
  inflect.plural(/ó([sn])$/i, 'o\1es')
  inflect.plural(/ú([sn])$/i, 'u\1es')
 
  inflect.singular(/s$/, '')
  inflect.singular(/es$/, '')
 
  inflect.irregular('el', 'los')
end
Debes usar ActiveSupport::Inflector.inflections(:en) (en Inglés) para que Rails pluralice de forma adecuada nombres de rutas, controladores y modelos.

Crea app/assets/stylesheets/estilos.css.sass

@import "bootstrap"

Modifica app/assets/scripts/application.js

// Loads all Bootstrap javascripts
//= require bootstrap

Realiza el commit con los cambios en la configuración.

git add --all
git commit -m "Configuración inicial"

¡Listo, a desarrollar! ;)

Recursos

Inflexiones en español para Rails
Configurar usuario y base de datos en PostgreSQL

Cómo instalar PostgreSQL 9.3 en Ubuntu 14.04

Abre una terminal y teclea:

sudo apt-get install postgresql postgresql-client postgresql-contrib libpq-dev

Esto instala el cliente y servidor de la base de datos y algunos scripts de utilería. El paquete de libpq-dev nos servirá para poder compilar la gema Ruby para PostgreSQL más adelante.

Confirma que la instalación terminó adecuadamente tecleando:

psql --version

En mi caso la respuesta fue:

psql (PostgreSQL) 9.3.4

PostgreSQL Ruby gem

Si planeas usar PostgreSQL con Ruby, necesitarás esto:

gem install pg

En Rails, puedes crear una aplicación configurada para usar PostgreSQL así:

rails new mi-nueva-aplicacion -d postgresql

Asigna el host en database.yml

Si trabajas con Ruby y Rails, es posible que al ejecutar algunos comandos de base de datos, te encuentres con un error que dice algo como:

FATAL: Peer authentication failed for user “X”

Para evitarlo necesitas editar el archivo config/database.yml en tu aplicación Rails y agregar la línea siguiente en las tres configuraciones (development, test y production):

host: localhost

Cómo crear un usuario en la base de datos para la aplicación Rails

Para crear un usuario llamado usuario_ejemplo que puedas usar en tu database.yml, teclea:

sudo su postgres -c psql
CREATE USER usuario_ejemplo WITH PASSWORD 'xxxxxx';
ALTER ROLE usuario_ejemplo WITH CREATEDB;
\q

¡Listo! :D

Tuneando PostgreSQL

Es importante tunear el servidor PostgreSQL para tener un rendimiento aceptable en un ambiente de producción.
Checa esta excelente guía: PostgreSQL: HW Tunning

Recursos

Install PostgreSQL on Ubuntu 8.04 (cómo acceder a tu DB desde otras máquinas en la red).
Switching Rails to PostgreSQL
PostgreSQL — Guía Ubuntu Wiki
Is there a way to break into a PostgreSQL database if you forgot the password?
Improving the Command-Line Postgres Experience

Un par de problemas con Passenger fáciles de resolver

Si al instalar Passenger con:

1
gem install passenger

Te sale el siguiente mensaje:

1
2
3
4
...
** Execute (dry run) nginx
/home/tlacaelel/.rvm/gems/ruby-1.9.2-p180/gems/passenger-3.0.7/lib/phusion_passenger/standalone/runtime_installer.rb:224:in `*': negative argument (ArgumentError)
...

Se resuelve al reintentar la instalación, teclea de nuevo:

1
gem install passenger

Si después al ejecutarlo con:

1
passenger start -p3001

Te aparece:

1
2
3
You can stop Phusion Passenger Standalone by pressing Ctrl-C.
===============================================================================
Cannot execute '/var/lib/passenger-standalone/3.0.7-x86-ruby1.9.2-linux-gcc4.5.2-1002/support/helper-scripts/prespawn http://0.0.0.0:3001': Permission denied (13)

Lo resuelves con:

1
sudo chmod +x /var/lib/passenger-standalone/3.0.7-x86-ruby1.9.2-linux-gcc4.5.2-1002/support/helper-scripts/prespawn

Missing host to link to! Please provide :host parameter or set default_url_options[:host]

Al estar desarrollando una aplicación web con Rails 3 y Devise, me apareció el siguiente error al estar jugando con la característica lockable:

ActionView::Template::Error (Missing host to link to! Please provide :host parameter or set default_url_options[:host])

Investigando un poco me topé con que la solución consistía en hacer caso a la indicación que aparece en el README de Devise. Je.

Necesitamos configurar en cada ambiente (development, production, etc.) las URLs que se emplearán en el envío de correos electrónicos:

Aquí está la configuración para config/environments/development.rb:

config.action_mailer.default_url_options = { :host => 'localhost:3000' }

Y aquí una de ejemplo para config/environments/production.rb:

config.action_mailer.default_url_options = { :host => 'lobotuerto.com' }

Cómo mostrar las sentencias SQL en la consola de Rails

Al operar la consola de Rails, muchas veces quisieramos que al usar nuestros modelos se nos mostrara el SQL que se está generando.

Sólo agrega las siguientes líneas a tu archivo ~/.irbrc

1
2
3
4
5
6
7
8
if ENV['RAILS_ENV']
  # Called after the irb session is initialized and Rails has been loaded
  IRB.conf[:IRB_RC] = Proc.new do
    logger = Logger.new(STDOUT)
    ActiveRecord::Base.logger = logger
    ActiveResource::Base.logger = logger
  end
end

Ahora, cuando interactúes con la base de datos verás algo como esto:

1
2
3
>> Oficina.find 1
  Oficina Load (1.2ms)   SELECT * FROM "oficinas" WHERE ("oficinas"."id" = 1) 
=> #<Oficina id: 1, nombre: "CAMPECHE BCMR", organizacion_id: 2, activa: true>

Referencia

Showing SQL statements in the Rails console

Programando un PBBG en Ruby & Rails

[singlepic=610,90,,,left]

Después de mi corto regreso a la programación de videojuegos, y de haber visto por ahí y leído acerca de algunos PBBGs, finalmente he decido darme a la tarea de desarrollar uno.

PBBGs

Seguramente se preguntarán ¿qué es y cómo se juega un PBBG?

PBBG == Persistent Browser Based Game
Eso básicamente quiere decir: juego persistente para navegador.

La infraestructura y herramientas necesarias para desarrollar videojuegos en el ámbito del desarrollo web no son ni remotamente cercanas a las que existen para el desarrollo de escritorio.

Así, esto se convierte básicamente en un arte, hay que diseñar y desarrollar un videojuego alrededor de una estructura de operación ya establecida como lo es el protocolo HTTP, el modelo cliente-servidor y los tiempos de respuesta acostumbrados de una página web.

Por esta razón, la gran mayoría de los PBBGs se inclinan por uno de estos dos géneros:

  • Juegos de rol
  • Juegos de estrategia

O alguna mezcla rara entre ellos.

El modelo de participación preferido y más fácil de implementar es por turnos, aunque algunos de los PBBGs más modernos están incorporando un modelo de participación en tiempo real.

Si no conoces aún algún PBBG, aquí te dejo unos enlaces para que te des una idea de cómo son y cómo se juegan:

Los juegos de estrategia tradicionalmente se dividen en: por turno (TBS) [turn based strategy] y en tiempo real (RTS) [real time strategy]. En los PBBG he visto mucho el uso de tiempo instantáneo (ITS) [instant time strategy].

Instant Time Strategy (ITS)

Por lo que he visto la estrategia en tiempo instantáneo es muy popular entre los desarrolladores de PBBGs.

Modelan combates enteros con ecuaciones y obtienen de manera inmediata el resultado de las peleas.

Aunque adecuado a la situación, este nivel de abstracción se me antoja demasiado alto para mi proyecto. Me llama la atención el implementar algo más cercano al tiempo real (o una mezcla de tiempo real y turnos).

Ahora con tecnologías como Ajax, lenguajes como Ruby y frameworks como Rails, no es tan complicado hacer un PBBG.

Ya que andamos hablando de tecnologías, les presento mi stack de desarrollo.

Mi development stack

Aquí pongo la lista de las herramientas que estoy utilizando para llevar a cabo este proyecto:

  • Linux (nada mejor para el desarrollo en general)
  • PostgreSQL (una robusta base de datos)
  • Ruby (sigo enamorado de este lenguaje)
  • Rails (web development framework)
  • jQuery (javascript framework)
  • Formtastic (excelente para lidiar con formas)
  • Authlogic (para implementar la autenticación de usuarios)
  • Haml (lenguaje para escribir las vistas HTML de la aplicación)
  • Sass (lenguaje para escribir el CSS de la aplicación)
  • Compass (framework CSS para hacer el layout de la aplicación)
  • git (version control system)
  • emacs (editor de código)

Tengo grandes planes para este PBBG: misiones, peleas entre clanes, clases variadas, habilidades especiales, mercado, subastas y una vibrante comunidad a su alrededor.

Pero como todo: debe empezar por algún lado.

Modelando los combates

Veamos un elemento que considero fundamental para este PBBG: El sistema de batallas.

En mi caso particular, si algo deseo ver funcionando primero son los combates.

Había comentado antes que quiero mis batallas en tiempo real (o algo que se le acerque). El tiempo real que puedes conseguir en una aplicación web no es el común de 60 fps de los videojuegos tradicionales.

Aquí tienes que pensar en término de peticiones por segundo a tu servidor web. GET, POST, params, sesiones, etc.

A continuación pongo una lista con algunas de las características que me gustaría ver en el sistema de batallas:

Representar y llevar a cabo un combate entre varios participantes

  • Duelos entre jugadores
  • Duelos entre NPC y jugadores
  • Duelos entre grupos de jugadores

Durante el combate los personajes podrán hacer uso de habilidades especiales, objetos y armas

  • Un guerrero puede dar un golpe especial con su arma
  • Un brujo puede hacer uso de alguna magia
  • Un guerrero puede hacer uso de una poción para curarse

En la pelea, los jugadores podrán seleccionar un objetivo para atacar

  • Un guerrero puede seleccionar al enemigo de su preferencia para recibir sus ataques

En el próximo artículo pondré algo de código del sistema de batallas, las decisiones de diseño que se tomaron y una breve explicación de cómo funciona.

Suena bien para comenzar, ¿no?

Cómo instalar PostgreSQL en Ubuntu 11.04

[singlepic=668,160,,,left]

Acabo de incorporarme a un proyecto en Rails en el que usan PostgreSQL, y como recién formateé y le puse Ubuntu 9.04 a la laptop, necesito ahora instalar este manejador de base de datos.

Y es un buen pretexto para por fin escribir la guía de cómo instalarlo en Ubuntu.

Como siempre, vamos a la terminal (Aplicaciones → Accesorios → Terminal) y tecleamos:

1
sudo apt-get install postgresql postgresql-client postgresql-contrib libpq-dev pgadmin3

Eso instala el cliente y servidor de la base de datos, algunos scripts de utilería y la aplicación pgAdmin para administrar la base de datos. El paquete de libpq-dev nos servirá para poder compilar la gema Ruby de PostgreSQL más adelante.

Confirmemos que la instalación terminó adecuadamente teclando:

1
psql --version

En mi caso la respuesta fue:
psql (PostgreSQL) 8.4.7

Cambiar la contraseña del usuario administrador

Ahora necesitamos establecer la contraseña del usuario administrador postgres. Teclea la siguiente línea en la terminal (cambia la palabra password por la contraseña que desees usar):

1
2
3
sudo su postgres -c psql
ALTER USER postgres WITH PASSWORD 'password';
q

Eso altera la contraseña dentro de la base de datos, ahora necesitamos hacer lo mismo para el usuario Linux postgres:

1
2
sudo passwd -d postgres
sudo su postgres -c passwd

Te aparecerá un prompt, introduce la misma contraseña que pusiste antes.

Poner a punto pgAdmin

Listo, de ahora en adelante podemos usar pgAdmin o la terminal para administrar nuestra base de datos como el usuario postgres. Pero antes de que te metas a pgAdmin deberías configurar el PostgreSQL Admin Pack, que te permite llevar un mejor registro y monitoreo de tu base de datos.

Ejecuta lo siguiente desde la línea de comandos en tu terminal:

1
sudo su postgres -c psql < /usr/share/postgresql/8.4/contrib/adminpack.sql

Para ejecutar pgAdmin ve a tu menú de aplicaciones:
Aplicaciones → Programación → pgAdmin III

Cambiar el esquema de autentificación de PostgreSQL

Al ejecutar algunos comandos de base de datos, es posible que te encuentres con un error que dice algo como:

FATAL: la autentificación Ident falló para el usuario «x»

Para evitarlo necesitas editar el archivo /etc/postgresql/8.4/main/pg_hba.conf y cambiar el esquema de autentificación. Abre el archivo con privilegios de root:

1
sudo gedit /etc/postgresql/8.4/main/pg_hba.conf

Y cambia esto:

1
2
# Database administrative login by UNIX sockets
local   all         postgres                          ident

Por:

1
2
# Database administrative login by UNIX sockets
local   all         postgres                          md5

Reinicia el servidor de PostgreSQL tecleando en tu terminal:

1
sudo /etc/init.d/postgresql restart

PostgreSQL Ruby gem

Si planeas usar PostgreSQL dentro de Ruby, necesitarás esto:

1
gem install pg

Si deseas instalar la gema desde código fuente, sigue estas instrucciones.

En Rails 3, puedes crear una aplicación configurada para usar PostgreSQL con este comando:

1
rails new mi-nueva-aplicacion -d postgresql

¡Listo! :D

Recursos

Install PostgreSQL on Ubuntu 8.04 (cómo acceder de manera remota a tu servidor)
Switching Rails to PostgreSQL