Apuntes Rails

Apuntes de Ruby on Rails, programación en GNU/Linux y Mac

Artículos interesantes

TAGS: None

Problema con Mongrel y los HEADERS

TAGS: None

Resulta que al desplegar una app con un servidor mongrel me fallan las funciones ajax. Mirando el archivo de logs de mongrel veo lo siguiente:

  1.  
  2. tail -n 100 log/mongrel.log
  3.  
  4. Error calling Dispatcher.dispatch #<NoMethodError: You have a nil object when you didn‘t expect it!
  5. You might have expected an instance of Array.
  6. The error occurred while evaluating nil.split>
  7. /usr/local/lib/ruby/gems/1.8/gems/actionpack-2.3.11/lib/action_controller/cgi_process.rb:54:in `dispatch_cgi’
  8.  

A través de aquí meentero que es problema del action pack y modifico el archivo cgi_process.rb:54

cambio:

  1.  
  2.  if headers.include?(‘Set-Cookie’)

por :

  1. if headers[‘Set-Cookie’]

Reinicio el servidor y andado!!

  1.  
  2.  mongrel_rails stop -P log/mongrel3001.pi
  3.  
  4.  mongrel_rails start -d -e development -p 3001 -P log/mongrel3001.pi</code>

Creando un filtro fecha

TAGS: None

Aunque parezca una tontería pero siempre es util tener un partial con un selector de fecha.

Creamos un parcial por ejemplo _date_select.erb

  1. <%
  2. name = "date" if name.nil?
  3. %>
  4.      <%=select_day(1,:prefix=>name)%>/
  5.      <%=select_month(Date.today,
  6. :use_month_names =>  %w( Enero Febrero Marzo Abril Mayo Junio Julio Agosto Septiembre Octubre Noviembre  Diciembre),:prefix=>name)%>/
  7.      <%= select_year(Date.today, :start_year => Communicationsview.first_year, :end_year =>Communicationsview.last_year,:prefix=>name) %>
  8.  

Ahora solo falta llamar desde una vista usando

  1. <%=render :partial=>"/fijos/date_filter" , :locals=>{:name =>"filtro[fecha]"} %>
  2.  

Fácil, verdad?

Problemas con Rails 2.2 y MySql

Tags: ,

Recién actualizado Rails a su versión 2.2 me encuentro con el siguiente error:

!!! The bundled mysql.rb driver has been removed from Rails 2.2. Please install the mysql gem and try again: gem install mysql.

Intento instalar la gem de mysql pero me suelta:


Building native extensions. This could take a while...
ERROR: Error installing mysql:
ERROR: Failed to build gem native extension.

*** extconf.rb failed ***
Could not create Makefile due to some reason, probably lack of
necessary libraries and/or headers. Check the mkmf.log file for more
details. You may need configuration options.

Bien, he dado con este post donde explica que solo tenemos que instalar lo siguiente:

  1. sudo apt-get install libmysqlclient15-dev
  2. sudo gem install mysql

En mi mac me ha pasado lo mismo y e seguido este artículo:

  1. sudo gem install mysql — –with-mysql-config=/usr/local/mysql/bin/mysql_config
  2.  

También me he encontrado con los siguientes problemas con algunas de las aplicaciones anteriores que tenia.

undefined method `cache_template_extensions=' for ActionView::Base:Class

Se soluciona comentando la linea cache_template_extensions = false de config/environments/development.rb

En otra aplicación me soltaba:

uninitialized constant ApplicationController

Se soluciona haciendo

  1. rake rails:update

Y con el plugin filecolumn igual:

Nos vamos al archivo file_column.rb y en la linea 619 ponemos

  1. ActiveSupport::Inflector.underscore(self.name).to_s

Espero que os sea de ayuda

Backup de Rails usando Rake

TAGS: None

Para simplificar los backups de nuestras aplicaciones podemos usar rake. Para hacernos con el es recomendable consultar el siguiente artículo Ruby on Rails Rake Tutorial

Los scripts propios los creamos en la carpeta lib/task

Vamos a crear un conjunto de acciones (task) dentro de la categoría (namespace) rbackup.

