viernes, 21 de diciembre de 2012

MongoDB en rails

Hay casos en los que una base de datos relacional no es la mejor opción. Si vamos a acceder siempre por una clave, y el objeto es bastante grande, es más conveniente usar una BBDD noSql.
En este caso, para Ruby on Rails, lo más extendido es usar MongoDB.

Configurar la aplicación es bastante sencillo. En el Gemfile metemos las gemas necearias. La principal es mongomapper: Si vamos a necesitar serializar objetos, también incluimos bson_ext:

# mongo db
gem "mongo_mapper"
gem "bson_ext"

Ahora tenemos que crear un fichero de configuración, y un initializer. En el de configuración (mongodb.yml, por ejemplo) meteremos la dirección, el nombre, ... de la base de datos MongoDB:

development:
  host: localhost
  port: 27017
  database: myapp-development

test:
  host: localhost
  port: 27017
  database: myapp-test

production:
  host: remote-host # (for me amazon ec2)
  port: 27017
  database: myapp-production

En el initializer (mongo.rb) creamos la conexión:

database_yaml = YAML::load(File.read("#{Rails.root}/config/mongodb.yml"))
puts "Initializing mongodb"

mongo_database = database_yaml[Rails.env]

MongoMapper.connection = Mongo::Connection.new(mongo_database['host'], mongo_database['port'])
MongoMapper.database = mongo_database['database']

if defined?(PhusionPassenger)
  PhusionPassenger.on_event(:starting_worker_process) do |forked|
    MongoMapper.connection.connect if forked
  end
end

Si sólo usamos modelos en mongoDB, debemos eliminar las referencias a ActiveRecord de la aplicación, ya que si no nos daría errores. En el fichero config/application.rb comentamos la línea donde pone "require 'rails/all'" y en su lugar ponemos:

require "action_controller/railtie"
require "action_mailer/railtie"
require "active_resource/railtie"
require "rails/test_unit/railtie"
require "sprockets/railtie"

Así evitamos que se requiera el AvtiveResource.

Ahora, creamos el modelo, mapeado por mongomapper:

class MyClase
  include MongoMapper::Document

  key :num_cosas, Integer, :default => 0
  key :fecha_cambio, Date

  key :nombre, String
end

Y con esto, al levantar la aplicación, podremos acceder a los objetos vía mongo-db