Как импортировать данные из файла Excel в Rails
Импорт из Excel в Rails с помощью roo gem.
Недавно мне пришлось это сделать по работе и я был удивлен тем, насколько это просто, поэтому и решил написать об этом статью.
Настройка демо проекта
Чтобы сделать все максимально понятным и простым, я просто импортирую пользователей.
Таблица пользователей выглядит следующим образом:
create_table "users", force: :cascade do |t| t.string "firstname" t.string "lastname", null: false t.string "username", null: false t.string "email", null: false t.integer "age" t.datetime "created_at", precision: 6, null: false t.datetime "updated_at", precision: 6, null: false t.index ["username"], name: "index_users_on_username", unique: true end
users table in schema.rb
Импорт данных из файла Excel
Создайте файл
Очевидно, что для работы вам нужен файл Excel. Если у вас нет Microsoft Office 365, то просто используйте Google Sheets и загрузите его в виде файла Excel (именно так я это сделал).
Каждый столбец соответствует строке в вашей базе данных. Тот, который я буду использовать, выглядит следующим образом:

Устанавливаем gem
Добавьте gem в свой Gemfile и запустите bundle install.
gem "roo", "~> 2.9.0"
(Или любую другую текущую версию)
Создайте метод импорта
Готовый метод выглядит следующим образом и находится внутри UsersController.rb :
def import_data(path)
xlsx = Roo::Spreadsheet.open(path[:xlsx_path])
xlsx.sheet(0).each_with_index(firstname: 'First name', lastname: 'Surname',
username: 'Username', email: 'E-Mail', age: 'Age') do |row, row_index|
next if row_index == 0 || User.find_by(username: row[:username]).present?
User.create(
firstname: row[:firstname],
lastname: row[:lastname],
username: row[:username],
email: row[:email],
age: row[:age]
)
end
end
Давайте пройдемся по нему шаг за шагом:
Первая строка открывает файл и делает его доступным для нас. Путь xlsx_path будет объяснен позже в разделе.
xlsx = Roo::Spreadsheet.open(path[:xlsx_path])
Затем он выбирает первый лист и перебирает строки. Круглые скобки не обязательны, я просто думаю, что так он будет более читабельным.
Без скобок row был бы простым массивом со значениями строки. Доступ к записям можно было бы получить, написав row[x]. Это быстро бы запутало, потому что я не думаю, что row[8] имеет большой смысл.
Со скобками создается хэш, что, на мой взгляд, делает его более читабельным.
xlsx.sheet(0).each_with_index(firstname: 'First name', lastname: 'Surname', username: 'Username', email: 'E-Mail', age: 'Age') do |row, row_index| stuff.. end
Далее мы пропускаем первую строку, поскольку это только заголовки, а также переходим к следующей строке, если пользователь с таким именем уже существует.
next if row_index == 0 || User.find_by(username: row[:username]).present?
Наконец, мы создаем нового пользователя с помощью полученной информации.
User.create( firstname: row[:firstname], lastname: row[:lastname], username: row[:username], email: row[:email], age: row[:age] )
Создайте задачу rake для запуска метода
Запустите генератор для создания задачи rake:
rails g task import user_data
В качестве аргумента вы передадите путь к файлу .xlsx. Внутри задачи мы вызываем метод import_data и передаем ему путь:
namespace :import do
desc 'Uploads data from xlsx'
task :user_data, [:xlsx_path] => :environment do |_t, args|
users_controller = UsersController.new
users_controller.import_data(xlsx_path: args[:xlsx_path])
end
end
Команда для запуска задачи rake выглядит следующим образом:
rake import:user_data['path']
И все! Импорт из Excel в Rails намного проще, чем я думал вначале.