Queremos que este script nos haga un backup de la base de datos y de algunas carpetas de public (por ejemplo la carpera upload) y que nos copie todo comprimido en un archivo accesible desde la web.

Lo primero que hacemos es crear el archivo lib/task/rbackup.rake y definir la categoria:

  1. namespace :rbackup do
  2.  
  3. end

Bien, ahora vamos a definir las acciones que vamos a necesitar

  1. namespace :rbackup do
  2. desc "Crea los directorios tmp/backup y public/backup"
  3. task :crea_dir do
  4. end
  5.  
  6. desc "Copia de seguridad de la base de datos en la carpeta tmp/backup"
  7. task :base_datos => :crea_dir do
  8. end
  9.  
  10. desc "Crea una copia de seguridad de las carpetas indicadas"
  11. task :carpetas => :crea_dir do
  12. end
  13.  
  14. desc "Crea una copia de la BD y de las carpetas y las comprime en pubic/backup "
  15. task :all => [:base_datos, :carpetas]do
  16. end
  17. end

Ejecutando rake –task y nos da información de losa task disponibles
Para ejecutar estas acciones podemos poner rake rbackup:base_datos o rake rbackup:all

Vamos a crear los task….

Este nos creará los directorios si no existen

  1. task :crea_dir do
  2. unless File.exist?("#{RAILS_ROOT}/public/backup")
  3. puts "Creando directorio public/backup"
  4. sh "mkdir #{RAILS_ROOT}/public/backup/"
  5. end
  6. unless File.exist?("#{RAILS_ROOT}/tmp/backup")
  7. puts "Creando directorio tmp/backup"
  8. sh "mkdir #{RAILS_ROOT}/tmp/backup/"
  9. end
  10. end

Para hacer el backup de la base de datos extraemos los datos del archivo database.yml para poder usarlos con el comando mysqldump

Como usamos YAML es necesario poner al principio del archivo require ‘yaml’

  1. task :base_datos => :crea_dir do
  2. @conf = YAML::load(File.open("#{RAILS_ROOT}/config/database.yml"))
  3. @db = @conf[‘development’]
  4. # Hacemos una copia de la base de datos en el directorio temporal
  5. puts "******  Creando copia de seguridad de #{@db['database']}…  ******"
  6. sh "mysqldump –opt –user=#{@db['username']} –password=#{@db['password']} #{@db['database']} -h #{@db['host']} > tmp/backup/#{@db['database']}.sql"
  7. end

con => :crea_dir le indicamos que tiene que ejecutar antes el task crea_dir

Nota: si no ponemos -h #{@db['host']} puede salirnos el error mysqldump error 2002

Ahora comprimimos las carpetas usando tar.

  1. desc "Crea una copia de seguridad de las carpetas indicadas"
  2. task :carpetas => :crea_dir do
  3. @carpetas = %w(images uploads)
  4. for carpeta in @carpetas
  5. puts "****** Creando copia de #{carpeta}… ******"
  6. system("tar cvzf ‘#{RAILS_ROOT}/tmp/backup/#{carpeta}.tar.gz’ ‘#{RAILS_ROOT}/public/#{carpeta}’")
  7. #  unless  system(comando)
  8. #    flash[:error] = comando
  9. #  end
  10. end
  11. end

En la variable @carpetas ponemos las carpetas de pubic de las que queremos hacer el backup

Por ultimo hacemos un task que nos ejecute todas las acciones:

  1. task :all => [:base_datos, :carpetas]do
  2. puts "******  Comprimiendo y publicando….  ******"
  3. system("tar cvzf  ’#{RAILS_ROOT}/public/backup/#{@db['database']}#{Date.today}.tar.gz’ ‘#{RAILS_ROOT}/tmp/backup’")
  4. puts "******  #{@db['database']}#{Date.today}.tar.gz creado  ******"
  5. puts "******  Borrando datos de tmp/backup…  ******"
  6. system("rm -f #{RAILS_ROOT}/tmp/backup/*")
  7. end

Ya tenemos nuestro script rake terminado. Ahora podemos crear un controlador para tener acceso a los archivos generados y poder borrarlos una vez descargados.

