How to create download button for CSV and PDF using Ruby on Rails

Hey Guys !
Let's cut to the chase, hands on code !
  • First generate scaffold
  • rails g scaffold Note title
  • run db:migrate
  • rails db:migrate
  • now we are going to install the gem to generate PDF, we will use the gem 'prawn' and the 'prawn-table':
  • bundle add prawn prawn-table
  • now we're going to add the route and buttons for downloads nor csv and pdf format:
  • # add route in file config/routes.rb
    resources :notes
    root 'notes#index'
    post 'download/notes', to: 'notes#download'
    
    # add method downlod in controller app/controllers/notes_controller.rb
    def download
        respond_to do |format|
          format.csv { send_data Note.to_csv, filename: "notes-#{Date.today}.csv" }
          format.pdf { send_data Note.to_pdf, filename: "notes-#{Date.today}.pdf" }
        end
    end
    
    # adds concerns to the note model to export the data
    class Note < ApplicationRecord
      include ExportCsv
      include ExportPdf
    end
    
    # now let's create the modules in app/models/concerns
    # first export_csv.rb
    # frozen_string_literal: true
    
    # module ExportCSV
    module ExportCsv
      extend ActiveSupport::Concern
    
      # module ClassMethods
      module ClassMethods
        def to_csv
          require 'csv'
          options = { col_sep: ';', encoding: 'utf-8' }
          headers = %i[id title]
    
          CSV.generate(headers: true, **options) do |csv|
            csv << headers
    
            all.each do |note|
              csv << [note.id, note.title]
            end
          end
        end
      end
    end
    
    # second export_pdf.rb
    # frozen_string_literal: true
    
    # module ExportPdf
    module ExportPdf
      extend ActiveSupport::Concern
    
      # module ClassMethods
      module ClassMethods
        def to_pdf
          require 'prawn'
          require 'prawn/table'
    
          options = { position: :center, column_widths: [300, 300], width: 600 }
    
          header = %w[ID Title]
          data = all.map { |note| [note.id, note.title] }
          Prawn::Document.new do
            text 'All Notes', align: :center, size: 18, style: :bold
            table([header, *data], header: true, **options)
          end.render
        end
      end
    end
    
    # and finally add the links on the app/views/notes/index.html.erb page
    <%= button_to "Download CSV", download_notes_path(request.params.merge(format: :csv)), data: {turbo: :false} %>
    <%= button_to "Download PDF", download_notes_path(request.params.merge(format: :pdf)), data: {turbo: :false} %>
    And that's it, we're done!

    71

    This website collects cookies to deliver better user experience

    How to create download button for CSV and PDF using Ruby on Rails