Tutorial Lengkap Membuat Web E-Commerce dengan Ruby dan Oracle Database

Advertisement

Sebelum kita mulai instal-instal dan ngetik kode, mari kita resapi dulu wejangan dari dua dimensi yang beda, biar batin dan logika kita sinkron.

Pertama, dari kitab kuning legendaris Ta'lim Muta'allim karya Syekh Az-Zarnuji. Di situ tertulis kaidah emas:

"Tsumma laa budda minal jiddi wal muwaadzobati"

Artinya kurang lebih, dalam menuntut ilmu itu hukumnya fardhu (wajib) buat bersungguh-sungguh dan tekun berkelanjutan (konsisten). Belajar Ruby digabung Oracle ini tantangannya lumayan, Cing. Kalo kagak tekun, bisa gampang putus asa di tengah jalan pas nemu error.

Kedua, dari buku babonnya anak Ruby, Practical Object-Oriented Design in Ruby karya Mpok Sandi Metz:

"Design is more the art of preserving changeability than it is the act of achieving perfection."

Maksudnya, nulis kode program itu seninya ada di gimana caranya kodingan kita gampang diubah-ubah di masa depan, bukan sekadar ngejar kesempurnaan di awal doang.

Tutorial Lengkap Membuat Web E-Commerce dengan Ruby dan Oracle Database

Tutorial Lengkap Membuat Web E-Commerce dengan Ruby dan Oracle Database

Kalo biasa ngulik XML sama HTML di Blogger demi dapet skor mobile cepek di PageSpeed, ketelitian ngerancang struktur kayak gitu bakal kepake banget di mari. Backend pake Oracle ini ibarat fondasi daleman yang kuat, biar frontend-nya bisa sedap dipandang—sama kayak pas ngerancang thumbnail video gaming, visualnya harus narik, tapi metadata di belakangnya juga kudu rapi biar dapet engagement maksimal.

Yuk, tarik napas panjang, kita mulai babad alas!

Buka Gerbang "Sultan" (Setup Ruby & Oracle)

Kenapa ane sebut gerbang Sultan? Karena Oracle ini bukan database ecek-ecek. Ini database kelas kakap (Enterpise) yang biasa dipake bank sama perusahaan gede. Nah, Ruby itu bahasa pemrograman yang elegan dan sat-set. Nggabungin keduanya butuh jembatan khusus.

Di penjelasan ini, target kita belum bikin aplikasi jualan, tapi masang fondasi dan mastiin Ruby bisa "ngobrol" nyambung sama Oracle.

1. Siapin Alat Tempur (Prerequisites)
Pastiin di laptop atau PC ente udah terpasang tiga barang ini:

- Ruby: Kalo pake Windows, sedot RubyInstaller (pilih yang ada Devkit-nya biar gampang). Kalo Mac/Linux bisa pake RVM atau rbenv.
- Oracle Database: Kalo buat belajar, download aja Oracle Database Express Edition (XE). Itu versi gratisannya.
- Oracle Instant Client: Ini penting banget! Ini driver atau jembatannya. Kudu di-download dari situs Oracle dan diatur Environment Variables (PATH) di sistem operasi ente.
2. Pasang Kabel Jembatan (Gem ruby-oci8)
Di dunia Ruby, segala macem ekstensi atau plugin itu disebutnya Gem. Buat nyambungin Ruby ke Oracle, kita butuh gem yang namanya ruby-oci8.

Buka Terminal atau CMD (kalo di Windows, pastiin Run as Administrator), trus ketik mantra ini:

gem install ruby-oci8

Catatan: Proses instalasi ini yang kadang suka rewel, Cing. Kalo error, biasanya karena Oracle Instant Client belom kebaca sama sistem. Kudu sabar dan teliti ngatur PATH-nya. Inget petuah Syekh Az-Zarnuji di atas, kudu muwaadzobah (tekun)!

3. Ritual Tes Koneksi (Script Sederhana)
Kalo gem-nya udah sukses terinstal, sekarang kita nulis script pemanasan. Bikin satu folder baru buat project kita, misal namanya toko_ruby. Di dalem folder itu, bikin file baru namanya tes_koneksi.rb.

Buka pake text editor (kayak VS Code atau Sublime), trus masukin kodingan ini:

# Panggil jembatannya dulu
require 'oci8'

puts "Mencoba ngetok pintu Oracle..."

begin
  # Ganti tulisan di bawah ini sesuai sama settingan Oracle XE ente
  # Formatnya: OCI8.new('username', 'password', 'alamat_server/Service_Name')
  
  koneksi = OCI8.new('sistem_toko', 'rahasia123', 'localhost:1521/XEPDB1')
  
  puts "Alhamdulillah, koneksi ke Oracle tembus, Cing!"
  
  # Coba nanya jam server ke Oracle buat bukti
  koneksi.exec('SELECT SYSDATE FROM DUAL') do |baris|
    puts "Waktu di server database sekarang: #{baris[0]}"
  end
  
  # Kalo udah kelar, pintunya kudu ditutup lagi biar memori kagak bocor
  koneksi.logoff
  
rescue OCIError => e
  # Kalo gagal, bakal nongol error-nya di mari
  puts "Waduh, gagal nyambung nih. Cek lagi dah: #{e.message}"
end
4. Eksekusi Script-nya
Balik ke terminal, arahin ke folder toko_ruby tadi, trus jalanin script-nya pake perintah:
ruby tes_koneksi.rb

Kalo di layar nongol tulisan "Alhamdulillah, koneksi ke Oracle tembus, Cing!" ditambah informasi jam server, berarti ente udah resmi menaklukkan tantangan terberat dari duet maut Ruby dan Oracle ini! Fondasinya udah berdiri kokoh.

Mantep, Cing! Semangatnya kudu terus nyala nih ibarat kompor warkop. Sambil nyeruput kopi yang udah diseduh, mari kita lanjutin gass ke penjelasan selanjutnya.


Di penjelasan pertama sebelumnya, kita udah berhasil nembus gerbang tebelnya Oracle pake jembatan ruby-oci8. Sekarang, ibaratnya kita udah masuk ke dalem tanah kosong, waktunya kita ngecor fondasi alias bikin Tabel Database buat nyimpen barang jualan e-commerce kita.

Tapi sebelum ngetik script, mari kita sejukkan hati dan pikiran pake petuah sakti.

Dari kitab kuning legendaris Al-Hikam karya Syekh Ibnu Atha'illah as-Sakandari, ada dawuh yang dalem banget:

"Maa istawda'a fil ghaibi minas saraair, dzahara fisy syahaadati minadz dzawahir."

(Apa yang tersimpan di dalam batin/rahasia, akan tampak bekasnya pada lahiriah/kenyataan).

Kalo ditarik ke dunia programming, database Oracle itu letaknya di batin (rahasia/di belakang layar). Kalo rancangan tabel di dalemnya berantakan, nanti pas datanya ditarik ke tampilan depan (frontend), website-nya bakal lemot dan error. Sebaliknya, kalo "batin"-nya rapi, tampilan luarnya bakal mulus. Ini persis kayak kaidah ngatur struktur kode XML atau HTML; kalo susunan kodenya bersih dan efisien, pas diaudit sama Google PageSpeed Insights, skor mobile-nya bisa gampang nembus cepek (100). Daleman yang bener, ngasilin performa luar yang kinclong!

Ditambah lagi wejangan dari buku The Pragmatic Programmer karya Andrew Hunt & David Thomas:

"A poorly designed system can be a nightmare to maintain."

Sistem yang dirancang asal-asalan bakal jadi mimpi buruk buat dirawat ntar-ntarnya. Makanya, mari kita rancang tabel Oracle ini dengan teliti.

Yuk, buka lagi text editor kesayangan ente, kita mulai ngecor!

Ngecor Fondasi (Bikin Tabel di Oracle pake Ruby)

Di dunia database, proses bikin tabel ini namanya DDL (Data Definition Language). Kita bakal nyuruh Ruby buat ngirim perintah SQL ke Oracle biar dibikinin rak etalase yang rapi.