Creamos un controlador rbackup_controller.rb y ponemos:

  1. class RbackupController < ApplicationController
  2.  
  3. def index
  4. @dir = Dir.new("#{RAILS_ROOT}/public/backup")
  5. @archivos = Array.new
  6. @dir.each do |x|
  7. if x[0] != 46
  8. @archivos =   @archivos + ["#{x}"]
  9. end
  10. end
  11.  
  12. end
  13.  
  14. def borrar
  15. comando = "rm -f #{RAILS_ROOT}/public/backup/#{params[:archivo]}"
  16. unless  system(comando)
  17. flash[:error] = comando
  18. end
  19. redirect_to :action => ‘index’
  20. end
  21. end

Ahora solo queda poner en la vista del controlador:

Listado de Archivos generados<br><br>

<% for archivo in @archivos %>

<%=link_to archivo, “backup/#{archivo}”%> - <%=number_to_human_size File.size(”#{RAILS_ROOT}/public/backup/#{archivo}”)%> - <%=link_to “borrar” , {:controller=>:rbackup,:action=>:borrar,:archivo=>archivo}, :confirm =>”Desea borrarlo?”%><br>

<% end %>
y tenemos un sistema de backups básico.

Insertar datos en la BD usando las migrations de Rails

TAGS: None

A veces cuando creamos una tabla a través de las migrations de Rails es necesario meterle algunas filas por defecto. Este es un ejemplo de como hacerlo.

Creamos una migración usando

./script/generate migration datos_personas

Esto nos creará un archivo en db/migrate que es el que tenemos que modificar. Por ejemplo

008_datos_personas.rb

class DatosPersonas < ActiveRecord::Migration
def self.up
end

def self.down
end
end

Para poder insertar los campos en la tabla personas debemos definir el modelo que controla la tabla dentro de la migracion

class DatosPersonas < ActiveRecord::Migration

class Personas < ActiveRecord::Base
end

def self.up

create_table :personas do |tabla|

tabla.column :nombre, :string
tabla.column :apellidos, :string
tabla.column :edad, :integer

end

Personas.new( :nombre => “Pedro”, :apellidos => “Marin”, :edad=29).save

end

def self.down

drop_table :personas

end
end

Es así de fácil. Los datos que podemos usar son:

:integer
:float
:datetime
:date
:timestamp
:time
:text
:string
:binary
:boolean

Y las acciones que podemos ejecutar:
create_table(name, options)
drop_table(name)
rename_table(old_name, new_name)
add_column(table_name, column_name, type, options)
rename_column(table_name, column_name, new_column_name)
change_column(table_name, column_name, type, options)
remove_column(table_name, column_name)
add_index(table_name, column_name, index_type)
remove_index(table_name, column_name)

Archivos de configuración con YAML para varios idiomas

TAGS: None

Creando una web me he encontrado con el problema de poner determinados textos en varios idiomas. Sin querer meterme en muchos follones (hay plugin para ello) y buscando una solución muy sencilla y rápida, un compañero de la lista de Rails me sugirió YAML. (Aquí y aquí hay información de YAML en Ruby)
El objetivo es el siguiente. Necesito un hash con los los textos que quiero poner en varios idiomas. Por ejemplo:

Español: { “menu_inicio” => “Inicio”, “listado_personas”=>”Listado Personas” }

Ingles: { “menu_inicio” => “Home”, “listado_personas”=>”List of Persons” }

Lo que quiero es guardar los datos de cada idioma en un archivo, y dependiendo del idioma seleccionado, cargar un archivo u otro. ok?

Creamos una carpeta lang donde guardar los siguientes archivos en formato YAML.
es.yml

menu_inicio: “Inicio”

listado_personas: “Listado de Personas”

en.yml

menu_inicio: “Home”
listado_personas: “List of Persons”


Ahora vamos a preparar la aplicación para cargue el archivo dependiendo del idioma. Modificamos el controlador principal de la aplicación.

application.rb

require ‘yaml’ # Necesario NO OLVIDAR!!!!

class ApplicationController < ActionController::Base

def idioma

@idioma = actualiza_idioma #funcion que captura si se ha cambiado de idioma. Por defecto devuelve 1
#Dependiendo del idioma cargamos un archivo u otro
case @idioma.to_i

