miércoles, 18 de abril de 2012

Como utilizar spree en heroku

Spree es una plataforma de comercio electrónico, para más información presiona aqui. Heroku es una plataforma para aplicaciones en la nube.

Hasta ahi todo facil, resulta que spree en su configuración por defecto (de hecho está quemado en el código) solo permite grabar las imagenes de productos de forma local, pero en cambio heroku no permite guardar archivos en disco (el sistema de archivos para las aplicaciones es de solo lectura).

Entonces. ¿Cómo hago para usar mezcladas estas 2 plataformas?

Pues bueno, es fácil (relativamente), toca configurar la aplicación para que use algun servicio de hospedaje en la nube (en mi ejemplo usaré Amazon S3) y modificar un poco la gema de spree (sobreescribir los modelos que tengan attachments) y pues estos son los pasos:
Creamos una aplicación de ejemplo (en el momento de escribir esto spree solo funciona con rails 3.1 (desde 3.1.1 hasta 3.1.4)

rails new ejemplo_spree
cd ejemplo_spree

Crea la base de datos (como por defecto rails usa SqLite pues no toca configurar nada)

rake db:create

Instala la gema de spree
 
gem install spree

Instala spree en tu aplicación

spree install --auto_accept

Hasta aquí, spree debería estar funcionando por lo que levanta el server para la app y verifica (http://localhost:3000)

rails s

Bueno, ahora como hacer que la aplicación funcione en heroku?

Crea un initializer y pon el siguiente código:

Spree::Image.class_eval do
    definition = self.attachment_definitions[:attachment]
    definition.delete :url
    definition[:path] = definition[:path].gsub(':rails_root/public/', '')
    definition[:storage] = 's3'
    definition[:bucket] = ENV['S3_BUCKET']
    definition[:s3_credentials] = {:access_key_id => ENV['S3_KEY'], :secret_access_key => ENV['S3_SECRET']}
  end

  Spree::Taxon.class_eval do
    definition = self.attachment_definitions[:icon]
    definition.delete :url
    definition[:path] = definition[:path].gsub(':rails_root/public/', '')
    definition[:storage] = 's3'
    definition[:bucket] = ENV['S3_BUCKET']
    definition[:s3_credentials] = {:access_key_id => ENV['S3_KEY'], :secret_access_key => ENV['S3_SECRET']}
  end

Lo hice separado para cada modelo para tratar de hacerlo más entendible pero no te olvides de usar DRY.

Aqui viene la primera inquietud (supongo): ¿y esas variables de ambiente ENV[xxx] como las seteo en heroku? pues bueno dentro de unas cuantas líneas responderé esa inquietud

Ahora toca agregar a la aplicación las gemas para Amazon S3 por lo que edita el Gemfile y agrega:

gem 'aws-s3'
gem 'aws-sdk'

instalamos las gemas

bundle install

Heroku utiliza git como repositorio para el código por lo que hacemos un repositorio para nuestra applicación y la creamos en heroku:

git init
git add .
git commit -m "Primer commit"
heroku create ejemplo_spree
git push heroku master

Al ser un proceso interactivo la creación de los datos iniciales de spree, la forma más facil de replicarlos en heroku es copiando los datos locales:

gem install tap
heroku db:push
heroku restart

Configuramos las variables de ambiente en heroku:

heroku config:add S3_KEY=el_key S3_SECRET=el_password S3_BUCKET=el_bucket

Habilitamos a heroku para que use sendgrid para enviar correos:

heroku addons:add sendgrid:starter

hasta ahi, la aplicacion deberia funcionar.

Ahora el problema es que las imágenes de las migraciones fueron creadas localmente, como las veo desde mi aplicación en heroku?

Sube las imagenes ubicadas en root_app/public/spree a tu cuenta de amazon en el bucket asignado para la aplicación y listo.

Y bueno eso es todo. Ahora deberias tener una aplicación usando spreed y que funcione en heroku.