CSV

Rake task personalizado

Um dia precisei criar uma rake task para automatizar a importação de arquivos CSV em uma aplicação em RubyOnRails (2.3.8), então resolvi criar este post para ajudar a pessoas com o mesmo objetivo e que procuram criar rake tasks personalizadas.

A estrutura apresentada no código abaixo apresenta um exemplo de importação de um arquivo CSV de funcionários, que contém 3 campos:

  • nome – string
  • salário – float
  • cpf – string

Antes de continuar, explicarei rapidamente sobre os arquivos CSV. Arquivos CSV (comma-separated values) são arquivos de dados que guardam valores separados por vírgula. Assim a linha abaixo é um exemplo válido de uma linha do arquivo de funcionários.

"Fulano de tal",123.45,"987.654.321-00"

Pronto, agora você já sabe o que é um arquivo CSV e qual a estrutura do arquivo que será importado pela nossa rake task personalizada. Só lembrando que o script foi feito para rodar na versão 2.3.8 do Rails, mas não está limitado a ele, você pode usar em versões mais atuais, com as devidas adaptações, caso necessite.

# DATA: 10/06/2011
# PROGRAMADOR: Valberto Carneiro
# OBJETIVO: Criar um script para atualizacao dos salarios dos funcionarios e
#           criacao de novos salarios, caso a matricula do funcionario ainda
#           nao exista na base de dados.
# CONSIDERAÇÕES:
#   1. Aplicação em Rails (>= 2.3.8)
#   2. Conexão com banco de dados configurada
#   3. Tabela "funcionarios" criada e populada
#   4. Campos da tabela: id:integer, nome:string, salario:float, cpf:string

# app/models/funcionario.rb

class Funcionario < ActiveRecord::Base
# os metodos de acesso sao criados automaticamente pelo ActiveRecord
end

# lib/tasks/minhas_tarefas.rake

require 'csv'

namespace :tarefas do

  desc "Importa arquivo CSV, Parametro: PATH=/caminho/completo/para/o/arquivo.csv"

  task :importar_funcionarios => :environment do
    csv_file = ENV["PATH"]

    puts "Verificando a existência do arquivo..."

    unless File::exists?(csv_file)
      puts "Arquivo nao encontrado, verifique se esta correto e tente novamente."
      return
    end

    puts "Arquivo encontrado!"
    puts "Executando importacao, aguarde..."

    CSV.open("#{csv_file}","r") do |linha|
      nome    = linha[0]
      salario = linha[1]
      cpf     = linha[2]

      funcionario =  Funcionario.find_by_cpf(cpf)

      if funcionario
        funcionario.salario = salario
      else
        funcionario = Pessoa.new(:nome => nome, :salario => salario)
        funcionario.save
      end
    end
    puts "Importacao concluida com sucesso!"
  end
end