Ruby on Rails — เกิดมาทำไม แก้อะไร ต่างจากชาวบ้านยังไง
“Convention over Configuration — อย่าให้โปรแกรมเมอร์ตัดสินใจในสิ่งที่ไม่จำเป็นต้องตัดสินใจ”
Part 1 — โลกก่อน Rails เป็นยังไง
ย้อนไปปี 2004
สมมติอยากทำเว็บง่ายๆ สักตัว — ระบบ blog ที่ user สร้าง post ได้, comment ได้, มี authentication
ตอนนั้นมีทางเลือกอยู่ไม่กี่ทาง:
ทางเลือกที่ 1 — PHP แบบดิบๆ
<?php
// blog.php
$conn = mysql_connect("localhost", "root", "password");
mysql_select_db("blog");
$result = mysql_query("SELECT * FROM posts ORDER BY created_at DESC");
echo "<html><body>";
while ($row = mysql_fetch_assoc($result)) {
echo "<h2>" . $row['title'] . "</h2>";
echo "<p>" . $row['body'] . "</p>";
// SQL injection? XSS? ช่างมัน...
}
echo "</body></html>";
?>
ปัญหา:
- HTML ปนกับ logic ปนกับ SQL — ทุกอย่างอยู่ในไฟล์เดียวกัน
- ไม่มี structure — แต่ละคนเขียนแต่ละแบบ ไม่มี convention
- Security เป็นศูนย์ — SQL injection, XSS เต็มไปหมด
- Reuse ไม่ได้ — copy-paste กันข้ามไฟล์
ทางเลือกที่ 2 — Java / J2EE
// PostServlet.java
public class PostServlet extends HttpServlet {
protected void doGet(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
// ... 20 บรรทัดแค่ setup connection
}
}
แล้วก็ต้องมี:
web.xml — config servlet mapping
build.xml — config build process
hibernate.cfg.xml — config ORM
struts-config.xml — config MVC framework
applicationContext.xml — config dependency injection
ปัญหา:
- XML hell — config มากกว่า code จริง
- Boilerplate ท่วม — เขียน 100 บรรทัดเพื่อทำสิ่งที่ควรจะใช้แค่ 10 บรรทัด
- Compile-deploy cycle ช้า — แก้ไฟล์ 1 บรรทัด รอ compile 2 นาที
- ต้องตัดสินใจเยอะมาก — ใช้ ORM ตัวไหน? MVC framework ตัวไหน? Build tool อะไร?
ทางเลือกที่ 3 — Perl CGI
#!/usr/bin/perl
print "Content-type: text/html\n\n";
# ... สิ่งที่ไม่มีใครอยากดูแล maintain
ทุกทางเลือกมีปัญหาเดียวกัน: web development ในยุคนั้นช้า เจ็บปวด และซ้ำซาก
Part 2 — Rails เกิดมายังไง
DHH กับ Basecamp
ปี 2003 — David Heinemeier Hansson (DHH) โปรแกรมเมอร์ชาวเดนมาร์กที่ทำงานให้ 37signals (บริษัทเล็กๆ ในชิคาโก) ได้รับมอบหมายให้สร้าง project management tool ชื่อ Basecamp
DHH เลือกใช้ Ruby — ภาษาที่ตอนนั้นแทบไม่มีใครรู้จักนอกญี่ปุ่น เพราะมันเขียนแล้ว “มีความสุข” ตามปรัชญาของ Matz (ผู้สร้าง Ruby) ที่ว่า “optimize for developer happiness”
ระหว่างที่สร้าง Basecamp, DHH เริ่มเห็น pattern ที่ซ้ำๆ:
- ทุก feature ต้อง map database table กับ Ruby object
- ทุก feature ต้อง handle HTTP request → process → render response
- ทุก feature ต้อง validate input, handle errors, redirect
เขาก็เลย extract ส่วนที่ซ้ำๆ ออกมาเป็น framework แล้วปล่อยเป็น open source ในปี 2004
นั่นคือ Ruby on Rails
Rails ไม่ได้เกิดจากทฤษฎี ไม่ได้เกิดจาก research paper มันเกิดจากการสร้างของจริง แล้ว extract pattern ที่ใช้ได้ออกมา
ต้องรู้ Ruby ก่อนมั้ย?
คำตอบตรงๆ: ไม่ต้องรู้ก่อนก็เริ่มได้ แต่ต้องเรียนไปพร้อมกัน
ถ้าเขียน JavaScript / Python / PHP มาก่อน — Ruby อ่านรู้เรื่องเกือบทันที:
# ตัวแปร — ไม่ต้องประกาศ type
name = "Skypart"
age = 25
is_admin = true
# String interpolation — เหมือน JS template literal
greeting = "Hello, #{name}!" # Ruby
# greeting = `Hello, ${name}!` # JS เทียบ
# Array
numbers = [1, 2, 3, 4, 5]
numbers.push(6)
numbers.first # => 1
numbers.last # => 6
numbers.length # => 6
# Hash (เหมือน Object ใน JS, Dict ใน Python)
user = { name: "Skypart", age: 25, role: "admin" }
user[:name] # => "Skypart"
# if/else — ไม่ต้องมีวงเล็บ ไม่ต้องมีปีกกา
if age >= 18
puts "Adult"
else
puts "Minor"
end
# เขียนบรรทัดเดียวก็ได้
puts "Adult" if age >= 18
# Loop
numbers.each do |n|
puts n
end
# เขียนสั้นๆ
numbers.each { |n| puts n }
# Method — ไม่ต้อง return (บรรทัดสุดท้ายคือ return อัตโนมัติ)
def greet(name)
"Hello, #{name}!" # return อัตโนมัติ
end
greet("Skypart") # => "Hello, Skypart!"
# Class
class User
attr_accessor :name, :email # สร้าง getter/setter ให้
def initialize(name, email) # constructor
@name = name # @ = instance variable
@email = email
end
def admin? # method ที่จบด้วย ? return boolean (convention)
@email.end_with?("@admin.com")
end
end
user = User.new("Skypart", "sky@admin.com")
user.name # => "Skypart"
user.admin? # => true
Ruby ที่ใช้ใน Rails จริงๆ 90% คือแค่นี้:
# ส่วนใหญ่เขียนแค่นี้ใน Rails:
# 1. ประกาศ model
class Post < ApplicationRecord
has_many :comments
validates :title, presence: true
end
# 2. query ข้อมูล
Post.where(published: true).order(:created_at)
# 3. if/else ใน controller
if @post.save
redirect_to @post
else
render :new
end
# 4. loop ใน view (ERB)
@posts.each do |post|
# render แต่ละ post
end
ไม่ต้องรู้ metaprogramming ไม่ต้องรู้ monkey patching ไม่ต้องรู้ Ruby ลึก — เริ่ม Rails ก่อน แล้วเรียน Ruby เพิ่มเมื่อต้องการ
Ruby syntax cheat sheet (เทียบกับ JS)
| สิ่งที่ทำ | JavaScript | Ruby |
|---|---|---|
| ประกาศตัวแปร | let x = 1 | x = 1 |
| String interpolation | `Hello ${name}` | "Hello #{name}" |
| Array map | arr.map(x => x * 2) | `arr.map { |
| Array filter | arr.filter(x => x > 3) | `arr.select { |
| Object / Hash | { name: "A" } | { name: "A" } |
| Access property | obj.name | hash[:name] |
| Function | function greet(name) {} | def greet(name) ... end |
| Arrow function | (x) => x * 2 | -> (x) { x * 2 } |
| Console log | console.log("hi") | puts "hi" |
| null | null | nil |
| if condition | if (x > 0) { } | if x > 0 ... end |
| forEach | arr.forEach(x => ...) | `arr.each { |
| Class | class User { } | class User ... end |
| Constructor | constructor(name) {} | def initialize(name) ... end |
| this | this.name | @name |
| Import | import X from 'x' | require 'x' |
แล้ว Ruby เป็น strong type มั้ย?
Ruby เป็น dynamically typed + strongly typed
ฟังดูขัดกัน แต่ 2 คำนี้คนละเรื่อง:
Weakly Typed Strongly Typed
(แปลง type ให้เอง) (ไม่แปลงให้ ต้องชัดเจน)
┌─────────────────┐ ┌─────────────────┐
Dynamically Typed │ JavaScript │ │ Ruby │
(ไม่ต้องประกาศ type) │ PHP │ │ Python │
└─────────────────┘ └─────────────────┘
Statically Typed │ C (บางกรณี) │ │ Java │
(ต้องประกาศ type) │ │ │ TypeScript │
└─────────────────┘ │ Swift │
│ Go │
└─────────────────┘
Dynamically typed = ไม่ต้องประกาศ type ตัวแปรเปลี่ยน type ได้ตลอด:
x = 1 # x เป็น Integer
x = "hello" # x เป็น String แล้ว — ไม่ error
Strongly typed = ไม่แปลง type ให้อัตโนมัติ ถ้า type ไม่ตรงก็ error:
# Ruby — strongly typed: ไม่แปลงให้
"age: " + 25 # TypeError! String + Integer ไม่ได้
"age: " + 25.to_s # ต้องแปลงเอง → "age: 25"
1 + "2" # TypeError!
1 + "2".to_i # ต้องแปลงเอง → 3
// JavaScript — weakly typed: แปลงให้เงียบๆ
"age: " + 25 // "age: 25" — JS แปลง 25 เป็น string ให้
1 + "2" // "12" — อ้าว! ได้ string ไม่ใช่ 3
// นี่คือที่มาของ meme "JavaScript is weird"
สรุป:
- Ruby ไม่มี TypeScript ไม่มี type annotation — ไม่ต้องเขียน
name: string - แต่ Ruby ไม่แปลง type มั่วเหมือน JS — ถ้า type ไม่ตรงมัน error ชัดเจน
- ไม่มี compile time error (เพราะ dynamic) แต่มี runtime error ถ้า type ผิด
แล้วถ้าอยาก type safety มากขึ้นล่ะ?
Ruby มี Sorbet (by Stripe) และ RBS (official) สำหรับเพิ่ม type checking:
# ปกติ — ไม่มี type
def greet(name)
"Hello, #{name}!"
end
# ใช้ Sorbet — เพิ่ม type annotation (optional)
sig { params(name: String).returns(String) }
def greet(name)
"Hello, #{name}!"
end
แต่ส่วนใหญ่ Rails community ไม่ใช้ type checker — ใช้ test แทน ปรัชญาคือ “เขียน test ดีกว่าประกาศ type”
สรุป: ถ้าเขียน JS/Python/PHP ได้ — Ruby อ่านรู้เรื่องใน 30 นาที ไม่ต้องเรียน Ruby course ก่อน เริ่ม Rails เลยแล้วค่อยเรียน Ruby ไปพร้อมกัน
Part 3 — Rails แก้อะไร
ปรัชญาหลัก 2 ข้อ
1. Convention over Configuration
แทนที่จะให้โปรแกรมเมอร์ตั้ง config ทุกอย่าง — Rails ตั้ง default ที่สมเหตุสมผลให้หมด
ก่อน Rails (Java-style):
<!-- ต้อง config ว่า class Post map กับ table ไหน -->
<hibernate-mapping>
<class name="com.blog.model.Post" table="posts">
<id name="id" column="id">
<generator class="native"/>
</id>
<property name="title" column="title" type="string"/>
<property name="body" column="body" type="text"/>
</class>
</hibernate-mapping>
Rails:
class Post < ApplicationRecord
# แค่นี้จบ
# Rails รู้เองว่า:
# - class Post → table ชื่อ "posts" (พหูพจน์อัตโนมัติ)
# - column ใน table → กลายเป็น attribute อัตโนมัติ
# - primary key คือ "id"
end
Convention ที่ Rails ตั้งไว้:
- Model ชื่อ
Post→ table ชื่อposts - Model ชื่อ
Person→ table ชื่อpeople(รู้จัก irregular plural!) - Controller ชื่อ
PostsController→ อยู่ในไฟล์posts_controller.rb - View สำหรับ
PostsController#index→ อยู่ที่app/views/posts/index.html.erb
ทุกอย่างมี “ที่ของมัน” ถ้าทำตาม convention — ไม่ต้อง config อะไรเลย
2. DRY — Don’t Repeat Yourself
ทุก piece of knowledge ควรมี single, unambiguous representation ในระบบ
ก่อน Rails:
1. สร้าง table ใน database
2. เขียน class ใน code ที่ mirror structure ของ table
3. เขียน mapping file ที่บอกว่า class map กับ table ยังไง
4. เขียน SQL query สำหรับ CRUD แต่ละตัว
Rails:
1. เขียน migration สร้าง table
2. จบ — Rails จัดการที่เหลือให้
Part 4 — Rails ต่างจากอันอื่นยังไง
เทียบกัน: สร้าง Blog CRUD
Django (Python)
# models.py
class Post(models.Model):
title = models.CharField(max_length=200)
body = models.TextField()
created_at = models.DateTimeField(auto_now_add=True)
# views.py
def post_list(request):
posts = Post.objects.all()
return render(request, 'blog/post_list.html', {'posts': posts})
# urls.py
urlpatterns = [
path('posts/', views.post_list, name='post_list'),
]
Django ใกล้เคียง Rails มากที่สุด (ได้แรงบันดาลใจจาก Rails ด้วยซ้ำ) แต่ต่างกันตรง:
- Django explicit กว่า — ต้องประกาศ field ใน model เอง
- Django ใช้ “explicit is better than implicit” (ตาม Zen of Python)
- Rails ใช้ “convention ดีกว่า config” — ประกาศน้อยกว่า magic เยอะกว่า
Express.js (Node.js)
// ไม่มี ORM มาให้ ต้องเลือกเอง (Sequelize? Mongoose? Prisma?)
// ไม่มี project structure มาให้ ต้องออกแบบเอง
// ไม่มี convention — ทุกอย่างคือทางเลือก
const express = require('express');
const app = express();
app.get('/posts', async (req, res) => {
// ORM ตัวไหน? query ยังไง? ขึ้นอยู่กับว่าเลือกอะไร
const posts = await Post.findAll();
res.json(posts);
});
Express.js เป็น un-opinionated framework — ให้อิสระเต็มที่ แต่ต้องตัดสินใจทุกอย่างเอง:
- Folder structure?
- ORM?
- Authentication library?
- Validation?
Rails เป็น opinionated framework — “ฉันตัดสินใจให้แล้ว ถ้าเชื่อฉัน มันจะเร็วมาก”
Spring Boot (Java)
@Entity
public class Post {
@Id @GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String title;
private String body;
// + getter, setter, constructor อีก 40 บรรทัด
}
@RestController
@RequestMapping("/posts")
public class PostController {
@Autowired
private PostRepository repository;
@GetMapping
public List<Post> index() {
return repository.findAll();
}
}
Spring Boot ดีขึ้นมากจาก J2EE แต่ยังคง verbose กว่า Rails หลายเท่า และ annotation hell แทน XML hell
Part 5 — ข้อเสียและข้อจำกัด
Rails ไม่ได้สมบูรณ์แบบ ต้องรู้ข้อจำกัดด้วย:
1. Performance
Ruby ช้ากว่า Go, Rust, Java ในแง่ raw throughput หลายเท่า ถ้าต้อง handle request เป็นแสนต่อวินาที Rails อาจไม่ใช่คำตอบ
แต่สำหรับ app ส่วนใหญ่ — bottleneck อยู่ที่ database query ไม่ใช่ภาษา Rails ก็เร็วพอ
มาดู context เพิ่มเติม:
- Benchmark ไม่เท่ากับ real-world performance — ในโลกจริง web app ส่วนใหญ่ใช้เวลา 80-90% ไปกับ I/O (database, API calls, file system) ไม่ใช่ CPU computation ดังนั้นภาษาจะเร็วขนาดไหนก็ไม่ช่วยถ้า query ช้า
- Ruby 3.x เร็วขึ้นมากจาก Ruby 2.x — project YJIT (Just-In-Time compiler ที่ Shopify สร้าง) ทำให้ Ruby เร็วขึ้น 15-30% ใน production workload จริงๆ และยังปรับปรุงต่อเนื่อง
- Horizontal scaling ทำได้ — ถ้า traffic เพิ่ม ก็เพิ่ม server/container ได้ Shopify รับ traffic มหาศาลด้วย Rails (รวมถึง Black Friday/Cyber Monday) โดยใช้ horizontal scaling
- ถ้า bottleneck จริงๆ อยู่ที่ Ruby — สามารถ extract ส่วนที่ performance-critical ออกไปเป็น microservice ที่เขียนด้วย Go/Rust ได้ ไม่จำเป็นต้อง rewrite ทั้ง app
- เทียบง่ายๆ: ถ้า app มี user หลักพัน-หลักหมื่นต่อวัน Rails เร็วเหลือเฟือ ถ้ามี user หลักแสน-หลักล้าน ก็ยัง handle ได้ด้วย caching + scaling ที่ดี ถ้าต้อง handle request เป็นล้านต่อวินาที ค่อยมาคิดเรื่องเปลี่ยนภาษา
2. Magic มากเกินไป
Convention ที่เยอะ = สิ่งที่เกิดขึ้น “โดยไม่รู้ตัว” ก็เยอะ
# ทำไม Post.find_by_title("Hello") ถึงใช้ได้?
# method นี้ไม่ได้ถูก define ตรงไหนเลย
# → Rails สร้างให้อัตโนมัติจาก column name ด้วย method_missing
สำหรับมือใหม่ magic เยอะ = เข้าใจยากว่าเบื้องหลังเกิดอะไรขึ้น
ลองดูตัวอย่าง magic ที่มักจะทำให้งง:
- ActiveRecord callbacks —
before_save,after_create,after_commitฯลฯ สามารถ trigger chain reaction ที่ตามยาก ถ้า model มี callback ซ้อนกัน 3-4 ชั้น debug ยากมาก เพราะ “ใครเรียกอันนี้?” ตอบไม่ได้โดยดูจาก code ตรงๆ - Autoloading — Rails โหลด class ให้อัตโนมัติตาม file path/naming convention ซึ่งส่วนใหญ่สะดวกดี แต่พอ naming ไม่ตรง convention มันจะ fail แบบ error message ไม่ค่อยช่วย (เช่น
NameError: uninitialized constantทั้งที่ไฟล์อยู่ตรงนั้น) - Implicit rendering — Controller action ที่ไม่มี
renderจะ render view ที่ชื่อตรงกับ action อัตโนมัติ สะดวกเมื่อรู้ convention แต่มือใหม่จะงงว่า “HTML มาจากไหน?” - Concern / Module include — การใช้
includeหรือextendทำให้ method “โผล่มาจากไหนไม่รู้” ใน model ที่ใหญ่ๆ มี concern เยอะๆ การหาว่า method นึงมาจากไหน ต้อง grep ข้าม 5-6 ไฟล์
วิธีรับมือ: อ่าน Rails Guides ให้เข้าใจ convention ก่อน อย่าเดา เพราะถ้าเดาผิด debug ยาก แต่ถ้าเข้าใจ convention แล้ว magic เหล่านี้จะกลายเป็น productivity boost
3. Monolith by default
Rails ถูกออกแบบมาเป็น monolithic application ถ้าทีมโตมาก หรือต้อง scale แต่ละส่วนแยกกัน จะต้อง break ออกเป็น service ซึ่งไม่ใช่จุดแข็งของ Rails
(แต่ DHH ก็ argue ว่า monolith ดีสำหรับทีมส่วนใหญ่ — และ Shopify ก็ยังเป็น Rails monolith ที่ใหญ่ที่สุดในโลก)
เรื่องนี้มี nuance เยอะ:
- Monolith ไม่ได้แปลว่า “แย่” — สำหรับทีม 1-30 คน monolith มักจะเป็นทางเลือกที่ดีที่สุด deploy ง่าย, debug ง่าย, ไม่ต้องจัดการ service communication
- ปัญหาเกิดเมื่อ monolith โตเกินไป — เมื่อ codebase มี model เป็นร้อย, ทีมมีคนเป็นสิบๆ ทีม การ deploy ครั้งนึงกระทบทั้ง app test suite รันนานเป็นชั่วโมง merge conflict เยอะ
- Shopify แก้ปัญหานี้ด้วย “modular monolith” — แทนที่จะแตกเป็น microservices ก็แบ่ง monolith เป็น component ที่มี boundary ชัดเจน ใช้ gem ชื่อ
packwerkในการ enforce boundaries ระหว่าง module - ถ้าต้อง microservices จริงๆ — Rails ทำ API-only mode ได้ดี (
rails new my_api --api) แต่ถ้าทั้งระบบเป็น microservices เยอะๆ อาจมี framework ที่เหมาะกว่า เช่น Go สำหรับ service ที่ต้องเบาและเร็ว
4. Hiring pool เล็กลง
JavaScript/TypeScript ครองตลาด Python มี AI hype — คน Ruby หายากขึ้นเรื่อยๆ ในบางตลาด
แต่ต้องมองหลายมุม:
- คน Ruby น้อยกว่า แต่คุณภาพมักจะสูง — เพราะคนที่ยังเขียน Ruby อยู่ในปี 2026 มักจะเป็นคนที่เลือกเอง ไม่ใช่เขียนเพราะ “ทุกคนเขียน” เหมือน JavaScript ทำให้ average skill level ของ Ruby developer ค่อนข้างสูง
- เงินเดือน Ruby developer มักจะสูง — เพราะ supply น้อย demand ยังมี ทำให้ salary range สูงกว่า average web developer
- ในบางประเทศ/ตลาดหายากจริงๆ — โดยเฉพาะในเอเชียตะวันออกเฉียงใต้ (ยกเว้นญี่ปุ่น) การหา Ruby developer อาจยากกว่าหา Node.js/Python developer หลายเท่า
- Onboarding คนจากภาษาอื่นไม่ยาก — ถ้า developer เขียน Python/JS มาก่อน สามารถเรียน Ruby/Rails ได้ใน 2-4 สัปดาห์ ดังนั้นไม่จำเป็นต้องหาคนที่ “เขียน Ruby มาก่อน” เสมอไป
5. Ecosystem เล็กกว่า JavaScript/Python
- npm มี package เป็นล้าน RubyGems มีประมาณ 170,000+ — น้อยกว่าหลายเท่า แต่ gem หลักๆ ที่ต้องใช้มีครบ (authentication, authorization, file upload, payment, search ฯลฯ)
- AI/ML ecosystem แทบไม่มี — ถ้าต้องทำ machine learning, data science, AI — Python ชนะขาด Ruby ไม่มี library ระดับ TensorFlow, PyTorch, pandas
- Frontend tooling เปลี่ยนเร็ว — Rails เคยมี asset pipeline ของตัวเอง (Sprockets) แล้วย้ายมา Webpacker แล้วก็เปลี่ยนอีก (importmap, jsbundling, cssbundling) ทำให้เรื่อง frontend tooling ใน Rails มีความสับสนเวลาอ่าน tutorial เก่าๆ
Part 6 — แล้วใครใช้ Rails อยู่
Rails ไม่ได้ตาย — หลายบริษัทใหญ่ยังใช้อยู่:
- GitHub — ใช้ Rails ตั้งแต่วันแรก ยังใช้อยู่ เป็น platform ที่ developer ทั่วโลกใช้ทุกวัน handle repository หลายร้อยล้าน, pull requests, issues, actions ทั้งหมดบน Rails
- Shopify — Rails monolith ที่ใหญ่ที่สุดในโลก ทำ e-commerce platform ที่ร้านค้าหลายล้านร้านใช้ รวมถึง handle Black Friday traffic มหาศาล ทีม Shopify ยังเป็นผู้สร้าง YJIT (Ruby JIT compiler) ที่ทำให้ Ruby เร็วขึ้นอย่างมีนัยสำคัญ
- Basecamp / HEY — ผลิตภัณฑ์ของ DHH เอง Basecamp เป็น project management tool, HEY เป็น email service ทั้งสองเป็น showcase ว่า Rails ทำอะไรได้ด้วยทีมเล็ก
- Airbnb — เริ่มต้นด้วย Rails (ส่วนใหญ่ยังเป็น Rails อยู่) ใช้ Rails เป็น core backend สำหรับ booking system, search, host management ส่วน frontend ค่อยๆ ย้ายไป React แต่ backend ยังเป็น Rails
- Coinbase — ใช้ Rails เป็น core สำหรับ crypto exchange platform ที่ handle เงินหลายพันล้านดอลลาร์ แสดงให้เห็นว่า Rails ใช้กับ fintech ที่ต้อง security สูงได้
- Stripe — API dashboard สร้างด้วย Rails ทีม Stripe ยังเป็นผู้สร้าง Sorbet (Ruby type checker) ด้วย
- Twitch — backend ของ Twitch ช่วงแรกสร้างด้วย Rails ก่อนที่จะค่อยๆ migrate บางส่วนไป Go/Java เพื่อ handle real-time streaming traffic แต่ Rails เป็นจุดเริ่มต้นที่ทำให้ Twitch ship ได้เร็ว
- Kickstarter — crowdfunding platform ที่ใช้ Rails ตั้งแต่ต้น handle campaign pages, payment processing, backer management ทั้งหมดบน Rails
- Zendesk — customer support platform ที่ใช้ Rails เป็น core backend รองรับลูกค้าองค์กรขนาดใหญ่ทั่วโลก
- Dribbble — community platform สำหรับ designer ใช้ Rails ในการจัดการ portfolio, shot uploads, hiring board
- Hulu — streaming platform ที่เริ่มต้นด้วย Rails สำหรับ content management, user accounts, subscription system ก่อนที่จะ scale บางส่วนออกไป
สิ่งที่น่าสังเกตคือ — หลายบริษัทที่ “เริ่มต้นด้วย Rails” แล้ว scale จนใหญ่มาก บางส่วนอาจ migrate ออกไปใช้ภาษาอื่นสำหรับ service ที่ต้อง performance สูงเป็นพิเศษ แต่ core ยังเป็น Rails อยู่ นี่พิสูจน์ว่า Rails เหมาะเป็นจุดเริ่มต้นที่ดีเยี่ยม — ship เร็ว, iterate เร็ว, แล้วค่อย optimize ทีหลังเมื่อจำเป็นจริงๆ
Part 7 — สรุป: Rails เหมาะกับอะไร
| เหมาะ | ไม่เหมาะ |
|---|---|
| Web app ทั่วไป (CRUD-heavy) | Real-time system ที่ต้อง ultra-low latency |
| Startup ที่ต้อง ship เร็ว | CPU-intensive computation |
| Solo developer / ทีมเล็ก | Microservices architecture ตั้งแต่วันแรก |
| Prototype / MVP | Mobile app backend ที่เป็น pure API (อาจลองดู API-only mode) |
| Content-heavy site | System programming |
แก่นแท้ของ Rails
Rails เกิดมาจากคำถามเดียว:
“ทำไม web development ถึงต้องเจ็บปวดขนาดนี้?”
คำตอบของ DHH คือ: มันไม่จำเป็นต้องเจ็บปวด ถ้าเรา:
- ตั้ง convention ที่ดี แทนที่จะให้ทุกคนตัดสินใจเอง
- ลด boilerplate ให้เหลือแต่ code ที่มีความหมาย
- ให้ทุกอย่างที่ต้องใช้มากับ framework แทนที่จะให้ไปหาเอง
- ทำให้โปรแกรมเมอร์มีความสุข — เพราะคนที่มีความสุขเขียน code ได้ดีกว่า
ไม่ว่าจะใช้ Rails หรือไม่ — แนวคิดพวกนี้เปลี่ยน web development ไปตลอดกาล ทุกวันนี้ทุก framework ได้รับอิทธิพลจาก Rails ไม่ทางใดก็ทางหนึ่ง Django, Laravel, Phoenix, Adonis, Next.js — ล้วนยืมแนวคิดจาก Rails ทั้งนั้น
“The best frameworks aren’t designed — they’re extracted.” — David Heinemeier Hansson
ต่อไป: Part 2: Rails ทำงานยังไง → — เจาะลึก rendering model, Hotwire, ERB, CSS, deploy