- vừa được xem lúc

Các kỹ thuật nâng cao trong Ruby on Rails dành cho **Senior Developer**.

0 0 5

Người đăng: Hoang Minh Dai

Theo Viblo Asia

1. Hiệu suất và tối ưu hóa

1.1. Tránh N+1 Query với Eager Loading

Nếu không dùng eager loading, Rails sẽ chạy N+1 query khi truy vấn dữ liệu có liên kết.

Ví dụ:

# N+1 Query (Không tối ưu)
users = User.all
users.each do |user| puts user.posts.count # Mỗi lần gọi .posts.count sẽ thực hiện một truy vấn SQL riêng
end

Giả sử có 100 users, điều này sẽ chạy 1 truy vấn lấy users + 100 truy vấn lấy posts.

🔹 Giải pháp: Dùng includes để eager load dữ liệu.

# Tối ưu hóa với Eager Loading
users = User.includes(:posts).all
users.each do |user| puts user.posts.count # Không truy vấn SQL lặp lại
end

Rails sẽ chỉ chạy 2 query:

  1. Lấy tất cả users
  2. Lấy tất cả posts liên quan

Bạn có thể dùng Bullet gem để phát hiện lỗi N+1:

# Gemfile
gem 'bullet', group: :development

Sau đó, cấu hình Bullet để log cảnh báo:

# config/environments/development.rb
config.after_initialize do Bullet.enable = true Bullet.alert = true Bullet.bullet_logger = true
end

1.2. Caching nâng cao

Cache Fragment (Lưu trữ từng phần HTML)

<% cache @user do %> <%= @user.name %> <%= @user.bio %>
<% end %>

Rails sẽ lưu kết quả vào cache để không cần truy vấn lại DB nếu dữ liệu chưa thay đổi.

Low-level Caching (Lưu trữ dữ liệu trong bộ nhớ)

Rails.cache.fetch("top_articles", expires_in: 1.hour) do Article.order(views: :desc).limit(10)
end

🔹 Redis cache được dùng để lưu trữ dữ liệu nhanh hơn:

# Cấu hình Redis
config.cache_store = :redis_cache_store, { url: "redis://localhost:6379/0" }

2. Cấu trúc dự án và kiến trúc phần mềm

2.1. Service Objects (Tách logic ra khỏi Model & Controller)

Trước đây (Viết hết trong Controller - Code lộn xộn)

class UsersController < ApplicationController def create @user = User.new(user_params) if @user.save UserMailer.welcome_email(@user).deliver_later redirect_to @user else render :new end end
end

🔹 Tối ưu với Service Object:

# app/services/user_creator.rb
class UserCreator def initialize(user_params) @user_params = user_params end def call user = User.create(@user_params) UserMailer.welcome_email(user).deliver_later if user.persisted? user end
end

Controller gọi service:

class UsersController < ApplicationController def create @user = UserCreator.new(user_params).call if @user.persisted? redirect_to @user else render :new end end
end

2.2. Query Objects (Tách truy vấn phức tạp ra khỏi Model)

Thay vì viết query dài trong Model:

class User < ApplicationRecord scope :active, -> { where(active: true) }
end

Dùng Query Object để quản lý:

# app/queries/active_users_query.rb
class ActiveUsersQuery def initialize(relation = User.all) @relation = relation end def call @relation.where(active: true) end
end

Gọi như sau:

users = ActiveUsersQuery.new.call

3. API và GraphQL

3.1. GraphQL API

Dùng graphql-ruby để định nghĩa API linh hoạt hơn REST.

Tạo một query:

class Types::QueryType < Types::BaseObject field :user, Types::UserType, null: false do argument :id, ID, required: true end def user(id:) User.find(id) end
end

Gọi API:

query { user(id: 1) { id name email }
}

4. Bảo mật nâng cao

4.1. Rate Limiting (Giới hạn số request tránh DDoS)

Sử dụng Rack::Attack để giới hạn request:

class Rack::Attack throttle("req/ip", limit: 100, period: 1.minute) do |req| req.ip end
end

