-
Notifications
You must be signed in to change notification settings - Fork 9
Allowing admins to import data from Excel and CSV files
Para components allow you to import Excel or CSV files into your system.
The only thing that you need to write, is the logic to import a single row, the rest (the file input, the controller action, the file parsing and iteration) is handled by Para.
The following steps allow you to make a complete importer feature in a CRUD component. If you're in a Form
or custom component, you'll need an extra step to create the link to your importer, which is described at the bottom of this tutorial.
- Generate the importer structure
- Configure your component
- Write the importing logic
- Error handling
- Managing multiple importers for a given component
For the demonstration, we'll suppose that we want to allow importing a users XLS file in our system.
First, we generate de importer file structure with the provided generator :
rails generate para:importer users
This will generate a file at : app/importers/users_importer.rb
Let's say we have a :users
component, we configure our config/components.rb
file to handle importing files with our importer :
component :users, :crud, importers: ['UsersImporter']
We can now go to our users component, and an import file field will be present at the top of the table.
Note : our importer and component both have the
users
prefix in their name, but this is not mandatory since we can configure any importer in our component.
Now, we go to the app/importers/users_importer.rb
file, which contains an import_from_row
method that we must define.
When the importer is run, the file headers are stripped and each row is passed to that method.
Here's how you would import an excel file with 3 columns, email, first_name, last_name :
class UsersImporter < Para::Importer::Base
def import_from_row(row)
email, first_name, last_name = row
User.where(email: email).first_or_create! do |user|
user.first_name = first_name
user.last_name = last_name
end
end
end
When you create each row, you can use the bang version of ActiveRecord::Base saving methods (save!
, create!
, first_or_create!
) to let errors raise and the importer handle the rest.
The importer will be able to complete even when there are errors, and errors will be displayed in the flash message on page reloading.
You can add several importers to the same component. This will let you handle multiple data sources differently, without having to handle the different cases in a single importer.
Since the :importers
component option is an array, just add the other importers to that array, like :
component :users, :crud, importers: ['UsersImporter', 'GuestsImporter']
This will transform the import button to be a dropdown.
Each link in the dropdown will have the name of the importer.
You can edit this name with active model translations. Here, we would add the following keys :
en:
activemodel:
models:
users_importer: "Users"
guests_importer: "Guests list"
CRUD components automatically show importers for a given component available as a button or a dropdown in the main table view of the component. For other cases, where you want to create a link to access the import form, you'll need to add the link manually to your views.
The URL to access the desired import form can be accessed through the component#path
method, like the following :
component.path(namespace: :import, action: :new, importer: 'YourImporterClassName')
.
Since importers are run in background and to allow the UI to work as needed, you'll need to add some specific attributes to your link to allow Para's async job tracker interface to work : the [data-remote]
and [data-job-tracker-button]
attributes.
For a basic link with an upload icon and a button appearance, the could would look like :
= link_to @component.path(namespace: :import, action: :new, importer: 'UsersImporter'), class: 'btn btn-lg btn-primary', remote: true, data: { :'job-tracker-button' => true } do
= fa_icon 'upload'
Import data