Skip to content

This tutorial builds an index page listing employees with action links to view and upload CVs, photos, PAN cards, and certificates.

Notifications You must be signed in to change notification settings

giljr/How_To_Use_Active_Storage

Folders and files

NameName
Last commit message
Last commit date

Latest commit

ย 

History

4 Commits
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 

Repository files navigation

Active Storage Demo with Employee Info & Certificates

A simple Rails app demonstrating how to use Active Storage to upload and manage employee information, PAN card, and certificate attachments using nested forms, file system storage, and Bootstrap-styled views.


๐Ÿ”ง Setup

Requirements

  • Ruby: 3.2.3
  • Rails: 8.0.2

๐Ÿš€ Let's Get Started

If you get stuck, check out my tutorial for the full working version.

1. Create a New Rails App

rails new active_storage_demo
cd active_storage_demo
code .

2. Add Required Gems

In your Gemfile:

gem "toastr-rails"
gem "jquery-rails"
gem "rails-ujs"

Then install them:

bundle install

๐Ÿ”Œ Setup Active Storage

rails active_storage:install

Creates:

active_storage_blobs

active_storage_attachments

active_storage_variant_records

๐Ÿงฑ Models

1. Generate Models

rails g model employeeinfo firstname:string lastname:string rails g model employeecertificate employeeinfo:references

2. Setup Associations

app/models/employeecertificate.rb

class Employeecertificate < ApplicationRecord
  belongs_to :employeeinfo
  has_one_attached :certi
end

app/models/employeeinfo.rb

class Employeeinfo < ApplicationRecord
  has_many :employeecertificates, dependent: :destroy
  accepts_nested_attributes_for :employeecertificates, allow_destroy: true
  has_one_attached :pan_card
end

3. Migrate Database

rails db:migrate

๐Ÿ“ Active Storage Config

config/storage.yml

test:
  service: Disk
  root: <%= Rails.root.join("tmp/storage") %>

local:
  service: Disk
  root: <%= Rails.root.join("storage") %>

Uncomment and configure Amazon/GCS/Azure if needed for cloud deployments.

๐ŸŽฎ Controller

Generate controller:

rails g controller employeeinfodetails

app/controllers/employeeinfodetails_controller.rb

class EmployeeinfodetailsController < ApplicationController
  def index
    @employees = Employeeinfo.all
  end

  def new
    @employee = Employeeinfo.new
  end

  def create
    @employee = Employeeinfo.new(employee_params)
    if @employee.save
      folder_name = "#{@employee.id}_#{@employee.lastname}"
      folder_path = Rails.public_path.join('employee_files', folder_name)
      FileUtils.mkdir_p(folder_path)

      upload_file(params[:cv], folder_path, "#{folder_name}_cv")
      upload_file(params[:photo], folder_path, "#{folder_name}_my_pic")

      certificate_path = folder_path.join('certificates')
      FileUtils.mkdir_p(certificate_path)

      params[:employee][:employeecertificates_attributes].each_with_index do |certificate, index|
        upload_file(certificate[:certi], certificate_path, "certificate_#{index + 1}")
      end

      @employee.update(certificate_params)
      redirect_to employeeinfodetails_path
    end
  end

  def show
    @employee = Employeeinfo.find_by(id: params[:id])
    if @employee
      @folder_name = "#{@employee.id}_#{@employee.lastname}"
      folder_path = Rails.public_path.join('employee_files', @folder_name)
      file_list = Dir["#{folder_path}/*"]

      @cv_file_path = extract_file_path(file_list, 'cv')
      @my_pic_file_path = extract_file_path(file_list, 'my_pic')

      certi_path = folder_path.join('certificates')
      certi_files = Dir["#{certi_path}/*"]
      @certificates = certi_files.map { |c| c[/"employee_files.*$/] }
    end
  end

  def download_file
    send_file("#{Rails.root}/public/#{params[:download_path]}")
  end

  private

  def employee_params
    params.require(:employeeinfo).permit(:firstname, :lastname, :pan_card)
  end

  def certificate_params
    params.require(:employee).permit(employeecertificates_attributes: [:certi])
  end

  def upload_file(uploaded_file, folder_path, new_fname)
    ext = File.extname(uploaded_file.original_filename)
    new_file = "#{new_fname}#{ext}"
    File.open(File.join(folder_path, new_file), 'wb') { |f| f.write(uploaded_file.read) }
  end

  def extract_file_path(files, keyword)
    file = files.find { |f| f.include?(keyword) }
    "employee_files/#{@folder_name}/#{File.basename(file)}" if file
  end
end

๐Ÿ—บ Routes

config/routes.rb

resources :employeeinfodetails, only: [:index, :show, :create, :new]
root "employeeinfodetails#index"
get "employees/download_file" => "employeeinfodetails#download_file"

๐ŸŽจ Front-End Setup

app/views/layouts/application.html.erb

<!-- Bootstrap -->
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/css/bootstrap.min.css" rel="stylesheet">
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/js/bootstrap.bundle.min.js"></script>

<!-- Bootstrap Icons -->
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.11.3/font/bootstrap-icons.min.css">

<!-- jQuery -->
<script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>

<!-- Toastr CSS/JS -->
<link href="https://cdnjs.cloudflare.com/ajax/libs/toastr.js/latest/toastr.min.css" rel="stylesheet">
<script src="https://cdnjs.cloudflare.com/ajax/libs/toastr.js/latest/toastr.min.js"></script>
๐Ÿ’ก Alternative:

Use importmap (Rails 7+) via config/importmap.rb and app/javascript/application.js.

๐Ÿ’ป JavaScript

app/javascript/application.js

import "@hotwired/turbo-rails"
import "controllers"

$(document).on('turbo:load', function() {
  addCertificate();
  submitEmployeeForm();
});

function addCertificate() {
  $('.add-certicate').on('click', function(e) {
    if ($('form .certi-box').length < 10) {
      // Add more certificate fields...
    }
  });
}

๐Ÿ“‚ Folder Structure Example

public/employee_files/
  โ””โ”€โ”€ 1_Smith/
      โ”œโ”€โ”€ 1_Smith_cv.pdf
      โ”œโ”€โ”€ 1_Smith_my_pic.jpg
      โ””โ”€โ”€ certificates/
          โ”œโ”€โ”€ certificate_1.pdf
          โ””โ”€โ”€ certificate_2.pdf

โœ… Done!

You now have a working Rails app with Active Storage, file uploads, nested attributes, and Bootstrap UI!

Happy coding! ๐ŸŽ‰

Authors

Documentation

Active Storage Overview

License

MIT