Мне для парсинга всегда хватало CSV из стандартной библиотеки ruby.
Я в подобной ситуации делал так:
Закачивал все csv-файлы в память, готовил индексы для связывания (в Hash) и потом с помощью методов create, build и save создавал объекты, связывая их.
Пример:
transaction do
albums = {}
album_csv.each do |line|
raise "errrrr" if albums.has_key? line.title
albums[line.title] = Album.create!(title: line.title)
end
artist_csv.each do |line|
artist = Artist.new(title: line.title)
artist.album = albums[line.album] or fail "no album: #{line.album}"
artist.save!
end
end
Если объем данных велик, то делаем все то же самое но закачиваем данные не в память а во временные таблицы в БД.