From Project Setup to Service Execution β A Step-by-Step Guide Using Ruby 3.3+, Transaction, FileUtils and Clean Architecture
RCAD is a fiscal data initiative by Brazil's CONFAZ (National Council for Fiscal Policy), enabling structured communication across all 27 state tax departments. This project simulates a real-world use case, where you'll build a robust upload and parsing system using a clean, modular Rails 8 architecture.
Though the data used here is fictitious, the structure is suitable for production with minimal adjustments.
Create a Rails 8 app with:
- β Ruby 3.3+ support
- β
Batch processing with
activerecord-import
- β Transaction safety and error rollback
- β
Modular parsing using
.detalhe(row)
- β Directory structure for organized file management
- β API endpoint for triggering the service
- β Ready for logging, testing, and extension
- π Batch import with
batch_size: 10000
for performance - π Safe transactions using
ActiveRecord::Base.transaction
- π§± Clean separation of logic using methods like
cliente(row)
- π Files moved after processing with
FileUtils.mv
β If you get stuck, feel free to check the GitHub repo.
rails new rcad_app --api
cd rcad_app
In your Gemfile:
gem "activerecord-import"
gem "tty-logger"
gem "tty-spinner"
Then run:
bundle install
rails g model MeioDeCaptura tipo_tecn:integer term_prop:integer marca:string mestre:references
rails g model IpParceira cnpj:string nome:string nome_resp:string fone:string email:string mestre:references
rails g model Adquirencia cnpj_adqui:string mestre:references
rails g model UfDestinataria uf:string qtd:integer mestre:references
rails g model Autorizacao tp_autoriz:integer cnpj:string tp_transac:integer dt_ini_aut:date dt_fim_aut:date mestre:references
rails g model ContadorRegistro qtd_b:integer qtd_c:integer qtd_d:integer qtd_e:integer qtd_f:integer qtd_g:integer qtd_h:integer mestre:references
Adjust model attributes as needed based on the .detalhe(row) parsing logic.
In config/application.rb
:
module RcadApp
class Application < Rails::Application
config.load_defaults 8.0
config.rcad_path = {
original: Rails.root.join('rcad_files/original'),
processados: Rails.root.join('rcad_files/processados'),
erros: Rails.root.join('rcad_files/erros')
}
end
end
mkdir -p rcad_files/{original,processados,erros}
You can now place .TXT files in rcad_files/original.
File: app/services/cargas/rcad_carga.rb
π See full implementation above β includes collection setup, transaction handling, row dispatching, and directory movement.
Example for Cliente:
class Cliente < ApplicationRecord
belongs_to :mestre
def detalhe(row)
linha = row.split('|')
self.cnpj = linha[2]
self.cpf = linha[3]
self.dt_credenciamento = parse_data(linha[4])
end
private
def parse_data(str)
Date.strptime(str, '%Y%m%d') rescue nil
end
end
Repeat for other models based on their layout in the RCAD spec.
In config/initializers/inflections.rb:
ActiveSupport::Inflector.inflections(:en) do |inflect|
inflect.irregular 'adquirencia', 'adquirencias'
inflect.irregular 'uf_destinataria', 'uf_destinatarias'
inflect.irregular 'autorizacao', 'autorizacoes'
end
This ensures proper pluralization when generating models or controllers.
rails db:create db:migrate
Generate controller:
rails g controller api/v1/rcad --skip-template-engine --no-assets --api
Add action:
module Api
module V1
class RcadController < ApplicationController
def processar
result = Cargas::RcadCarga.new
render json: { message: 'RCAD file processed successfully' }, status: :ok
rescue => e
render json: { error: e.message }, status: :unprocessable_entity
end
end
end
end
Add route:
Rails.application.routes.draw do
namespace :api do
namespace :v1 do
post 'rcad/processar', to: 'rcad#processar'
end
end
end
Start the server:
rails s
Then run:
curl -X POST http://localhost:3000/api/v1/rcad/processar
You should receive:
{"message":"RCAD file processed successfully"}
rails console
Then
Cargas::RcadCarga.new
See detailed Suggestions for Improvement, based on a review and best practices analysis.
β Done!
You now have a production-ready Rails 8 app capable of parsing and storing fiscal data from RCAD-formatted files.