when 1 then archivo = “es.yml”
when 2 then archivo = “en.yml”

end

@lang = YAML::load(File.open(”#{RAILS_ROOT}/lang/#{archivo}”))

end

Bien así de sencillo. Ahora en cualquier vista podemos poner <%=lang['menu_inicio'] %> y nos lo mostrará en el idioma seleccionado.

PD: Se me olvidaba, tenemos que poner en los controladores before_filter :idioma para que ejecute la función

Creación de un proyecto Rails usando Subversion

TAGS: None

Estos son unos apuntes personales sobre la creación de un proyecto en rails usando subversion (sistema de control de versiones). Si buscas, seguro encontrarás artículos mas completos que este. ;)
Vamos a crear una base de datos vacía para el proyecto (Las tablas las crearemos usando migration)

mysqladmin -u root create inmobiliaria

Suponiendo instalado RoR (Ruby on Rails) en tu ordenador creamos un proyecto

rails inmobiliaria

Esto nos crea la estructura básica para nuestro proyecto. Ahora vamos a configurar el acceso a nuestra base de datos. Editamos el archivo inmobiliaria/config/database.yml

development:
adapter: mysql
database: inmobiliaria
socket: /var/run/mysqld/mysqld.sock
username: peluo
password: atitelovoyadecir
host: localhost

Importante: Dependiendo del sistema operativo, tendrás que especificar la ubicación del socket de mysql.

Bien, supuestamente ya tenemos una aplicación conectada a nuestra base de datos.

Para ver que todo está bien ejecutamos ./script/server y nos metemos en http://localhost:3000

Es hora de ponernos con subversion.(Como instalar subversion, Subversion en 28 segundos, Introduccion a subversion )

En el servidor donde vayamos a crear el repositorio creamos la carpeta donde guardaremos todos los datos.

Por ejemplo creamos /var/lib/svn.

Ahora dentro de esa carpeta ejecutamos svnadmin create inmobiliaria. Esto nos creará una estructura vacía.

Ahora tenemos que rellenar esta estructura. Desde el ordenador cliente, donde hemos creado el proyecto rails, ejecutamos:

svn import inmobiliaria svn+ssh://direccion_servidor/var/lib/svn/inmobiliara

o

svn import inmobiliaria http://direccion_servidor/svn/inmobiliara

(Depende como hayamos configurado el servidor)

o

svn import inmobiliaria file:///var/lib/svn/inmobiliaria si lo hacemos desde el propio servidor

Ya tenemos los datos en el repositorio. Para empezar a trabajar tenemos que descargarnos los datos desde el servidor (no nos vale la estructura del proyecto que tenemos ya que no la controla subversion). Movemos el proyecto a por ejemplo inmobiliaria_old y ejecutamos:

svn co http://direccion_servidor/svn/inmobiliara inmobiliaria

Ya tenemos el proyecto bajo el control de subversion. Ahora solo falta aplicar los comandos de este articulo -> Como usar Rails con Subversion

SVN y servidores con IP dinámicas

TAGS: None

Bueno, este es el problema que he tenido. Tengo el servidor de subversion en mi casa y desde otro ordenador actualizo el código con un svn up.

El problema se presenta cuando cambian la ip de mi acceso a internet. Al crear la primera copia del repositorio usé el comando

svn co http://80.123.123.123/svn aplicacion.

Al cambiar me la IP subversion sigue buscando en la ip anterior. Mirando la documentación me encuentro el subcomando sw y se supone que haciendo esto

svn sw http://ip_nueva/svn aplicacion

debería cambiarme la ip del repositorio del cliente, pero por alguna razón no funciona (y mira que he probado cosas).

Solución que le he dado. He echado mano del archivo /etc/host del ordenardor del cliente. He puesto la siguiente linea.

80.123.123.123 servidor_svn

y he vuelto a descargar el repositorio

svn co http://servidor_svn/svn aplicacion

Ahora, cada vez que cambie la IP de mi servidor, solo tengo que modificar el archivo host.

© 2009 Apuntes Rails. All Rights Reserved.

This blog is powered by Wordpress and the Magatheme Wordpress Theme by Mid MO SEO.