I am working on a project where I have a CSV uploader class method import_listings(file)
which is being called by Sidekiq perform method.
class CsvWorker
include Sidekiq::Worker
sidekiq_options retry: false
def perform(file)
#call import listings class method on the file.
imported = Listing.import_listings(file)
# return true
end
end
I am calling the perform_async in a controller action index as shown:
def import
@imported = CsvWorker.perform_async(params[:file].path)
end
Everything works great!
I want to move this method on the backend, in the active admin dashboard page. As shown in the figure below. There would be columns for different CSV uploads each with a file upload form :
A member action won't be best suited for this task because there is no particular resource. It's a dashboard page.
The code for the dashboard is as below:
ActiveAdmin.register_page "Dashboard" do
menu priority: 1, label: proc{ I18n.t("active_admin.dashboard") }
content title: proc{ I18n.t("active_admin.dashboard") } do
div class: "blank_slate_container", id: "dashboard_default_message" do
span class: "blank_slate" do
span "Welcome To Want A Car Buy A Car Backend!"
small "Use options below for CSV below:"
end
end
end # content
end
The problem is if I try to add a form action in the column like below, it gives me an error saying I can't add inside the column:
columns do
column do
panel "CSV Uploads for Dealers" do
ul do
form_tag import_listings_path, multipart: true do
file_field_tag :file
submit_tag "Import Csv"
end
end
end
end
My question is: how can I add a file upload form in these columns, which will call the sidekiq method and pass file params to it? Where to define the method in the dashboard page? There is no controller on the page right? I don't want to add it to the admin resource files. I want it on the dashboard page.
In ActiveAdmin
, when we want to render some data on a page that is not tied to any resource, Custom Pages give you that option. Dashboard
is such an example which we define as: ActiveAdmin.register_page 'Dashboard'
.
A custom page gives you a bare-metal controller and routes as you need. It also enables you to render any partials and page actions too. These page actions will have corresponding named routes too to be accessible with route helpers. You are free to invoke any outside model methods from those actions to accomplish any task.
Knowing all these, let's define a page action which will receive the uploaded file, process it and then redirect to the dashboard page.
# app/admin/dashboard.rb
page_action :import_listings, method: :post do
# set a breakpoint here to check if you receive the file inside params properly
CsvWorker.perform_async(params[:file].path)
# do anything else you need and redirect as the last step
redirect_to admin_dashboard_path
end
At this point, :import_listings
action will have a named route as admin_dashboard_import_listings
.
Now we need to refer to this action upon form submission. Let's put the form block inside a partial:
<!-- app/views/admin/dashboard/_import_listings.html.erb -->
<%= form_tag admin_dashboard_import_listings_path, multipart: true do %>
<%= file_field_tag 'file', accept: 'text/csv' %>
<%= submit_tag 'Import Csv' %>
<% end %>
Finally render this partial inside the content block:
# app/admin/dashboard.rb
content do
...
columns do
column do
panel 'CSV Uploads for Dealers' do
ul do
render 'admin/dashboard/import_listings'
end
end
end
end
...
end
Now you will be able to render that form in the dashboard, upload files, submit, handle the uploads in background jobs and finally redirect to the dashboard or anywhere you want.
Enjoy!