Tag Archives: Ruby on Rails

Ruby: Convertir Números en Palabras (Cantidad con Letra)

Cierto día en el trabajo nos pusimos a hacer un pequeño gem que le hace un override a la clase Numeric de Ruby, agregando un método de instancia to_words que entrega el número en texto. El número puede estar entre 0 y 9 quintillones (como si realmente necesitaras esta cantidad 😀 ). Esta hecho para que lo escriba en español de la siguiente forma:
$ irb(main):001:0> require 'rubygems'
$ => true
$ irb(main):002:0> require 'number_to_words'
$ => true
$ irb(main):003:0> 5678.to_words
$ => "cinco mil seiscientos setenta y ocho"

Y para que te sirva para un cheque, osea para uso monetario….

$ irb(main) :004:0> number = 4567.90
$ => 4567.9
$ irb(main):005:0> number.to_words.capitalize << " pesos " << (number.to_s.split(".")[1] || 0).rjust(2,'0')<< "/100 M.N."
$ => "Cuatro mil quinientos sesenta y siete pesos 09/100 M.N."

Hasta el momento nos ha funcionado a la perfección.
Para instalarlo y usarlo hechenle un ojo al sitio de github http://github.com/innetra/number_to_words/tree/master.

Si le encuentran defectos, errores o se les ocurre una mejora dejenme saber para ver si se incluye. Espero les sirva. Saludos.
Recommend Me

auto_complete en Ruby on Rails

Esto solía ser nativo de rails en las primeras versiones, sin embargo, a partir de la 2.0 si mal no recuerdo, fue extraido a un plugin. Este plugin esta muy bueno para auto completar text_fields en formularios.
Para usarlo primero hay que instalarlo, asi que desde la carpeta vendor/plugins de nuestra aplicación rails:
$ git clone git://github.com/rails/auto_complete.git
$ rm -rf auto_complete/.git
O bien desde la carpeta root de tu proyecto Rails.
$ ./srcipt/plugin install git://github.com/rails/auto_complete.git

Para ver buenos ejemplos de como usar este plugin recomiendo ver el capítulo 102 en Railscasts.com y el ejemplo que D.H.H. puso aqui http://github.com/rails/auto_complete/tree/master

Ahi lo tienen.
Comentarios, preguntas, dudas e insultos son bienvenidos, dejen un mensaje.
Recommend Me

Sending mail smtp gmail, with attachment using Ruby on Rails: ActionMailer

Ruby on rails has a native class to send email. It may look easy but it can get confusing when you have to configure your rails app to manage this.
All the configuration must be in the environment.rb file or in any specific environment file ( development.rb, production.rb, test.rb), however I sugest using environmet.rb so you won’t have to repeat configuration.

All the information on configuration is at http://api.rubyonrails.org but here is an example using gmail.

config/environment.rb
config.action_mailer.delivery_method = :smtp

# I do care if the mailer can't send
config.action_mailer.raise_delivery_errors = true

# Include your app's configuration here:
config.action_mailer.smtp_settings = {
:address => "smtp.gmail.com",
:port => "587",
:domain => "my_app_domain", #Example: blog.local
:authentication => :plain,
:user_name => "my.gmail.account",
:password => "th1s1s4l33tpwd!"
}

That is all the configuration to send the mail, now you need to create your mailer.
$ script/generate mailer my_mailer

Write all the logic of this mailer on the “model” my_mailer.rb, here is an example that also sends an attachment, I asume that you have a user model or a person model, this model should have a field name and email:

app/models/my_mailer.rb
class MyMailer < ActionMailer::Base

def email(recipient)
recipients recipient.email
from "my.gmail.account@gmail.com"
subject "This is a test mail"
body :user => recipient # Im sending the recipient object as a local variable in a partial, but you will access it as an instance variable

@file_name = "#{RAILS_ROOT}/public/attachment.txt"
create_attachment
attachment :content_type => "text/plain",
:filename => "Some useless attachment",
:body => File.read(@file_name)
delete_attachment_file
end

protected
def create_attachment
attachment = File.new(@file_name, 'w')
attachment.puts "I am a useless text file"
attachment.puts " C(0_0)D "
attachment.close
end

def delete_attachment_file
File.delete(@file_name)
end
end

Now let’s make a view for the mail layout. This view will define the body or content of your mail.
So now you need to create a file named email.erb this is because our method that sends the mail is named email, so this basically works as the views for the controller actions. Create your file under views/my_mailer. Here is an example that uses the local variable user that I send from the email method.

app/views/my_mailer/email.erb

Hello . I have an attachment for you :)

Ok now you have almost everything done, but we still have to call our email method. This is done using a dynamic method deliver_my_method_name(param_1, param_2, …, param_n)