5. Tối ưu Active Record

5.1. Partitioning Tables

Chia bảng theo tháng giúp truy vấn nhanh hơn.

CREATE TABLE orders ( id SERIAL PRIMARY KEY, created_at TIMESTAMP NOT NULL
) PARTITION BY RANGE (created_at);

Tạo bảng con cho từng tháng:

CREATE TABLE orders_2025_03 PARTITION OF orders
FOR VALUES FROM ('2025-03-01') TO ('2025-04-01');

6. Quản lý công việc lớn và batch processing

6.1. Batch Processing với Sidekiq

Dùng Sidekiq để xử lý job nặng:

class ImportCsvJob include Sidekiq::Worker def perform(csv_file_path) CSV.foreach(csv_file_path, headers: true) do |row| User.create!(row.to_h) end end
end

Gọi job từ controller:

ImportCsvJob.perform_async("/path/to/file.csv")

7. DevOps và CI/CD

7.1. Dockerizing Rails

Tạo Dockerfile để deploy Rails app:

FROM ruby:3.2
WORKDIR /app
COPY . .
RUN bundle install
CMD ["rails", "server"]

Chạy app với Docker Compose:

version: "3"
services: web: build: . ports: - "3000:3000"

8. WebSockets và Real-time Features

8.1. ActionCable (Realtime Chat)

Rails hỗ trợ WebSockets với ActionCable:

class ChatChannel < ApplicationCable::Channel def subscribed stream_from "chat_#{params[:room]}" end
end

Frontend kết nối WebSocket:

App.cable.subscriptions.create({ channel: "ChatChannel", room: "general" }, { received(data) { console.log(data); }
});

Tóm tắt

✅ Tránh N+1 query với Eager Loading
✅ Sử dụng Service ObjectQuery Object
✅ Tăng tốc API với GraphQLRedis cache
✅ Bảo mật với JWT, Rate Limiting
✅ Dùng Sidekiq, Docker, WebSockets cho hiệu suất cao

Bình luận

Bài viết tương tự

- vừa được xem lúc

Tôi cá là bạn không biết những điều này - Ruby on rails ( Phần 2)

Các bạn có thể theo dõi phần 1 ở đây :. https://viblo.asia/p/toi-ca-la-ban-khong-biet-nhung-dieu-nay-ruby-on-rails-phan-1-WAyK8DDeKxX. 5.

0 0 231

- vừa được xem lúc

Rails Memoization

Memoization is a process that can be used to speed up rails methods. It caches the results of methods that do time-consuming work, work that only needs to be done once. Here is an example. Example.

0 0 48

- vừa được xem lúc

Tại sao Rails lại dùng cả Webpack lẫn Sprocket?

Khi Rails 6 được ra mắt, có thể bạn đã từng tự hỏi. WTF, sao Webpack đã được add vào rồi, mà Sprocket vẫn tồn tại thế kia . Chẳng phải Webpack và Sprocket được dùng để giải quyết chung một công việc hay sao. Hoặc cả đây:.

0 0 60

- vừa được xem lúc

Bạn nên sử dụng Elasticsearch trong ứng dụng Ruby On Rails như thế nào?

Elasticsearch là một công cụ phân tích và mã nguồn mở mạnh mẽ và linh hoạt, phân tán, theo thời gian thực. Đó là tiêu chuẩn vàng trong công nghệ tìm kiếm.

0 0 81

- vừa được xem lúc

Form object pattern trong rails

1.Mở đầu.

0 0 113

- vừa được xem lúc

Sử dụng Twilio để gửi SMS trong ứng dụng Ruby on Rails

Ngoài cách xác nhận tài khoản hay gửi thông báo bằng email thì hôm nay mình sẽ hướng dẫn các bạn 1 cách nữa là thông qua SMS/Voice. Công cụ sử dụng sẽ là gem Twilio. Installation. Để cài đặt bằng Bundler, hãy lấy phiên bản mới nhất:.

0 0 67