Как импортировать данные из файла 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 намного проще, чем я думал вначале.