This is an example of this dynamic method called from the person model.

app/models/person.rb
class Person < ActiveRecord::Base
def send_email
MyMailer.deliver_email(self) # I am sending the person as a parameter.
end
end

One last thing, to send email using accounts that need tsl like gmail you need some libraries that will give you extra methods. What i did to solve this was to create a lib file in my Rails application under the lib directory ( I know this is obvious but i have to be specific 😀 ). This is the code of that file, I found this code googling and I just copied it into my app, it works for me and I hope it’ll work for you:

lib/smtp_tsl.rb
require "openssl"
require "net/smtp"

Net::SMTP.class_eval do
private
def do_start(helodomain, user, secret, authtype)
raise IOError, 'SMTP session already started' if @started
if RUBY_VERSION == "1.8.7"
check_auth_args user, secret if user or secret
else
check_auth_args user, secret, authtype if user or secret
end

sock = timeout(@open_timeout) { TCPSocket.open(@address, @port) }
@socket = Net::InternetMessageIO.new(sock)
@socket.read_timeout = 60 #@read_timeout
#@socket.debug_output = STDERR #@debug_output

check_response(critical { recv_response() })
do_helo(helodomain)

if starttls
raise 'openssl library not installed' unless defined?(OpenSSL)
ssl = OpenSSL::SSL::SSLSocket.new(sock)
ssl.sync_close = true
ssl.connect
@socket = Net::InternetMessageIO.new(ssl)
@socket.read_timeout = 60 #@read_timeout
#@socket.debug_output = STDERR #@debug_output
do_helo(helodomain)
end

authenticate user, secret, authtype if user
@started = true
ensure
unless @started
# authentication failed, cancel connection.
@socket.close if not @started and @socket and not @socket.closed?
@socket = nil
end
end

def do_helo(helodomain)
begin
if @esmtp
ehlo helodomain
else
helo helodomain
end
rescue Net::ProtocolError
if @esmtp
@esmtp = false
@error_occured = false
retry
end
raise
end
end

def starttls
getok('STARTTLS') rescue return false
return true
end

def quit
begin
getok('QUIT')
rescue EOFError, OpenSSL::SSL::SSLError
end
end
end

Enjoy. Leave me a comment if you see anything funny, annoying, cool or just to say hello.
Recommend Me

Ya tenemos Rails 2.2. Necesita actualización de Ruby gems

Rails 2.2 fue liberado hace algunos días. Rayan Bates de railscasts.com ya tiene un nuevo episodio que explica un nevo feature llamado Memoize, lo que hace este memoize es casi lo mismo que se vio en su primer episodio “Caching with instance variables”, denle una revisada al material de este señor porque vale la pena.
Por cierto, si quieren actualizar su version de rails deben saber que la version 1.3.1 de rubygems es necesaria, asi que pueden intentar:
$ sudo gem update --system
Pero en mi caso y algunos otros tuvimos algunos problemas, asi que esta otra opción funciona bien
$ sudo gem install rubygems-update
Esto instala la actualización pero hay que hacerla valida asi
$ sudo update_rubygems
Y ahora que ya tenemos el rubygems instalado pues podemos actualizar rails de cuaquiera de las siguientes tres formas
$ sudo gem update gems o
$ sudo gem update rails o
$ sudo gem install rails
Para cerrar con broche de oro, simplemente revisa que tu version sea la indicada
$ rails --version
y lo que te debe regresar este comando es Rails 2.2.2
ACTUALIZACIóN:
Algo que había olvidado antes en esta guía, es que para cambiar una aplicación Rails a otra versión Rails es necesario modificar un par de líneas del environment.rb:
# Specifies gem version of Rails to use when vendor/rails is not present
RAILS_GEM_VERSION = ‘2.2.2′ unless defined? RAILS_GEM_VERSION

Luego ejecutamos la tarea rake rails:update

Ahí lo tienen.
Comentarios, preguntas, dudas o insultos son bienvenidos.
Recommend Me

Installing Ruby on Rails in Ubuntu Hardy Heron (8.04 Lts)

1. First Install ruby and rails dependencies
$ sudo apt-get install ruby irb ri rdoc ruby1.8-dev libzlib-ruby libyaml-ruby libreadline-ruby libncurses-ruby libcurses-ruby libruby libruby-extras libfcgi-ruby1.8 build-essential libopenssl-ruby libdbm-ruby libdbi-ruby libdbd-sqlite3-ruby sqlite3 libsqlite3-dev libsqlite3-ruby libxml-ruby libxml2-dev
2. Download rubygems from ruby forge.
3. Extract the contents and change directory into the recently created rubygems directory.
4. Run setup
$ sudo ruby setup.rb
5. Make the link
$ sudo ln -s /usr/bin/gem1.8 /usr/bin/gem
6. Run update
$ sudo gem update --system
7. In case you get the

