Rails Active Storage 2026: Upload File, Integrasi S3, dan Pertanyaan Interview

Panduan lengkap Rails Active Storage untuk upload file, integrasi Amazon S3, dan persiapan pertanyaan interview Ruby on Rails.

Rails Active Storage 2026: Upload File, Integrasi S3, dan Pertanyaan Interview

Active Storage merupakan fitur bawaan Ruby on Rails yang menyederhanakan proses upload file dan manajemen attachment. Dengan dukungan cloud storage seperti Amazon S3, Google Cloud Storage, dan Microsoft Azure, Active Storage memberikan solusi lengkap untuk kebutuhan file handling dalam aplikasi web modern.

Dalam panduan ini, pembaca akan mempelajari cara mengimplementasikan upload file dengan Active Storage, mengkonfigurasi integrasi S3, serta mempersiapkan diri untuk pertanyaan interview terkait file handling di Ruby on Rails.

Active Storage telah menjadi standar untuk file handling di Rails sejak versi 5.2. Memahami fitur ini sangat penting untuk setiap developer Rails yang ingin membangun aplikasi production-ready.

Memahami Arsitektur Active Storage

Active Storage menggunakan dua tabel database untuk mengelola attachment: active_storage_blobs dan active_storage_attachments. Tabel blob menyimpan metadata file seperti nama, content type, dan checksum, sedangkan tabel attachment menghubungkan blob dengan model ActiveRecord.

Arsitektur ini memungkinkan satu file di-attach ke multiple record dan mendukung berbagai storage backend tanpa mengubah kode aplikasi.

bash
# Generate Active Storage tables
rails active_storage:install
rails db:migrate

Perintah di atas membuat migration untuk kedua tabel yang diperlukan Active Storage.

Konfigurasi Model untuk File Upload

Menambahkan attachment ke model Rails sangat sederhana dengan macro has_one_attached dan has_many_attached.

ruby
# app/models/user.rb
class User < ApplicationRecord
  has_one_attached :avatar
  has_many_attached :documents

  validates :avatar, content_type: ['image/png', 'image/jpeg'],
                     size: { less_than: 5.megabytes }
end

Dengan deklarasi ini, model User dapat menerima satu avatar dan multiple documents.

Implementasi Controller untuk Upload

Controller menangani proses upload dengan memanfaatkan strong parameters untuk menerima file dari form.

ruby
# app/controllers/users_controller.rb
class UsersController < ApplicationController
  def create
    @user = User.new(user_params)
    if @user.save
      redirect_to @user, notice: 'User created successfully'
    else
      render :new, status: :unprocessable_entity
    end
  end

  def update
    @user = User.find(params[:id])
    if @user.update(user_params)
      redirect_to @user, notice: 'User updated successfully'
    else
      render :edit, status: :unprocessable_entity
    end
  end

  private

  def user_params
    params.require(:user).permit(:name, :email, :avatar, documents: [])
  end
end

Membuat Form Upload dengan Rails 8

Rails 8 menyediakan form helper yang terintegrasi dengan Active Storage.

erb
<%# app/views/users/_form.html.erb %>
<%= form_with model: @user do |form| %>
  <div class="field">
    <%= form.label :avatar %>
    <%= form.file_field :avatar, accept: 'image/png,image/jpeg',
        direct_upload: true %>
  </div>

  <div class="field">
    <%= form.label :documents %>
    <%= form.file_field :documents, multiple: true,
        direct_upload: true %>
  </div>

  <%= form.submit %>
<% end %>

Atribut direct_upload: true mengaktifkan upload langsung ke storage service tanpa melalui server Rails.

Konfigurasi Amazon S3 untuk Production

Untuk production environment, S3 menjadi pilihan populer karena skalabilitas dan reliabilitasnya.

yaml
# config/storage.yml
amazon:
  service: S3
  access_key_id: <%= Rails.application.credentials.dig(:aws, :access_key_id) %>
  secret_access_key: <%= Rails.application.credentials.dig(:aws, :secret_access_key) %>
  region: ap-southeast-1
  bucket: myapp-production-uploads
  public: false

Konfigurasi di atas menggunakan Rails credentials untuk menyimpan API keys dengan aman.

ruby
# config/environments/production.rb
Rails.application.configure do
  config.active_storage.service = :amazon
end

Menambahkan Gem yang Diperlukan

S3 storage memerlukan gem AWS SDK.

ruby
# Gemfile
gem 'aws-sdk-s3', require: false
gem 'image_processing', '~> 1.2'

Gem image_processing diperlukan untuk fitur variant seperti resize dan crop gambar.

Image Variants dan Transformasi

Active Storage menyediakan fitur variant untuk mengubah ukuran dan format gambar secara on-demand.

ruby
# Generating image variants
@user.avatar.variant(resize_to_limit: [200, 200]).processed

# Pre-defined variants in model
class User < ApplicationRecord
  has_one_attached :avatar do |attachable|
    attachable.variant :thumb, resize_to_limit: [100, 100]
    attachable.variant :medium, resize_to_limit: [300, 300]
    attachable.variant :large, resize_to_limit: [800, 800]
  end
end

Variant dibuat secara lazy dan di-cache untuk request selanjutnya.

Menampilkan Attachment di View

Rails menyediakan helper untuk menampilkan gambar dan file attachment.

erb
<%# Display avatar with variant %>
<%= image_tag @user.avatar.variant(:thumb) if @user.avatar.attached? %>

<%# Link to download document %>
<% @user.documents.each do |document| %>
  <%= link_to document.filename, rails_blob_path(document, disposition: 'attachment') %>
<% end %>

<%# Display image with fallback %>
<%= image_tag(@user.avatar.attached? ? @user.avatar.variant(:medium) : 'default-avatar.png') %>

