Blog

Programar tareas automáticas en Rails Blog

Programar tareas automáticas en Rails
Tags: rails ruby

La semana pasada mostré como consultar los APIs de las redes sociales más populares para sacar el conteo de likes y shares de una URL. El día de hoy quiero explicar como hice para hacer estas consultas de manera automática cada hora.

Para correr este sitio utilizo Ruby on Rails, así que lo único que hice fue buscar una gema que me permitiera agregar tareas al CRON JOB del servidor donde tengo corriendo esta aplicación. La gema más popular que encontré y que es muy sencillo usarla se llama whenever.

Para instalarla solamente es necesario agregarla al Gemfile.

gem 'whenever', :require => false

Y descargarla con el bundler.

$ bundler install

Ahora para consultar los servicios realice una tarea en Rake de la siguiente manera.

# encoding: UTF-8 
require 'net/http'
include Rails.application.routes.url_helpers

namespace :articles do
  desc "Update articles popularity"
  task :popularity => :environment do
    puts "Starting at: #{Time.now}"
    
    url = "https://quizzpot.com/some/blog-post"

    #facebook like counts
    uri = URI('http://graph.facebook.com')
    params = {id: url}
    uri.query = URI.encode_www_form(params)

    response = Net::HTTP.get_response(uri)
    if response.is_a?(Net::HTTPSuccess)
      record = ActiveSupport::JSON.decode(response.body)

      facebook = record['shares'] #<---- facebook shares
    else
      puts "ERROR Getting facebook counts for url: #{url}"
    end


    #twitter link counts
    uri = URI('http://cdn.api.twitter.com/1/urls/count.json')
    params = {url: url}
    uri.query = URI.encode_www_form(params)

    response = Net::HTTP.get_response(uri)
    if response.is_a?(Net::HTTPSuccess)
      record = ActiveSupport::JSON.decode(response.body)
      
      twitter = record['count'] #<---- twitter shares
    else
      puts "ERROR Getting twitter counts for url: #{url}"
    end

    
    #youtube video
    id = 'abcd123' #<--- youtube ID video    
    uri = URI("http://gdata.youtube.com/feeds/api/videos/#{id}")
    params = {v:"2",alt:"jsonc"}
    uri.query = URI.encode_www_form(params)
            
    response = Net::HTTP.get_response(uri)
    if response.is_a?(Net::HTTPSuccess)
      record = ActiveSupport::JSON.decode(response.body)
      
      youtube = record['data']['likeCount'] #<---- youtube likes
    else
      puts "ERROR Getting youtube counts for url: #{url}"
    end

    puts "Ending at: #{Time.now}"
  end
end

Prácticamente solo se están haciendo los request a los APIs que compartí anteriormente, luego saco los conteos de cada respuesta, claro está que mi script final consulto la base de datos para formar ls URLs dinámicamente, además de que guardo los conteos al final.

Ahora lo último que nos falta es ejecutar esa tarea cada determinado tiempo, para es que usamos la gema que instalamos previamente.

Creamos un archivo en config/shcedules.rb y le agregamos el siguiente código.

set :output, "log/cron.log"  #Step 1
#
# every 2.hours do
#   command "/usr/bin/some_great_command"
#   runner "MyModel.some_method"
#   rake "some:great:rake:task"
# end
#
# every 4.days do
#   runner "AnotherModel.prune_old_records"
# end

# Learn more: http://github.com/javan/whenever

every 1.day, :at => '07:00 am' do   #Step 2
  rake "articles:popularity"        #Step 3
end
  1. En el paso uno se especificamos el archivo donde guardaremos los logs, aquí decidí meterlo al folder log que ya viene con rails.
  2. El paso dos es el que hace la magia, aquí le estoy indicando que se ejecute una sola vez diariamente a las 7 de la mañana.
  3. En el paso tres ejecutamos la tarea de rake

Una vez que tenemos la tarea lista, debemos ejecutar el siguiente comando en la terminal.

$ whenever --update-crontab config/schedule.rb 

Con eso automáticamente se agregará la tarea al Crontab. Uno de los inconvenientes que tuve en producción (Un sistema Linux), es que no me agregó la tarea de manera automática, por el contrario el comando anterior me puso en consola la instrucción que tenía que agregar al archivo de configuración del Cron.

Para ver las tareas que están actualmente programadas lo puedes hacer con:

$ crontab -l

Si quieres borrar las tareas programadas.

$ crontab -r

Ahora ya tendrás listo tus tareas, estas se ejecutarán cuando tu le indiques de manera automática, en mi caso consultan los APIs de Twitter, Facebook y Youtube, actualizando los contadores en la base de datos.

Happy Coding! 

Se el primero en comentar!

Instructor del curso

Crysfel3

Autor: Crysfel Villa

Soy un geek que disfruta crear y compartir cosas en internet! Sígueme en twitter @crysfel