Uninitialized constant Gem::GemRunner

just follow the instructions in my post with that title.
8. Install Rails from gems
$ sudo gem install rails
$ sudo gem install sqlite3-ruby mongrel capistrano

9. If you want to use MySql
sudo apt-get install mysql-server mysql-client libdbd-mysql-ruby libmysqlclient15-dev

Read third party HTML using Ruby on Rails and Hpricot

A few weeks ago, mi Distributed Systems class profesor asked us to implement some sort of Web Service that gave Currency Rates information in XML format. This looked pretty easy, but all went wrong when he asked us to read the HTML from a bank’s web site and retrieve the information from there.
The idea then was to read that HTML code from a reliable site, transform it and make it available for us to download or use. Looking for a free web service that presented this information and using it wouldnt have been as easy as it was for me to use Hpricot. So here is the code I wrote, I just changed the url from where i fetched the information, because I don’t know if it is legal to do that :D.

First there is the model CurrencyService
currency_service.rb
require ‘open-uri’
require ‘hpricot’

class CurrencyService “”},
{:CUR_CODE => “USD”, :MEX_EQV => get_data(”#FIX_DATA”).gsub(/ /,”).chomp},
{:CURRENCY_EQV => “”},
{:CUR_CODE => “EUR”, :MEX_EQV => get_data(”#EURO_DATA”).gsub(/ /,”).chomp},
{:CURRENCY_EQV => “”},
{:CUR_CODE => “YEN”, :MEX_EQV => get_data(”#YEN_DATA”).gsub(/ /,”).chomp},
{:CURRENCY_EQV => “”},
{:CUR_CODE => “CAN”, :MEX_EQV => get_data(”#LIBRA_DATA”).gsub(/ /,”).chomp}
}.to_xml
end

end

And then the controller

curency_service_controller.rb
class CurrencyServiceController “text/xml”,
:filename => “currencies.xml” )
end

end

Enjoy

Leer HTML de un sitio externo con Ruby on Rails y Hpricot

Hace un par de semanas mi profesor de Sistemas Distribuidos en el ITESO nos pidió hacer una especie de Web Service que te entregara información del mercado cambiaro en formato XML. Esto sonaba bastante sencillo, sin embargo todo se complicó cuando nos pidio información real tomada de la página de un banco, debiamos leerla en HTML.
La idea entonces era leer el código HTML de una página web confiable que presentara esta información y nosotros convertirla en XML con el formato solicitado. Al principio si le batalle en buscar mejor un Web Service ya hecho y gratuito que presentara esta información, sólo encontre uno aqui, sin embargo no pude encontrar un API ni nada parecido que me facilitara el uso.
Para este momento ya tenia el tiempo encima así que como de costumbre acudí a la comunidad de RoR para ver que herramientas tenía a la mano para leer HTML. Me encontré con Hpricot que es un gem que me solucionó la vida. La solución final quedo muy simple.

Primero hize un modelo CurrencyService que se conecta con el sitio web del que obtuve la información, lo lee como un string y este lo convierte a un Hpricot, después usando la librería Hpricot busca por ID los datos que se necesitan, el controlador simplemente presenta la información en formato XML y listo. Aqui dejo el código, solo que no revelaré la fuente de información ya que no se si es legal.

currency_service.rb
require ‘open-uri’
require ‘hpricot’

class CurrencyService < ActiveRecord::Base
def get_data(id)
html = Hpricot(open("http://www.urlfalso.fake").read)
return (html/id).inner_html
end

def get_xml_content
@currencies = {
{:CURRENCY_EQV => ""},
{:CUR_CODE => "USD", :MEX_EQV => get_data("#FIX_DATO").gsub(/ /,'').chomp},
{:CURRENCY_EQV => ""},
{:CUR_CODE => "EUR", :MEX_EQV => get_data("#EURO_DATO").gsub(/ /,'').chomp},
{:CURRENCY_EQV => ""},
{:CUR_CODE => "YEN", :MEX_EQV => get_data("#YEN_DATO").gsub(/ /,'').chomp},
{:CURRENCY_EQV => ""},
{:CUR_CODE => "CAN", :MEX_EQV => get_data("#LIBRA_DATO").gsub(/ /,'').chomp}
}.to_xml

end

end

curency_service_controller.rb
class CurrencyServiceController < ApplicationController

def index
@currency_service = CurrencyService.new
send_data( @currency_service.get_xml_content, :type => "text/xml",
:filename => "currencies.xml" )
end

end

Asi de simple es…