Direct Upload dengan JavaScript

Direct upload memungkinkan file dikirim langsung ke storage service, mengurangi beban server Rails.

app/javascript/direct_uploads.jsjavascript
import { DirectUpload } from "@rails/activestorage"

class DirectUploadController {
  constructor(file, url) {
    this.directUpload = new DirectUpload(file, url, this)
  }

  upload() {
    return new Promise((resolve, reject) => {
      this.directUpload.create((error, blob) => {
        if (error) {
          reject(error)
        } else {
          resolve(blob.signed_id)
        }
      })
    })
  }

  directUploadWillStoreFileWithXHR(request) {
    request.upload.addEventListener("progress", event => {
      const progress = (event.loaded / event.total) * 100
      console.log(`Upload progress: ${progress.toFixed(2)}%`)
    })
  }
}

export { DirectUploadController }

Validasi File dengan Custom Validator

Validasi yang lebih kompleks dapat diimplementasikan dengan custom validator.

ruby
# app/validators/file_size_validator.rb
class FileSizeValidator < ActiveModel::EachValidator
  def validate_each(record, attribute, value)
    return unless value.attached?

    if value.is_a?(ActiveStorage::Attached::Many)
      value.each do |attachment|
        validate_attachment(record, attribute, attachment)
      end
    else
      validate_attachment(record, attribute, value)
    end
  end

  private

  def validate_attachment(record, attribute, attachment)
    max_size = options[:max] || 10.megabytes
    if attachment.blob.byte_size > max_size
      record.errors.add(attribute, "is too large (max: #{max_size / 1.megabyte}MB)")
    end
  end
end

Background Processing dengan Active Job

Proses berat seperti video transcoding sebaiknya dilakukan di background.

ruby
# app/jobs/process_video_job.rb
class ProcessVideoJob < ApplicationJob
  queue_as :default

  def perform(video_id)
    video = Video.find(video_id)
    return unless video.file.attached?

    video.file.analyze
    # Additional processing logic
  end
end

# Trigger job after upload
class Video < ApplicationRecord
  has_one_attached :file

  after_commit :process_video, on: [:create, :update]

  private

  def process_video
    ProcessVideoJob.perform_later(id) if file.attached?
  end
end

Testing Active Storage

Rails menyediakan fixtures dan helpers untuk testing Active Storage.

ruby
# test/models/user_test.rb
require 'test_helper'

class UserTest < ActiveSupport::TestCase
  test 'should attach avatar' do
    user = users(:john)
    user.avatar.attach(
      io: File.open(Rails.root.join('test/fixtures/files/avatar.png')),
      filename: 'avatar.png',
      content_type: 'image/png'
    )

    assert user.avatar.attached?
    assert_equal 'avatar.png', user.avatar.filename.to_s
  end

  test 'should validate avatar content type' do
    user = users(:john)
    user.avatar.attach(
      io: File.open(Rails.root.join('test/fixtures/files/document.pdf')),
      filename: 'document.pdf',
      content_type: 'application/pdf'
    )

    assert_not user.valid?
    assert_includes user.errors[:avatar], 'has an invalid content type'
  end
end

Pertanyaan Interview Active Storage

Berikut pertanyaan umum yang sering muncul dalam interview Ruby on Rails:

Apa perbedaan antara has_one_attached dan has_many_attached?

has_one_attached digunakan untuk single file attachment seperti avatar, sedangkan has_many_attached untuk multiple files seperti gallery atau documents.

Bagaimana Active Storage menyimpan file secara default?

Secara default, Active Storage menggunakan disk service yang menyimpan file di folder storage/ dalam aplikasi. Untuk production, sebaiknya menggunakan cloud storage seperti S3.

Apa itu Direct Upload dan kapan menggunakannya?

Direct Upload memungkinkan browser mengupload file langsung ke storage service tanpa melalui server Rails. Ini berguna untuk file besar karena mengurangi memory usage di server.

Bagaimana cara mengoptimalkan gambar dengan Active Storage?

Gunakan variants untuk membuat versi gambar dengan ukuran berbeda. Variants dibuat secara lazy dan di-cache, sehingga tidak membebani server.

Bagaimana menghapus attachment yang tidak terpakai?

Gunakan task rails active_storage:purge:unattached untuk membersihkan blob yang tidak terhubung ke record manapun.

ruby
# Manual purge
ActiveStorage::Blob.unattached.where('created_at < ?', 1.day.ago).find_each(&:purge_later)

Siap menguasai wawancara Ruby on Rails Anda?

Berlatih dengan simulator interaktif, flashcards, dan tes teknis kami.

Kesimpulan

Active Storage menyediakan solusi komprehensif untuk file handling di Ruby on Rails. Dengan integrasi cloud storage seperti S3, fitur direct upload, dan image variants, developer dapat membangun sistem upload file yang scalable dan production-ready.

Memahami konsep dasar seperti blob, attachment, dan variants sangat penting untuk interview dan development sehari-hari. Praktik terbaik seperti validasi file, background processing, dan proper testing akan memastikan implementasi yang robust dan maintainable.

Tantangan harian

Bisakah kamu menemukan bug di Ruby on Rails?

Satu potongan kode nyata, satu bug tersembunyi, satu percobaan per hari. Tanpa akun untuk mencoba.

Anthony Fillion-Maillet

Ditulis oleh

Anthony Fillion-Maillet

Pendiri SharpSkill

Developer fullstack selama lebih dari 10 tahun. Ia menjalankan SharpSkill dan bertanggung jawab atas semua yang diterbitkan di sini.

Diperbarui 9 September 2026

Bagikan

Artikel terkait