Back to home

Uploading Files In ActiveAdmin main image

Uploading Files In ActiveAdmin

This post will demonstrate how to upload files to ActiveAdmin.

Source code can be found here

Prerequisites

  1. It is expected that you follow on from a previous setup like the one explored in my previous blog post "ActiveAdmin With Ruby On Rails 7".

Getting started

It is expected that you follow the "Getting Started" section from my previous post "ActiveAdmin With Ruby On Rails 7" (but for a project named demo-upload-csv-to-active-admin).

Once you are at the point of seeing the /admin route from that post, come back here to finish the rest.

The last things that we want to do:

  1. Create a Template model (that we will populate in the database from a CSV file).
  2. Create a page for our CSV upload.
  3. Create a file for our CSV helper file.
  4. Create a CSV file for our test upload.

# Create our "Template" model $ bin/rails g model Template name:string description:string author:string # Create a page for our CSV upload $ touch app/admin/templates.rb # Create a service folder for the CSV converter $ mkdir app/services $ touch app/services/csv_helper.rb test.csv # Migrate changes for our template $ bin/rails db:migrate

At this stage, our project is now ready to start populating.

Updating our Template model

We will add some simple validations for our file app/models/template.rb here:

class Template < ApplicationRecord validates :name, presence: true validates :description, presence: true validates :author, presence: true end

Setting our CSV data

Our CSV data will map to our name, description and author columns respectively.

"POST A","DESCRIPTION A","AUTHOR A" "POST B","DESCRIPTION B","AUTHOR B" "POST C","DESCRIPTION C","AUTHOR C" "POST D","DESCRIPTION D","AUTHOR D" "POST E","DESCRIPTION E","AUTHOR E"

The idea is that each row will end up populating the data.

Writing out our admin template page

In app/admin/templates.rb, we will register a page "Template":

ActiveAdmin.register_page 'Template' do action_item only: :index do link_to 'Upload CSV', action: 'upload_csv' end page_action :upload_csv do render 'admin/csv/upload_csv' end page_action :import_csv, method: :post do templates = CsvHelper.convert_to_templates(params[:dump][:file]) Template.transaction do templates.each(&:save!) end redirect_to({ action: :index }, notice: 'CSV imported successfully!') rescue StandardError redirect_to({ action: :index }, flash: { error: 'CSV imported failed! Check the template is correct or contact a developer.' }) end end

There are a few things that we are doing here:

  1. Creating a page at the route /admin/template.
  2. Adding a link to the page at the top of the page for uploading a CSV that will redirect to admin/template/upload_csv.
  3. The route admin/template/upload_csv will render the app/views/admin/csv/upload_csv.html.erb view (that we will create next).
  4. The page_action method will be called when the user clicks on the link to upload a CSV.

The last action is most important. It will attempt to convert our CSV file to Template instances and then a transaction will attempt to upload them to the database (which we will also create soon).

If successful, the user will be redirected back to /admin/template with a success banner message displayed.

If the user is unsuccessful, the user will be redirected back to /admin/template with a failure banner message.

Next, let's tackle the view.

Creating our upload CSV view

Create the file app/views/admin/csv/upload_csv.html.erb and add the following:

<%= form_for :dump, :url=>{:action=>"import_csv"}, :html => { :multipart => true } do |f| %> <table> <tr> <td> <label for="dump_file"> Select a CSV File : </label> </td> <td><%= f.file_field :file %></td> </tr> <tr> <td><%= submit_tag 'Submit' %></td> </tr> </table> <% end %>

The above code will create a form that allows for a file, then on submission uploads that to the /admin/template/import_csv route that we have our handler for.

Finally, we need to add in the CsvHelper class.

Adding the CsvHelper class

Under app/services/csv_helper.rb, add the following:

class CsvHelper class << self def convert_to_templates(csv_data) templates = [] csv_file = csv_data.read CSV.parse(csv_file) do |row| name, description, author = row templates << Template.new(name: name, description: description, author: author) end templates end end end

Here we are adding a class method to the CsvHelper class. This method takes CSV data from the upload, converts each row to a Template instance, pushes it to an array of templates and finally returns it.

The returned templates will start a transaction for them to be inserted (as you can see in the previous code for the form submission handler).

Testing the CSV upload

At this point, we can get to our admin panel and test things out.

Run bin/rails s to start the server, head to /admin and login with the admin@example.com and password details.

Once logged in, you can head to /admin/template and click on the Upload CSV link.

Template page

Template page

The following page will display the form for your CSV file upload.

Template form for the file upload

Template form for the file upload

Once you select the test.csv file that we created, you will be redirected to the /admin/template/import_csv route with a success message (unless there is an issue).

Success

Success

If you have an issue, you will see the error message:

Error

Error

Summary

Today's post demonstrated how to upload a file to ActiveAdmin and process that upload.

Resources and further reading

Photo credit: bernardhermant

Personal image

Dennis O'Keeffe

@dennisokeeffe92
  • Melbourne, Australia

Hi, I am a professional Software Engineer. Formerly of Culture Amp, UsabilityHub, Present Company and NightGuru.
I am currently working on workingoutloud.dev, Den Dribbles and LandPad .

1,200+ PEOPLE ALREADY JOINED ❤️️

Get fresh posts + news direct to your inbox.

No spam. We only send you relevant content.