1. Bikin Script Pembuat Tabel
Bikin file baru di dalem folder toko_ruby sebelonnya, kasih nama bikin_tabel.rb. Ketik kodingan di bawah ini. Ane udah tambahin komentar pake tanda pager (#) biar ente kagak puyeng bacanya:
require 'oci8'

begin
  # Buka pintu ke Oracle (Ganti sesuai settingan ente yak, Cing)
  koneksi = OCI8.new('sistem_toko', 'rahasia123', 'localhost:1521/XEPDB1')
  puts "Koneksi aman, Cing! Mulai ngaduk semen buat tabel..."

  # Ini dia rancangan blueprint rak etalasenya pake bahasa SQL Oracle.
  # Kita pake 'GENERATED ALWAYS AS IDENTITY' biar ID-nya otomatis nambah (kayak Auto Increment)
  rancangan_sql = <<-SQL
    CREATE TABLE barang_dagangan (
      id NUMBER GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
      nama_barang VARCHAR2(100) NOT NULL,
      deskripsi VARCHAR2(500),
      harga NUMBER NOT NULL,
      stok NUMBER DEFAULT 0
    )
  SQL

  # Perintahin Ruby buat ngelempar blueprint tadi ke Oracle
  koneksi.exec(rancangan_sql)
  
  puts "Alhamdulillah, rak etalase (tabel) 'barang_dagangan' udah berdiri kokoh!"

rescue OCIError => e
  # Kalo gagal, satpam Oracle bakal ngasih tau error-nya di mari
  puts "Waduh, ada yang salah pas ngecor nih: #{e.message}"
ensure
  # Wajib fardhu ain nutup koneksi kalo udah kelar!
  if koneksi
    koneksi.logoff
    puts "Pintu Oracle udah ditutup rapi."
  end
end
2. Eksekusi Cor-coran!
Kalo kodenya udah di-save, balik ke terminal ente, trus jalanin mantra ini:
ruby bikin_tabel.rb

Kalo sukses, bakal muncul tulisan "Alhamdulillah, rak etalase (tabel) 'barang_dagangan' udah berdiri kokoh!" (Catatan dikit nih, Cing: Kalo ente ngejalanin script ini dua kali, Oracle bakal ngamuk ngasih error ORA-00955: name is already used by an existing object. Itu wajar, pan tabelnya udah ada, masa mau dibikin numpuk!)

Misi Tambahan: Masukin Barang ke Etalase (Insert Data)

Tabelnya udah jadi, tapi masih kosong melompong. Masa jualan kagak ada barangnya? Ibarat udah bikin saluran video gaming tapi belom upload konten satupun. Sekarang kita isi barangnya pake proses DML (Data Manipulation Language).

Bikin file baru lagi, kasih nama tambah_barang.rb, trus copas racikan kode ini:

require 'oci8'

begin
  koneksi = OCI8.new('sistem_toko', 'rahasia123', 'localhost:1521/XEPDB1')
  puts "Koneksi tembus! Siap bongkar muatan barang..."

  # Siapin barang dagangannya (Nama, Deskripsi, Harga, Stok)
  # ID kagak usah diisi, pan tadi udah dibikin otomatis (Identity)
  sql_tambah = <<-SQL
    INSERT INTO barang_dagangan (nama_barang, deskripsi, harga, stok)
    VALUES (:nama, :deskripsi, :harga, :stok)
  SQL

  # Kita pake metode 'Bind Variables' biar aman dari serangan hacker (SQL Injection)
  kursor = koneksi.parse(sql_tambah)
  
  # Barang Pertama
  kursor.exec('Kaos Polos Mbois', 'Kaos bahan katun adem, cocok buat nongkrong', 55000, 24)
  # Barang Kedua
  kursor.exec('Kopi Bubuk Asli', 'Kopi item racikan warkop, bikin melek nulis kode', 25000, 50)
  
  # Kalo di Oracle, abis masukin data WAJIB dikasih stempel sah (Commit)
  # Kalo kagak di-commit, datanya bakal ilang pas pintu Oracle ditutup.
  koneksi.commit
  
  puts "Dua barang andalan udah sukses masuk etalase!"

rescue OCIError => e
  puts "Gagal bongkar muatan, Cing: #{e.message}"
ensure
  koneksi.logoff if koneksi
end

Jalanin script-nya di terminal:

ruby tambah_barang.rb

Nah, sampe di sini, fondasi database kita beneran udah mantep. Batin (backend) aplikasi e-commerce kita udah punya struktur dan ada isinya.

Kopi paitnya diseruput dulu dah biar mata kagak sepet. Pantang mundur sebelum programnya beneran ngacir. Kita masuk ke penjelasan selanjutnya, nih!


Di penjelasan sebelumnya, kita udah sukses ngecor tabel dan masukin dua barang jagoan ke dalem database Oracle. Nah, barang yang udah disimpen itu ibarat harta karun. Kalo cuma disimpen doang di gudang, pembeli mana tau? Di penjelasan ini, kita bakal ngebongkar gudang itu dan majang datanya biar bisa dibaca (proses Read dari siklus CRUD).

Tapi sebelum jari kita nari di atas keyboard, mari kita resapi dulu asupan rohani dan ilmu dari para sesepuh.

Dari ranah kitab kuning, ada satu kaidah fiqh super mantep dari kitab Al-Ashbah wan Nadza'ir karya Imam Jalaluddin As-Suyuthi:

"Al-yaqinu laa yazaalu bisy-syakk"

(Keyakinan itu tidak bisa dihilangkan oleh keraguan).

Kalo ditarik ke dunia digital marketing dan e-commerce, maknanya dalem banget, Cing. Pas kita nampilin data jualan ke pembeli—mulai dari nama barang, deskripsi, sampe sisa stok—datanya kudu presisi dan real-time. Kagak boleh ada keraguan. Kalo di web tampil stoknya ada 10, pas di-WA ternyata kosong, pembeli bisa kabur dan trust issue. Makanya tarikan data dari Oracle ini harus pasti dan meyakinkan.

Satu lagi dari buku andalan para arsitek software, Clean Architecture karya Om Robert C. Martin (Uncle Bob):

"The goal of software architecture is to minimize the human resources required to build and maintain the required system."

Intinya, kode buat narik data ini kudu ditulis serapi mungkin. Biar ke depannya, kalo toko makin gede, kita kagak capek ngurusinnya. Ketelitian ngeracik kode Ruby ini sebenernya sebelas-dua belas sama ketelitian pas lagi ngoprek struktur XML dan HTML di template Blogger. Buat nembus skor sempurna di Google PageSpeed Insights versi mobile, setiap baris tag kudu efisien, kagak ada kode sampah yang bikin render-blocking. Nah, mental optimasi performa kayak gitu yang mau kita pake buat narik data Oracle ini.

Udah siap? Yuk, buka text editor ente, kita racik kodenya!

Buka Toko & Majang Barang (Read Data)

Kita bakal bikin satu script Ruby yang tugasnya ngetok pintu Oracle, minta daftar barang yang ada di tabel barang_dagangan, trus ditata rapi ke layar biar cakep diliatnya.

1. Bikin Script Penarik Data
Bikin file baru di dalem folder toko_ruby sebelonnya, kasih nama buka_toko.rb. Ketik kodingan di bawah ini. Ane udah pasangin komentar dan bikin format Rupiah sederhana biar tampilannya narik engagement, persis kayak fungsi thumbnail di video konten.
require 'oci8'

# Bikin fungsi kecil buat ngatur format duit biar cakep (ada titiknya)
# Biar harga 55000 jadi 55.000
def format_rupiah(angka)
  angka.to_s.reverse.gsub(/(\d{3})(?=\d)/, '\\1.').reverse
end

begin
  # Buka pintu ke Oracle (Pastiin username sama password ente bener yak)
  koneksi = OCI8.new('sistem_toko', 'rahasia123', 'localhost:1521/XEPDB1')
  puts "\n============================================="
  puts "   SELAMAT DATANG DI TOKO RUBY SULTAN      "
  puts "=============================================\n\n"

  # Ini mantra SQL buat narik semua kolom dari etalase
  sql_tarik_data = "SELECT id, nama_barang, deskripsi, harga, stok FROM barang_dagangan ORDER BY id ASC"

  # Kita eksekusi mantranya, trus datanya kita looping (ulang) per baris
  koneksi.exec(sql_tarik_data) do |baris|
    # baris[0] itu ID, baris[1] itu nama_barang, dan seterusnya sesuai urutan di SELECT
    id_barang = baris[0]
    nama      = baris[1]
    deskripsi = baris[2]
    harga     = format_rupiah(baris[3])
    stok      = baris[4]

    # Nampilin datanya ke layar biar rapi jali
    puts "[#{id_barang}] #{nama.upcase}"
    puts "    Keterangan : #{deskripsi}"
    puts "    Harga      : Rp #{harga}"
    puts "    Sisa Stok  : #{stok} Pcs"
    puts "---------------------------------------------"
  end

  puts "\nSilakan pilih barangnya, Cing! Langsung sikat sebelum kehabisan."

rescue OCIError => e
  # Kalo database ngambek, pesan error-nya ditangkep di mari
  puts "Waduh, etalase macet nutup nih: #{e.message}"
ensure
  # Tutup lagi pintunya biar aman dari kang iseng
  koneksi.logoff if koneksi
end
2. Uji Coba Etalase
Kalo udah di-save dengan rapi, sekarang saatnya pembuktian. Buka terminal ente, arahin ke folder project, trus jalanin mantranya:
ruby buka_toko.rb

Kalo kodingannya lancar jaya, di layar terminal ente bakal nongol output yang rapi banget, nampilin Kaos Polos Mbois sama Kopi Bubuk Asli lengkap sama harganya yang udah ada titiknya dan sisa stoknya. Udah berasa kayak liat katalog di console, kan?

Nah, sampe titik ini, kita udah berhasil nerapin setengah dari ilmu CRUD (Create dan Read). Fondasinya udah cakep, datanya udah bisa dibaca dengan presisi tanpa keraguan sedikitpun.

Kopi paitnya moga belom abis yak, biar semangat tetep ngacir.


Di penjelasan sebelumnya kita udah sukses ngebuka toko dan majang barang (fitur Read). Nah, yang namanya jualan, pasti ada dinamisnya. Kadang harga dari supplier naik, kadang stok ludes diborong orang, atau malah ada barang yang udah discontinue alias kagak diproduksi lagi. Makanya, di penjelasan ini kita bakal namatin siklus maut CRUD di terminal dengan nambahin fitur Update (Revisi Data) dan Delete (Hapus Data).

Tapi tahan dulu jarinya, Cing. Mari kita siram dulu batin kita pake ilmu dari para sesepuh, biar ngetik kodenya makin berkah.

Dari khazanah kitab kuning, ada satu kaidah fiqh yang masyhur banget dari kitab Al-Ashbah wan Nadza'ir karya Imam As-Suyuthi:

"Ad-dhararu yuzal."

(Kemudaratan atau bahaya itu harus dihilangkan).

Kalo ditarik ke urusan database dan programming, data yang udah usang, dobel, atau salah ketik itu adalah "mudarat" buat sistem. Kalo didiemin, database bakal bengkak, tarikan data jadi lemot, dan ujung-ujungnya ngeberatin server. Ini logikanya sebelas-dua belas sama pas lagi ngoprek template Blogger; kalo ada kode XML, script JS, atau CSS usang yang render-blocking kagak dihapus, skor mobile di Google PageSpeed Insights kagak bakal bisa nembus cepek (100). Yang nyampah dan bikin mudarat, kudu ditebas!

Satu lagi wejangan dari Om Kent Beck di dalem bukunya Test-Driven Development: By Example:

"Make it work, make it right, make it fast."

Bikin jalan dulu, baru rapiin, baru bikin ngacir. Nah, fitur Update dan Delete ini adalah fase "Make it right". Kita mastiin data yang ada di Oracle itu selalu valid dan presisi.

Yuk, buka text editor ente, kita mulai ritualnya!

Bengkel Revisi (Update) dan Sapu Jagat (Delete)

Di Oracle, buat ngubah dan ngapus data, kita tetep butuh yang namanya Commit. Kalo kagak di-commit, perubahannya cuma ngambang di memori sementara dan bakal balik ke asal pas pintunya ditutup.

1. Bikin Fitur Revisi Harga dan Stok (UPDATE)
Anggep aja "Kaos Polos Mbois" yang sebelonnya kita masukin (ID nomor 1) harganya naik jadi Rp 60.000 dan stoknya sisa 20. Bikin file baru namanya revisi_barang.rb, trus copas racikan ini:
require 'oci8'

begin
  koneksi = OCI8.new('sistem_toko', 'rahasia123', 'localhost:1521/XEPDB1')
  puts "Pintu bengkel Oracle udah kebuka, Cing!"

  # Kita bikin mantra SQL buat UPDATE
  # Inget, WAJIB pake WHERE. Kalo kagak, semua barang di etalase harganya bakal ikut berubah!
  sql_revisi = <<-SQL
    UPDATE barang_dagangan 
    SET harga = :harga_baru, stok = :stok_baru 
    WHERE id = :id_barang
  SQL

  # Eksekusi mantranya pake Bind Variables biar aman dari hacker
  # Urutannya kudu pas sama titik dua (:) di dalem mantra SQL di atas
  harga_update = 60000
  stok_update = 20
  id_target = 1 # ID Kaos Polos Mbois

  puts "Lagi ngotak-ngatik data Kaos Polos Mbois..."
  
  koneksi.exec(sql_revisi, harga_update, stok_update, id_target)
  
  # Stempel sah! (Commit)
  koneksi.commit
  
  puts "Alhamdulillah, harga sama stok udah sukses di-update!"

rescue OCIError => e
  puts "Waduh, kunci inggrisnya meleset: #{e.message}"
ensure
  koneksi.logoff if koneksi
end

Jalanin script-nya di terminal pake perintah ruby revisi_barang.rb. Kalo sukses, nanti ente bisa cek lagi pake script buka_toko.rb yang kita bikin di penjelasan sebelumnya buat liat perubahannya.

2. Bikin Fitur Hapus Barang (DELETE)
Sekarang, anggep aja "Kopi Bubuk Asli" (ID nomor 2) udah discontinue dari supplier. Ketimbang menuhin database dan ngerusak layout katalog kita, mending kita tebas.

Bikin file baru namanya hapus_barang.rb, ketik kode di bawah ini:

require 'oci8'

begin
  koneksi = OCI8.new('sistem_toko', 'rahasia123', 'localhost:1521/XEPDB1')
  puts "Petugas kebersihan Oracle udah siap sedia!"

  # Mantra SQL buat DELETE
  # Sekali lagi, WAJIB pake WHERE! Kalo kelupaan, ludes semua barang jualan ente.
  sql_hapus = "DELETE FROM barang_dagangan WHERE id = :id_barang"

  id_target_hapus = 2 # ID Kopi Bubuk Asli

  puts "Lagi nyingkirin Kopi Bubuk Asli dari gudang..."
  
  # Eksekusi dan langsung buang
  koneksi.exec(sql_hapus, id_target_hapus)
  
  # Jangan lupa distempel biar perubahannya permanen
  koneksi.commit
  
  puts "Beres, Cing! Barangnya udah musnah dari muka bumi Oracle."

rescue OCIError => e
  puts "Gagal ngapus nih, sapunya patah: #{e.message}"
ensure
  koneksi.logoff if koneksi
end

Jalanin lagi script-nya pake ruby hapus_barang.rb. Kalo ente buka lagi buka_toko.rb, dijamin si kopi udah ilang tanpa bekas.

Kopi seduhan barunya udah siap pan? Kita gass masuk ke penjelasan selanjutnya!


Di empat penjelasan sebelumnya, kita udah sukses ngebangun pondasi dan namatin siklus CRUD (Create, Read, Update, Delete) pake Ruby dan Oracle. Tapi masalahnya, sejauh ini kita cuma mainan di layar terminal item putih doang. Masa iyak jualan e-commerce kagak ada visualnya? Kalo kagak ada alamat web-nya, gimana Mbah Google mau nge-crawl dan nge-indeks toko kita?

Nah, di penjelasan ini kita bakal nyulap kodingan backend terminal tadi jadi sebuah website beneran yang bisa dibuka di browser (Chrome, Firefox, dsb).

Tapi sebelum tangan kita keriting ngetik kode, mari kita isi bensin rohani dan intelektual dulu dari para suhu.

Pertama, dari ranah kitab kuning, kita pinjem kaidah dari matan ilmu tata bahasa Arab paling legendaris, Al-Ajurrumiyyah karya Syekh As-Shanhaji. Di bab awal beliau bilang:

"Al-kalamu huwa al-lafzhu al-murakkabu al-mufidu bil-wadh'i."

(Kalam/kalimat itu adalah lafaz yang tersusun, memberikan faedah, dan disengaja letaknya).

Kalo ditarik ke dunia web development, HTML dan Ruby yang kita tulis itu ibarat "kalam". Susunan tag HTML-nya kudu murakkab (tersusun rapi dan terstruktur), isinya kudu mufid (berfaedah buat user dan mesin pencari), dan tata letaknya kudu pas. Kalo kode HTML-nya berantakan, browser bakal puyeng bacanya, dan bot Mbah Google bakal males nge-indeks website kita.

Kedua, ada wejangan super penting dari Om Steve Souders (Bapak Kinerja Web) di bukunya High Performance Web Sites:

"80% to 90% of the end-user response time is spent on the frontend. Start there."

Dalem banget nih, Cing! Percuma database Oracle kita udah kekar badak, kalo pas datanya ditampilin ke depan (frontend) loading-nya berat gara-gara banyak elemen render-blocking. Ente pan udah biasa ngulik-ngulik struktur XML/HTML di Blogger demi ngejar skor sempurna di PageSpeed mobile, nah mental teliti dan ngejar performa ngacir itu kudu ente bawa pas kita ngerajut HTML pake Ruby ini.

Biar kagak pusing langsung lompat ke framework raksasa kayak Ruby on Rails, kita bakal pake framework Ruby yang super ringan, ramping, tapi ngebut banget. Namanya Sinatra. Yuk, kita mulai ritualnya!

Ngebuka Pintu Web (Bikin Server pake Sinatra)

Sinatra ini ibarat gerobak jualan yang sat-set. Kagak butuh banyak file, cukup satu file utama, website langsung tayang.

1. Pasang Alat Tempur Baru (Install Sinatra)
Buka terminal atau CMD ente (pastiin lagi ada di folder toko_ruby yang sebelonnya), trus ketik mantra ini buat nginstal Sinatra:
gem install sinatra

Tungguin bentar sampe kelar. Sinatra ini ukurannya kecil, jadi kagak bakal ngabisin kuota.

2. Bikin Halaman Tampilan (View / HTML)
Biar kodenya rapi dan SEO friendly, kita pisahin antara logika mesin (Ruby) sama tampilan layar (HTML).

Di dalem folder toko_ruby, bikin folder baru, kasih nama views. (Nama foldernya wajib views yak, huruf kecil semua).

Di dalem folder views itu, bikin file baru namanya etalase.erb.

File .erb (Embedded Ruby) ini ibarat HTML biasa, tapi kita bisa nyelipin kode Ruby di dalemnya. Buka file etalase.erb pake text editor, trus copas racikan kode ini. Ane udah susun struktur tag-nya biar rapi dan enteng pas di-load:

<!DOCTYPE html>
<html lang="id">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Toko Sultan Oracle - Belanja Ngacir</title>
    <meta name="description" content="Katalog barang mantep langsung dari database Oracle. Belanja sat-set, loading ngacir.">
    
    <style>
        /* CSS seadanya biar kagak sakit mata, tapi tetep enteng (gak pake framework external) */
        body { font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif; background-color: #f4f4f9; padding: 20px; margin: 0; }
        .header { text-align: center; margin-bottom: 30px; }
        .grid-container { display: flex; gap: 20px; flex-wrap: wrap; justify-content: center; }
        .card { background: white; border: 1px solid #ddd; border-radius: 10px; padding: 20px; width: 280px; box-shadow: 0 4px 6px rgba(0,0,0,0.05); }
        .card h3 { margin-top: 0; color: #333; }
        .harga { color: #e74c3c; font-weight: bold; font-size: 1.2em; }
        .stok { font-size: 0.9em; color: #7f8c8d; }
        .btn-beli { display: block; text-align: center; background-color: #27ae60; color: white; padding: 10px; text-decoration: none; border-radius: 5px; margin-top: 15px; font-weight: bold; }
    </style>
</head>
<body>

    <div class="header">
        <h1>Katalog Toko Sultan</h1>
        <p>Silakan dipilih, Cing! Data ditarik langsung dari perut Oracle.</p>
    </div>

    <div class="grid-container">
        <% @daftar_barang.each do |barang| %>
            <div class="card">
                <h3><%= barang[:nama] %></h3>
                <p><%= barang[:deskripsi] %></p>
                <p class="harga">Rp <%= barang[:harga] %></p>
                <p class="stok">Sisa Stok: <%= barang[:stok] %></p>
                
                <a href="#" class="btn-beli">🛒 Beli Sekarang</a>
            </div>
        <% end %>
        
        <% if @daftar_barang.empty? %>
            <p>Waduh, etalase lagi kosong melompong nih, Cing!</p>
        <% end %>
    </div>

</body>
</html>
3. Bikin Pelayan Web (Server Sinatra)
Tampilan HTML udah jadi, sekarang kita bikin mesin pelayannya. Balik ke luar folder views (di dalem folder utama toko_ruby), bikin file baru namanya toko_web.rb.

Ini dia racikan sat-set gabungan Ruby, Sinatra, dan Oracle:

require 'sinatra'
require 'oci8'

# Ini rute utama (pintu depan website)
# Kalo ada orang ngetik alamat web kita di browser, ini yang bakal dieksekusi
get '/' do
  # Bikin wadah kosong buat nyimpen barang dari Oracle
  @daftar_barang = []

  begin
    # Ketok pintu Oracle
    koneksi = OCI8.new('sistem_toko', 'rahasia123', 'localhost:1521/XEPDB1')
    
    # Tarik datanya
    koneksi.exec("SELECT id, nama_barang, deskripsi, harga, stok FROM barang_dagangan ORDER BY id ASC") do |baris|
      # Rapihin duit pake format Rupiah
      harga_rupiah = baris[3].to_s.reverse.gsub(/(\d{3})(?=\d)/, '\\1.').reverse
      
      # Masukin datanya ke wadah @daftar_barang (dalam bentuk Hash/Kamus)
      @daftar_barang << {
        id: baris[0],
        nama: baris[1],
        deskripsi: baris[2],
        harga: harga_rupiah,
        stok: baris[4]
      }
    end

  rescue OCIError => e
    # Kalo Oracle lagi ngambek, tampilin error-nya
    return "Yah, database-nya lagi maintenance, Cing: #{e.message}"
  ensure
    # Jangan lupa pintunya ditutup!
    koneksi.logoff if koneksi
  end

  # Lempar wadah @daftar_barang tadi ke file HTML (etalase.erb) buat ditampilin
  erb :etalase
end
4. Uji Coba Launching Web!
Semua file udah di-save? Cakep! Sekarang balik ke terminal, pastiin ente ada di folder toko_ruby, trus jalanin mantranya:
ruby toko_web.rb

Kalo sukses, di terminal bakal nongol tulisan keren dari Sinatra, ngasih tau kalo server ente udah jalan di port 4567.

Sekarang, buka browser ente (Chrome/Firefox/Brave), terus ketik alamat ini di URL:
http://localhost:4567

Jreng-jreng!
Kalo kodingannya lancar, ente bakal ngeliat website etalase toko ente udah nongol! Kagak lagi di layar item terminal, tapi udah rapi pake kotak-kotak putih yang sedap dipandang mata.

Kopi seduhan barunya diseruput dulu, Cing. Alhamdulillah kita nyampe juga di penjelasan selanjutnya.


Di penjelasan sebelumnya kita udah sukses nampilin barang dari "perut" Oracle ke browser pake bantuan Sinatra. Tapi ada yang kurang greget: tombol "Beli Sekarang" masih pajangan doang alias link mati. Di penjelasan ini, kita bakal nyulap tombol itu biar langsung nembak pesenan ke WhatsApp (WA Checkout).

Sebelum ngetik script, mari kita sejukkan pikiran pake wejangan sakti biar kodingannya makin berkah.

Pertama, dari ranah kitab kuning, ada satu kaidah fiqh mentereng dari kitab Al-Ashbah wan Nadza'ir karya Imam As-Suyuthi:

"Al-Masyaqqatu tajlibut taysir."

(Kesulitan itu menarik datangnya kemudahan).

Kalo ditarik ke dunia muamalah zaman now, pembeli itu paling males kalo disuruh ngisi form checkout yang kepanjangan. Kesulitan pembeli ini kudu kita kasih kemudahan. Jalur paling gampang buat market lokal ya ngebuka pintu negosiasi langsung ke WhatsApp.

Kedua, dari buku andalan para perancang produk, Hooked karya Om Nir Eyal:

"To initiate action, doing must be easier than thinking."

Maksudnya, buat mancing orang ngeklik, prosesnya harus lebih gampang daripada mikir. Ane Sebagai orang yang ngebawa bendera filosofi Raja Digital ID, ngegabungin web development yang solid sama digital marketing yang sat-set itu udah jadi kewajiban. Akhir April ini pas lagi mantau progress submission video gaming ke platform distribusi sebelonnya, ane ngerasain banget kalo milih settingan yang ribet itu bikin proses mandek. Nah, pembeli juga gitu. Begitu ngeliat thumbnail produk yang eye-catching, mereka harus dikasih jalur checkout yang sekali klik langsung jalan.

Yuk, buka lagi text editor ente. Kita racik link pintar WA Checkout-nya!

Nyambungin Jalur Cuan (WhatsApp Checkout pake Ruby)

Di Sinatra, nyisipin logika Ruby ke dalem HTML itu gampang banget pake tag <% ... %>. Kita bakal pake fungsi bawaan Ruby buat ngubah teks pesan yang ada spasinya jadi format URL yang aman (URL Encoding), biar link WA-nya kagak patah di tengah jalan.

1. Rombak File Tampilan (etalase.erb)
Buka lagi file views/etalase.erb yang kita bikin di penjelasan sebelumnya. Cari bagian tombol <a href="#" class="btn-beli">🛒 Beli Sekarang</a>, trus ganti script di dalem div class="card" itu pake racikan baru di bawah ini:
        <% @daftar_barang.each do |barang| %>
            <div class="card">
                <h3><%= barang[:nama] %></h3>
                <p><%= barang[:deskripsi] %></p>
                <p class="harga">Rp <%= barang[:harga] %></p>
                <p class="stok">Sisa Stok: <%= barang[:stok] %></p>
                
                <% 
                  # Panggil pustaka URI bawaan Ruby buat ngerapihin teks URL
                  require 'uri'
                  
                  # Ganti pake nomor WA toko ente (Wajib mulai dari 62, jangan 0)
                  nomor_wa = "6281234567890" 
                  
                  # Susun kalimat pesenannya (Simbol \n itu buat enter/baris baru)
                  teks_pesan = "Halo Admin, ane kepincut sama barang ini:\n\n"
                  teks_pesan += "📦 Nama Barang: #{barang[:nama]}\n"
                  teks_pesan += "💰 Harga: Rp #{barang[:harga]}\n\n"
                  teks_pesan += "Kira-kira sisa stok yang #{barang[:stok]} biji itu masih ready buat dikirim hari ini kagak?"
                  
                  # Encode teksnya biar spasi berubah jadi %20 dan aman diklik
                  teks_aman = URI.encode_www_form_component(teks_pesan)
                  
                  # Gabungin jadi link WA sakti
                  link_checkout = "https://wa.me/#{nomor_wa}?text=#{teks_aman}"
                %>
                
                <a href="<%= link_checkout %>" target="_blank" class="btn-beli">
                    🛒 Beli via WhatsApp
                </a>
            </div>
        <% end %>
2. Bedah Singkat Kodingannya Biar Kagak Puyeng

- require 'uri': Ini ibarat kita manggil bala bantuan dari dalem mesin Ruby buat ngurusin link internet.
- #{barang[:nama]}: Ini cara Ruby nyelipin nilai variabel ke dalem kalimat teks (String Interpolation). Kalo di PHP kan biasanya pake titik (.), di Ruby lebih elegan pake pager sama kurung kurawal.
- URI.encode_www_form_component(): Ini fungsi magic-nya, Cing. Browser itu kagak kenal yang namanya spasi ( ). Kalo kalimat WA ente kagak dimasukin ke mesin ini dulu, nanti pas tombolnya diklik, pesannya bakal kepotong.
- target="_blank": Ini hukumnya fardhu ain buat digital marketing. Biar pas pembeli ngeklik tombol, aplikasi WA bakal kebuka di tab baru, sementara website katalog kita kagak ketutup. Bounce rate tetep aman terkendali!
3. Waktunya Uji Coba Jalur Cuan!
Kalo file etalase.erb udah di-save, ente kagak perlu ngerestart server Sinatra-nya (selama ente cuma ngubah file .erb alias view).

Langsung aja buka browser ente.
Refresh halaman http://localhost:4567.
Coba klik tombol "🛒 Beli via WhatsApp" di salah satu barang (misal: Kopi Bubuk Asli).

Kalo kodingannya bener, browser bakal langsung buka tab baru ke api.whatsapp.com (atau langsung ngebuka aplikasi WhatsApp Desktop di laptop), dan di kolom chat-nya udah tertulis rapi format pesenan sesuai nama barang dan harganya.

Kopi paitnya moga masih anget yak. Kita gass masuk ke penjelasan seanjutnya!


Di penjelasan sebelumnya kita udah sukses ngebuka etalase depan dan masang tombol sakti WhatsApp Checkout. Tapi coba ente pikirin dah, kalo sewaktu-waktu ada barang baru masuk dari supplier, masa iyak kita kudu buka terminal item-putih lagi trus ngetik script tambah_barang.rb kayak di penjelasan yang kedua ? Kagak efisien banget!

Sebagai developer yang bawa bendera mentereng Raja Digital ID, workflow kita kudu elegan dan sat-set. Makanya, di penjelasan ini kita bakal bikin Formulir Tambah Barang langsung di dalem website (Web Form). Jadi, urusan nambah data ke perut Oracle bisa dilakuin sambil ngopi buka browser.

Sebelum jari kita nari di keyboard, mari kita resapi dulu ilmu dari dua dimensi yang beda ini.

Pertama, dari kitab kuning kebanggaan para santri, Al-Hikam karya Syekh Ibnu Atha'illah as-Sakandari. Ada satu hikmah yang dalem banget bunyinya:

"Al-a'malu shuwarun qaaimatun, wa arwahuha wujuudu sirril ikhlaasi fiiha."

(Amal-amal perbuatan itu ibarat kerangka/rupa yang tegak berdiri, sedangkan ruhnya adalah adanya rahasia ikhlas di dalamnya).

Kalo ditarik ke urusan kodingan web, formulir HTML (kotak input yang kita bikin) itu cuma kerangkanya doang, Cing. Rupa luarnya doang. Nah, biar formulir itu hidup dan beneran bisa nyimpen data ke database, dia butuh "ruh", yaitu script logika backend (pake metode POST) di dalem Sinatra. Kalo rupa sama ruhnya kagak nyatu, formnya bakal mati alias error.

Kedua, dari buku sucinya para pakar UX (User Experience), Don't Make Me Think karya Om Steve Krug:

"It doesn't matter how many times I have to click, as long as each click is a mindless, unambiguous choice."

Maksudnya, mau nambah barang itu prosesnya kudu sejelas mungkin. Kotak isian buat nama barang ya isinya nama, jangan bikin admin (atau kita sendiri) puyeng nebak-nebak ini form buat ngisi apaan. Kerapian ini juga yang ngebantu performa kerjaan SEO dan web development kita makin ngacir, karena sistemnya gampang dikelola.

Yuk, kita racik kerangka HTML sama ruh Ruby-nya!

Bikin Pintu Belakang (Formulir Tambah Barang via Web)

Di Sinatra, kita butuh dua rute baru: satu rute pake metode GET buat nampilin formulirnya, dan satu rute pake metode POST buat nangkep isian formnya trus dilempar ke dalem Oracle.

1. Rombak Pelayan Web (toko_web.rb)
Buka file toko_web.rb yang kita bikin di penjelasan lima. Di bawah rute get '/' do ... end, tambahin dua rute baru ini:
# 1. Pintu buat nampilin halaman formulir tambah barang
get '/tambah' do
  erb :tambah_barang
end

# 2. Pintu rahasia (Ruh-nya) buat nangkep data dari formulir dan disimpen ke Oracle
post '/simpan' do
  # Tangkep data yang diketik di dalem form HTML (pake atribut 'name')
  nama      = params[:nama_barang]
  deskripsi = params[:deskripsi]
  harga     = params[:harga]
  stok      = params[:stok]

  begin
    koneksi = OCI8.new('sistem_toko', 'rahasia123', 'localhost:1521/XEPDB1')
    
    # Mantra SQL buat bongkar muatan ke tabel Oracle (pake Bind Variables :1, :2 dst biar aman)
    sql_simpan = "INSERT INTO barang_dagangan (nama_barang, deskripsi, harga, stok) VALUES (:1, :2, :3, :4)"
    
    koneksi.exec(sql_simpan, nama, deskripsi, harga, stok)
    
    # Wajib stempel sah (commit) biar datanya kagak ngilang!
    koneksi.commit
    
  rescue OCIError => e
    return "Waduh, gagal masuk gudang nih Cing: #{e.message}"
  ensure
    koneksi.logoff if koneksi
  end

  # Kalo udah sukses nyimpen, pelayan otomatis ngelempar kita balik ke etalase depan
  redirect '/'
end
2. Bikin Kerangka Formulirnya (HTML / ERB)
Sekarang, masuk ke folder views, trus bikin file baru namanya tambah_barang.erb. Ini dia kerangka HTML-nya. Ane udah desain simpel tapi tetep rapi.
<!DOCTYPE html>
<html lang="id">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Gudang Admin - Tambah Barang</title>
    <style>
        body { font-family: 'Segoe UI', Tahoma, sans-serif; background-color: #f4f4f9; padding: 20px; }
        .form-container { background: white; max-width: 400px; margin: 0 auto; padding: 30px; border-radius: 10px; box-shadow: 0 4px 6px rgba(0,0,0,0.1); }
        h2 { text-align: center; color: #333; margin-top: 0; }
        .form-group { margin-bottom: 15px; }
        label { display: block; font-weight: bold; margin-bottom: 5px; color: #555; }
        input[type="text"], input[type="number"], textarea { width: 100%; padding: 10px; border: 1px solid #ccc; border-radius: 5px; box-sizing: border-box; }
        .btn-simpan { width: 100%; background-color: #2980b9; color: white; padding: 12px; border: none; border-radius: 5px; font-weight: bold; cursor: pointer; margin-top: 10px; }
        .btn-batal { display: block; text-align: center; color: #e74c3c; text-decoration: none; margin-top: 15px; font-size: 14px; }
    </style>
</head>
<body>

    <div class="form-container">
        <h2>📦 Tambah Barang Baru</h2>
        
        <form action="/simpan" method="POST">
            
            <div class="form-group">
                <label>Nama Barang:</label>
                <input type="text" name="nama_barang" required placeholder="Contoh: Kaos Polos Mbois">
            </div>

            <div class="form-group">
                <label>Deskripsi (Biar SEO-nya dapet):</label>
                <textarea name="deskripsi" rows="3" required placeholder="Jelasin barangnya di mari..."></textarea>
            </div>

            <div class="form-group">
                <label>Harga (Rupiah):</label>
                <input type="number" name="harga" required placeholder="Contoh: 50000">
            </div>

            <div class="form-group">
                <label>Jumlah Stok Awal:</label>
                <input type="number" name="stok" required placeholder="Contoh: 12">
            </div>

            <button type="submit" class="btn-simpan">💾 Simpan ke Database</button>
            <a href="/" class="btn-batal">← Batal & Balik ke Etalase</a>
            
        </form>
    </div>

</body>
</html>
3. Tambahin Jalan Masuk di Halaman Depan
Biar ente gampang ngeklik form-nya dari halaman utama, buka lagi file views/etalase.erb. Di bawah tulisan <p>Silakan dipilih, Cing! ... </p>, selipin tombol ini:
    <div style="text-align: center; margin-bottom: 20px;">
        <a href="/tambah" style="background-color: #34495e; color: white; padding: 10px 20px; text-decoration: none; border-radius: 5px; font-weight: bold;">➕ Tambah Barang Baru</a>
    </div>

Waktunya Uji Coba Pintu Belakang!

Kalo kodingan tadi udah di-save semua, ente kudu nge-restart server Sinatra-nya (karena kita nambahin logika Ruby di toko_web.rb).

Buka terminal, teken Ctrl + C buat matiin server yang sebelonnya.
Jalanin lagi mantranya: ruby toko_web.rb.
Buka browser, refresh http://localhost:4567.

Sekarang, di etalase depan udah ada tombol item bertuliskan "➕ Tambah Barang Baru". Coba ente klik! Ente bakal dibawa ke halaman formulir yang rapi. Isi dah tuh nama barang, harganya, stoknya, trus klik Simpan ke Database.

Kalo berhasil, ente bakal otomatis dilempar balik ke etalase depan, dan barang yang barusan ente masukin udah langsung mejeng dengan gagah di situ!

Kopi seduhan terbarunya diseruput dulu biar makin fokus. Kita udah nyampe di penjelasan selanjutnya nih.


Di penjelasan sebelumnya, pintu belakang toko kita udah kebuka lebar pake formulir HTML. Masalahnya, pintu itu belom digembok! Kalo website ini di-hosting ke internet, siapa bae yang iseng ngetik URL /tambah bakal bisa nyelonong masuk dan ngacak-ngacak database Oracle kita.

Sebelum kita pasang satpam, mari kita siram batin kita pake ilmu dari para sesepuh.

Dari khazanah kitab kuning, ada wejangan super dalem dari kitab Bidayatul Hidayah karya Hujjatul Islam Imam Al-Ghazali. Di bab menjaga anggota badan, beliau berpesan:

"Fahfadz bathnaka min tanaawulil haraam wash-syubuhaat."

(Maka jagalah perutmu dari mengonsumsi makanan yang haram dan syubhat).

Kalo ditarik ke urusan kodingan, "perut" dari aplikasi e-commerce kita ini adalah database Oracle. Kita wajib fardhu ain ngejaga perut database itu dari "makanan" (input data) yang kagak berizin alias haram. Jangan sampe disusupin data sampah sama kang iseng di internet.

Satu lagi dari buku babon keamanan siber, The Web Application Hacker's Handbook karya Dafydd Stuttard:

"All user input is untrusted. Security mechanisms must be designed to assume that all input is potentially malicious."

Maksudnya, jangan pernah percaya sama apa pun yang diketik pengunjung. Pas lagi ngatur settingan submission konten video gaming biar rilisnya mulus, ente pasti mikirin keamanan akun juga pan biar kagak dibajak? Sama aja kayak website jualan. Kalo form /tambah dibiarin telanjang, kang iseng bisa nyampah di etalase kita. Ujung-ujungnya, database bengkak, loading web jadi berat, dan skor PageSpeed mobile andalan kita bisa anjlok.

Biar sat-set tapi tetep aman, kita bakal pasang gembok ala ninja pake fitur HTTP Basic Auth di dalem Sinatra. Kodenya ringkas, tapi ampuh buat nyegat pengunjung gelap!

Masang Satpam di Pintu Belakang (Authentication)

Di Sinatra, kita bisa bikin fungsi Helper (pembantu) yang tugasnya jadi satpam. Dia bakal ngecek setiap pengunjung yang mau masuk ke rute /tambah atau /simpan. Kalo kagak punya username dan password yang bener, pengunjung bakal ditendang balik.

1. Ngedidik Satpam (Bikin Helper Auth)
Buka lagi file toko_web.rb punya ente. Di baris atas (tepat di bawah tulisan require 'oci8'), selipin racikan script satpam ini:
require 'sinatra'
require 'oci8'

# ==========================================
# SATPAM PENJAGA PINTU (Helper Auth)
# ==========================================
helpers do
  def satpam_jaga!
    # Kalo udah bawa tiket (login bener), silakan masuk
    return if authorized?
    
    # Kalo belom login, munculin popup minta password
    headers['WWW-Authenticate'] = 'Basic realm="Gudang Rahasia Toko Sultan"'
    halt 401, "Akses Ditolak, Cing! Ente bukan admin, dilarang masuk.\n"
  end

  def authorized?
    # Proses ngecek username sama password yang diketik di popup
    @auth ||=  Rack::Auth::Basic::Request.new(request.env)
    
    # Ganti 'admin' sama 'rahasia123' ini pake password andalan ente
    @auth.provided? && @auth.basic? && @auth.credentials && @auth.credentials == ['admin', 'rahasia123']
  end
end
# ==========================================
2. Nugas-in Satpam di Rute Rahasia
Satpamnya udah pinter, sekarang kita kudu naruh dia di pintu yang bener. Jangan taruh di pintu depan (get '/'), ntar pembeli malah disuruh login! Taruh aja di dalem rute /tambah dan /simpan.

Gulir file toko_web.rb ente ke bawah, trus panggil fungsi satpam_jaga! di baris pertama dalem rute tersebut. Jadinya kayak gini:

# 1. Pintu buat nampilin halaman formulir (Sekarang udah digembok!)
get '/tambah' do
  satpam_jaga!  # <--- Panggil satpamnya di mari
  
  erb :tambah_barang
end

# 2. Pintu rahasia buat nangkep data dan disimpen ke Oracle (Digembok juga!)
post '/simpan' do
  satpam_jaga!  # <--- Panggil satpamnya di mari juga, biar aman ganda
  
  nama      = params[:nama_barang]
  deskripsi = params[:deskripsi]
  harga     = params[:harga]
  stok      = params[:stok]

  # ... (Sisa kodingan simpan ke Oracle tetep sama kayak di penjelasan tujuh) ...

Waktunya Uji Coba Gembok!

Save kodingan ente. Karena kita abis ngubah file Ruby utama, ente kudu nge-restart mesin pelayannya.

Di terminal, teken Ctrl + C buat matiin server.
Nyalain lagi pake ruby toko_web.rb.
Buka browser ente, masuk ke etalase depan: http://localhost:4567.

Etalase depan tetep bisa dibuka tanpa rintangan (aman buat pembeli dan aman buat di-crawl Mbah Google).

Sekarang, coba klik tombol "➕ Tambah Barang Baru".

Jreng-jreng!
Browser ente (entah itu Chrome atau Firefox) bakal langsung ngeluarin pop-up kecil dari atas, nanyain Username sama Password. Kalo ente iseng ngeklik Cancel, ente bakal dikasih layar putih polos bertuliskan: "Akses Ditolak, Cing! Ente bukan admin, dilarang masuk."

Biar pintunya kebuka, isi pop-up tadi pake data sandi yang udah kita setel di kodingan tadi:
Username: admin
Password: rahasia123

Begitu dienter, wusss! Pintu gudang kebuka, dan ente bisa ngakses formulir tambah barang lagi dengan tenang.


Di penjelasan sebelumnya, pintu belakang toko kita udah digembok rapet pake satpam Basic Auth. Tapi sekarang ada PR baru di etalase depan. Kalo barang jualan kita baru dua biji sih enak diliatnya, nah kalo barangnya udah ratusan? Pembeli bisa kriting jempolnya nge-scroll ke bawah.

Sebelum kita babat kodenya, mari kita sejukkan akal kita pake wejangan sakti dari dua dunia yang beda.

Pertama, dari ranah kitab kuning, ada dawuh yang masyhur dari kitab Nashaihul 'Ibad karya ulama nusantara legendaris, Syekh Nawawi al-Bantani. Beliau mengutip maqalah:

"Kullu syai'in idza katsura rakhusa, illal adab."

(Segala sesuatu itu jika bertambah banyak jumlahnya, maka harganya akan menjadi murah/jatuh, kecuali adab atau ilmu).

Kalo ditarik ke urusan e-commerce, barang jualan di database yang makin banyak dan numpuk itu bisa bikin value atau kenyamanan website kita jatuh murah di mata pembeli, kecuali kalo kita pake "ilmu" buat ngaturnya. Ilmu ngaturnya itu ya bikin fitur filter atau Pencarian (Search), biar tumpukan barang tadi gampang diurai.

Kedua, ada petuah emas dari suhu Information Architecture, Om Peter Morville, di dalem bukunya yang top markotop, Ambient Findability:

"Findability precedes usability. In the alphabet and on the Web. You can't use what you can't find."

Maksudnya dalem banget, Cing. Percuma website kita tampilannya canggih atau harganya paling murah, kalo pembeli puyeng nyari barangnya, mereka pasti langsung kabur (bounce). Navigasi yang ribet itu musuh utama konversi. Sama persis logikanya pas ente lagi ngatur settingan submission konten video gaming ke platform distribusi; kalo form-nya ribet, proses rilisnya mandek. Atau pas ente lagi ngoprek struktur XML di Blogger demi ngejar skor PageSpeed mobile cepek (100); selain loading kudu ngacir, pengunjung juga kudu gampang nemuin apa yang mereka cari. Kalo kagak, thumbnail narik yang udah capek-capek dibikin bakal sia-sia.

Yuk, langsung kita eksekusi fitur Search pake metode GET di Sinatra biar pembeli kagak nyasar!

Bikin Kolom Pencarian (Search Feature)

Di Ruby dan Oracle, bikin fitur pencarian itu gampang banget. Kita cuma butuh ngandelin form HTML biasa, trus ditangkep sama rute utama kita buat difilter di database pake perintah SQL LIKE.

1. Pasang Kolom Ketikan di Etalase (View / HTML)
Buka lagi file views/etalase.erb punya ente. Di bawah judul "Katalog Toko Sultan" (di bawah tag </div> bagian header), selipin script HTML buat kotak pencariannya:
    <div style="text-align: center; margin-bottom: 30px;">
        <form action="/" method="GET" style="display: inline-flex; width: 100%; max-width: 400px; box-shadow: 0 2px 4px rgba(0,0,0,0.1); border-radius: 5px; overflow: hidden;">
            
            <input type="text" name="cari" placeholder="Cari barang apa bosku?..." 
                   style="flex-grow: 1; padding: 12px; border: 1px solid #ccc; border-right: none; outline: none; font-size: 16px;">
            
            <button type="submit" style="background-color: #e67e22; color: white; padding: 12px 20px; border: none; cursor: pointer; font-weight: bold;">
                🔍 Cari
            </button>
        </form>
    </div>
2. Ngedidik Pelayan Buat Nerima Kata Kunci (Ruby / Sinatra)
Formnya udah mejeng, sekarang pelayannya kudu kita ajarin nangkep kata kuncinya. Buka file toko_web.rb, trus ubah bagian rute get '/' do yang paling atas jadi kayak gini:
# Rute utama (pintu depan) yang sekarang udah pinter nyari barang
get '/' do
  @daftar_barang = []
  
  # Tangkep isian dari kolom pencarian (kalo ada)
  kata_kunci = params[:cari]

  begin
    koneksi = OCI8.new('sistem_toko', 'rahasia123', 'localhost:1521/XEPDB1')
    
    # Kalo pengunjung ngetik sesuatu di kolom pencarian
    if kata_kunci && !kata_kunci.strip.empty?
      
      # Mantra SQL pake 'LOWER' biar pencariannya kagak peduli huruf gede/kecil (Case Insensitive)
      # Simbol % itu ibarat 'wildcard', artinya huruf depan/belakangnya bebas apa aja
      sql_tarik = "SELECT id, nama_barang, deskripsi, harga, stok FROM barang_dagangan 
                   WHERE LOWER(nama_barang) LIKE :1 OR LOWER(deskripsi) LIKE :1 
                   ORDER BY id ASC"
      
      # Eksekusi pake Bind Variable, tambahin % di awal dan akhir kata
      pencarian_aman = "%#{kata_kunci.downcase}%"
      kursor = koneksi.exec(sql_tarik, pencarian_aman)
      
    else
      # Kalo kolomnya kosong, yaudah tarik semua data kayak biasa
      sql_tarik = "SELECT id, nama_barang, deskripsi, harga, stok FROM barang_dagangan ORDER BY id ASC"
      kursor = koneksi.exec(sql_tarik)
    end

    # Looping datanya (sama kayak sebelumnya)
    while baris = kursor.fetch
      harga_rupiah = baris[3].to_s.reverse.gsub(/(\d{3})(?=\d)/, '\\1.').reverse
      
      @daftar_barang << {
        id: baris[0],
        nama: baris[1],
        deskripsi: baris[2],
        harga: harga_rupiah,
        stok: baris[4]
      }
    end

  rescue OCIError => e
    return "Database Oracle lagi semaput nih, Cing: #{e.message}"
  ensure
    koneksi.logoff if koneksi
  end

  erb :etalase
end

Waktunya Uji Coba Kecepatan!

Udah gitu doang, Cing! Simpel parah pan? Sekarang coba save semua file-nya.

Di terminal, teken Ctrl + C buat matiin server yang lama.
Nyalain lagi mesinnya pake perintah ruby toko_web.rb.
Buka browser dan masuk ke etalase depan toko ente: http://localhost:4567.

Kalo kodenya kagak ada yang typo, sekarang di bawah judul toko udah nongol tuh kotak pencarian yang rapi jali. Coba ente ketik nama barang yang sebelonnya kita masukin (misal: "Kopi" atau "Kaos"), trus klik tombol Cari.

Liat ajaibnya, halaman bakal nge-refresh dan URL-nya bakal berubah ada embel-embelnya /?cari=Kopi. Barang yang nongol di etalase juga langsung ke-filter secepat kilat pake tenaga mesin Oracle. Pembeli udah kagak bakal nyasar lagi dah!

Alhamdulillah, kelar juga penjelsan ini! Toko e-commerce Ruby-Oracle kita sekarang otaknya udah makin pinter. Navigasinya mulus, user experience-nya dapet, dan udah siap buat ngedatengin traffic tinggi.

Ibarat kata, rumah udah jadi, perabotan udah komplit, satpam udah jaga di belakang, dan petunjuk jalan buat tamu udah jelas.


Alhamdulillah, nyampe juga kita di puncak gunung, Cing! Kopi seduhan terakhir udah siap belom nih?

Di penjelasan sebelumnya, toko kita di localhost udah komplit banget. Ada etalase, sistem search, WA Checkout, sampe pintu belakang yang digembok satpam. Tapi, sehebat-hebatnya website yang kita bikin, kalo cuma nangkring di laptop ente doang (XAMPP/Localhost), ya kagak bakal ada cuan yang masuk. Alamatnya belom bisa di-crawl sama Mbah Google, dan thumbnail produk ente yang cakep itu kagak bisa di-share ke mana-mana.

Sebelum kita babat proses hosting, mari kita resapi asupan gizi rohani dan intelektual terakhir kita.

Pertama, dari kitab kuning abadi, Diwan Al-Syafi'i karya Imam Syafi'i. Beliau punya satu bait syair yang masyhur banget soal merantau:

"Ma fi maqami lidzi ‘aqlin wa dzi adabin / Min raahatin fada’il awthaana wajtarib."

(Orang yang berakal dan beradab tidak akan menemukan kenyamanan jika hanya berdiam diri di kampung halaman / Maka tinggalkanlah negerimu dan merantaulah).

Kalo ditarik ke dunia coding, website yang ente bikin ini ibarat pemuda beradab yang udah pinter. Dia kagak boleh ngedekem aja di "kampung halaman" (laptop ente). Kodenya kudu merantau, ngelepasin diri ke alam liar internet (Deployment), biar bisa ngasih manfaat dan narik pembeli dari seluruh dunia.

Kedua, ada wejangan keras tapi nyata dari Om Jez Humble di dalem bukunya yang jadi kitab suci para developer, Continuous Delivery:

"Software is only 'done' when it is released to users."

Maksudnya, kodingan ente belom bisa dibilang "selesai" kalo belom dirilis ke tangan user. Mau kodenya sebersih apa, fitur selengkap apa, skor mobile PageSpeed sampe nembus 100 pun, kalo belom live di internet, nilainya masih nol besar. Makanya, neken tombol deploy itu hukumnya fardhu ain buat seorang praktisi digital!

Yuk, kita bahas gambaran besar gimana caranya ngelepas duet maut Ruby dan Oracle ini ke internet!

Merantau ke Internet (VPS & Deployment)

Kalo sebelonnya bikin PHP/Laravel bisa pake hosting cPanel yang murah meriah dan tinggal drag-and-drop, nah Ruby dan Oracle ini beda kelas, Cing. Ini mesin "Sultan". cPanel biasa rata-rata kagak sanggup atau kagak ngasih izin buat nginstal driver Oracle Instant Client.

Jadi, kita kudu sewa tanah kosong dan bangun rumahnya sendiri. Namanya VPS (Virtual Private Server).

1. Beli Kapling Tanah (Sewa VPS)
Langkah pertama, ente kudu nyewa VPS. Bisa pake layanan kayak DigitalOcean, Linode, Vultr, atau AWS. Pilihan sistem operasinya, pake aja Ubuntu Server.
Di dalem Ubuntu ini ntar, ente bakal ngelakuin instalasi sama persis kayak pas ngebangun di laptop:
- Nginstal Ruby (pake RVM atau rbenv).
- Nginstal Oracle Instant Client versi Linux.
- Narik kode Sinatra ente dari GitHub (pake perintah git clone).
2. Ngurusin Gudang Sultan (Database Oracle Cloud)
Nah, Oracle XE itu kan database yang lumayan berat kalo diinstal di VPS biasa. Solusi paling sat-set zaman sekarang adalah pake Oracle Cloud Free Tier.
- Daftar akun Oracle Cloud (gratis selamanya buat kapasitas tertentu).
- Bikin Autonomous Database di sana.
- Dari laptop ente, export data barang yang udah ente masukin pake fitur bawaan Oracle.
- Import data tadi ke Oracle Cloud.
Nanti ente bakal dapet file Wallet buat koneksi. Nah, kodingan OCI8.new di script Ruby ente tinggal diganti alamatnya ngarah ke Oracle Cloud ini.
3. Nyalain Mesin Pelayan 24 Jam (Puma & Nginx)
Kalo di laptop kita nyalain Sinatra pake perintah ruby toko_web.rb, di server beneran kita kagak pake itu. Kita butuh pelayan yang lebih kuat nahan gempuran ribuan pengunjung.
- Kita bakal pake web server khusus Ruby, namanya Puma atau Unicorn.
- Trus di depannya, kita pasang satpam pengatur lalu lintas yang namanya Nginx.
Nginx ini yang bakal nangkep request dari pengunjung di internet, trus dilempar ke mesin Sinatra kita. Konfigurasi Nginx ini juga penting banget buat nge-compress gambar thumbnail dan ngecilin file statis biar skor performance website ente tetep ngacir badai di PageSpeed.
4. Pasang Plang Nama & SSL (Domain & HTTPS)
Terakhir, VPS ente kan alamatnya masih berupa angka (IP Address, misal 192.168.x.x). Ente kudu beli domain (misal: tokosultan-ngacir.com).
- Arahin DNS (A Record) domain ente ke IP Address VPS tadi.
- Ini Fardhu Ain buat SEO: Pasang gembok ijo alias SSL/HTTPS. Di Ubuntu, ente tinggal jalanin alat sakti gratisan namanya Certbot (Let's Encrypt). Kalo website jualan ente kagak pake HTTPS, Mbah Google bakal ngasih peringatan "Not Secure", dan ranking pencarian ente bakal nyungsep di halaman belakang.

JREENGG! TOKO SULTAN RESMI DIBUKA BUAT DUNIA!

Begitu domain ente diakses dari browser HP atau laptop pembeli, etalase yang ditarik dari perut Oracle Cloud bakal nongol dengan gagah. Thumbnail produk ente siap memanjakan mata, kolom pencarian siap melayani filter kilat, dan tombol "🛒 Beli via WhatsApp" siap ngebuka kran cuan yang langsung masuk ke hape ente.

Alhamdulillah, kelar juga penjelasan maraton kita, Cing! Mulai dari ngebongkar fondasi pake ruby-oci8, nulis bahasa SQL DDL & DML, nguasain siklus CRUD utuh, ngeracik tampilan enteng pake Sinatra dan HTML, sampe ngebahas teori ngerilis website ke alam liar Virtual Private Server.

Sebagai web developer dan analis SEO yang biasa bawa nama Raja Digital ID, ane sekarang udah nambah satu senjata rahasia kelas berat di sabuk peralatan ente cing: Kombinasi Elegan Ruby dan Kekuatan Enterprise Oracle.


Ini rangkuman pertanyaan yang paling sering bikin developer garuk-garuk kepala pas lagi asyik ngawinin Ruby sama Oracle.

Sebelum masuk ke daftar pertanyaannya, mari kita ikat dulu ilmu kita pake wejangan dari para sesepuh.

Dari khazanah kitab kuning, ada pepatah mahsyur dari Imam Asy-Syafi'i (sering dikutip di pesantren dalam kitab Ta'lim Muta'allim):

"Al-ilmu shaidun wal kitaabatu qaiduhu. Qayyid shuyuudaka bil-hibaali al-waatsiqati."

(Ilmu itu ibarat hewan buruan, dan tulisan adalah ikatannya. Maka ikatlah buruanmu dengan tali yang kuat).

Kalo ente nemu error pas lagi ngoding Ruby atau nyambungin database Oracle, jangan cuma diinget-inget doang. Catet error-nya, catet solusinya. Error log itu adalah tali pengikat ilmu biar besok-besok kalo kejadian lagi, ente bisa langsung sat-set ngeberesinnya.

Dari dunia software engineering, ada wejangan sakti dari Om Martin Fowler di dalem bukunya, Refactoring: Improving the Design of Existing Code:

"Whenever I have to think to understand what the code is doing, I ask myself if I can refactor the code to make that understanding more immediately apparent."

Maksudnya, kalo ente sendiri puyeng baca kodingan yang ente tulis bulan sebelonnya, berarti kodenya kudu dirapiin (refactor). Kerapian struktur ini pan udah jadi makanan sehari-hari ente. Pas lagi ngoprek daleman XML atau HTML di Blogger demi ngejar skor PageSpeed mobile cepek (100), tiap baris kode kudu punya makna. Nah, nulis script Ruby juga gitu, kudu bersih dan elegan.

Yuk, kita bedah FAQ-nya!

FAQ: Duet Maut Ruby & Oracle "Sultan"

Q1: Bang, ini Ruby pake Sinatra kalo dibandingin sama template Blogger yang biasa ane optimasi buat SEO, menang mana skor PageSpeed-nya?

Pertanyaan bagus, Cing! Gini logikanya: Ruby dan Oracle itu mesin penggerak di belakang layar (backend). Kecepatan narik data dari Oracle pake Ruby itu emang ngacir badai. Tapi, skor PageSpeed di Mbah Google itu tetep 100% dinilai dari tampilan depannya (frontend). Kalo ente ngirim data dari Ruby ke browser tapi HTML/CSS-nya berantakan, render-blocking, atau ukuran file-nya segede gaban, ya tetep bae skor mobile-nya nyungsep. Jadi, mental teliti optimasi HTML yang biasa ente pake di Blogger kudu tetep dibawa pas nulis file .erb di Sinatra.

Q2: Kenapa pas ane jalanin `ruby tes_koneksi.rb`, malah muncul error ORA-12154: TNS:could not resolve the connect identifier specified?

Wah, ini mah penyakit langganannya Oracle, Cing! Error ini artinya jembatan Instant Client ente kagak nemu alamat rumah Oracle-nya.
Solusinya: Cek file yang namanya tnsnames.ora di dalem folder instalasi Oracle ente. Pastiin Service Name (misal: XEPDB1 atau XE) udah tertulis bener di situ, dan format alamat di kodingan Ruby ente (localhost:1521/XEPDB1) udah nyambung alias sama persis.

Q3: Kalo ane mau nambahin fitur upload thumbnail produk, gimana caranya? Biar narik engagement kayak thumbnail video gaming yang biasa ane bikin!

Ide mbois! Thumbnail itu emang ujung tombak konversi. Di Sinatra, ente butuh dua langkah:
1. Di form HTML (tambah_barang.erb), tambahin atribut enctype="multipart/form-data" di tag <form>. Kalo kagak pake ini, gambar kagak bakal bisa nyebrang.
2. Di rute post '/simpan', tangkep file-nya pake params[:gambar][:tempfile], trus save ke dalem folder baru bernama public/images/. Nah, yang disimpen ke database Oracle cukup nama file-nya doang (misal: kaos-mbois.jpg), jangan nyimpen gambar mentah ke dalem Oracle ntar database-nya bisa obesitas!

Q4: Pas ane deploy ke VPS, kenapa website-nya kagak bisa dibuka padahal server Sinatra udah jalan?

Ini biasanya karena masalah port. Secara default, Sinatra jalan di port 4567, sementara browser pengunjung nyarinya di port 80 (HTTP) atau 443 (HTTPS).
Solusinya: Ente kudu ngatur Reverse Proxy pake Nginx (kayak yang disinggung di sebelumnya). Nginx tugasnya nangkep tamu dari pintu depan (port 80), trus digiring ke dalem kamar Sinatra (port 4567) lewat belakang. Jangan lupa juga buka Firewall di VPS ente biar lalu lintasnya kagak mampet.

Q5: Sebelonnya pas ane submit konten ke platform distribusi rasanya ribet kalo banyak settingan manual. Bisa kagak Ruby ini dibikin otomatis ngirim notif ke Telegram kalo ada barang baru?

Bisa banget, Cing! Ruby itu rajanya sat-set buat integrasi API. Ente tinggal panggil fungsi Net::HTTP bawaan Ruby, trus tembak data barang baru ente ke URL API Bot Telegram pas rute post '/simpan' sukses dieksekusi. Jadi workflow manajemen konten ente bisa jalan otomatis tanpa kudu klik-klik manual lagi.

Udah lega pan sekarang, Cing? Semua rintangan dari setup database sultan sampe deployment dan troubleshooting udah kita bahas tuntas tas tas. Selamat ngoprek, moga toko Ruby-Oracle barunya ngacir bawa rezeki!

Baca Juga (Sponsor)