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

Bí Mật Của Block, Proc và Lambda Trong Ruby on Rails – Hiểu Rõ Làm Chủ Code!

0 0 2

Người đăng: son vu

Theo Viblo Asia

Ruby không chỉ nổi tiếng bởi cú pháp “thơ văn” mà còn vì khả năng xử lý code dưới dạng khối (block of code) cực kỳ linh hoạt. Trong thế giới Ruby on Rails, nếu bạn từng gặp yield, proc, hoặc lambda mà chưa thực sự hiểu sự khác biệt giữa chúng – thì bài viết này dành cho bạn. Screenshot 2025-06-24 at 00.48.13.png

I. Block, Proc và Lambda là gì?

1. Block

Block là một đoạn code có thể được truyền vào một method nhưng không phải là đối tượng (object). Ruby hỗ trợ hai dạng block:

# Dạng do...end
[1, 2, 3].each do |num| puts num
end # Dạng ngoặc {}
[1, 2, 3].each { |num| puts num } 

Bạn thường thấy block đi kèm với yield trong method:

def say_hello puts "Hello" yield if block_given? puts "Bye"
end say_hello { puts "I'm a block" }

2. Proc

Proc là đối tượng của class Proc, là một object đại diện cho một đoạn mã (block) có thể được lưu trữ vào biến, truyền như tham số, và gọi thực thi nhiều lần.

my_proc = Proc.new { |name| puts "Hello #{name}" }
my_proc.call("Ruby") # => Hello Ruby

Đặc điểm:

  • Không kiểm tra số lượng tham số (argument).
  • Có thể được gọi bằng .call, .[], hoặc .()
Proc.new { |x, y| puts "#{x}, #{y}" }.call(1) # => "1, " (Không lỗi, thiếu biến y => nil)

return trong Proc sẽ thoát khỏi method bên ngoài, điều này có thể gây bất ngờ:

def test_proc my_proc = Proc.new { return "From Proc" } my_proc.call return "After Proc"
end puts test_proc
# => "From Proc"

Sử dụng:

Gọi proc với 1 giá trị

proc.call(2)

Gọi proc với 1 array

proc = Proc.new { |x| puts "Giá trị là #{x}" } [1, 2, 3].each(&proc)
# => Giá trị là 1
# => Giá trị là 2
# => Giá trị là 3

Dùng symbol to proc: &:method_name

Ký hiệu & chuyển một symbol thành một proc object và truyền nó vào như một block

[1, 2, 3].map(&:to_s)
# tương đương với:
[1, 2, 3].map { |i| i.to_s }

Truyền proc như callback hay logic tái sử dụng

upcase_proc = Proc.new { |str| str.upcase } def process_strings(arr, proc) arr.map(&proc)
end puts process_strings(["a", "b", "c"], upcase_proc)
# => ["A", "B", "C"]

3. Lambda

  • Lambda là một function và không có tên cụ thể
  • Nó có thể được sử dụng để gán 1 đoạn code
  • là một object
# Cách 1: Dùng từ khóa lambda
my_lambda = lambda { |x| puts "Hello #{x}" }
my_lambda.call("Rails") # Hello Rails # Cách 2: Dùng dấu chấm -> (ngắn gọn hơn)
my_lambda = ->(x) { puts "Hello #{x}" } # Cách 3: Với nhiều dòng
my_lambda = ->(x, y) do puts "x + y = #{x + y}"
end

Lambda giống Proc, nhưng nghiêm khắc hơn về số lượng tham số. Nó hoạt động như một method thực thụ.

my_lambda = -> (x, y) { puts x + y }
my_lambda.call(2, 3) # => 5 my_lambda.call(1) # ArgumentError

Một điểm khác biệt nữa: return trong lambda chỉ thoát khỏi lambda, trong khi return trong Proc thoát cả method chứa nó:

def test_lambda lam = lambda { return "Thoát khỏi lambda" } lam.call return "Thoát khỏi method"
end puts test_lambda # 👉 Output: "Thoát khỏi method"

Một vài ứng dụng thực tế vào trong rails:

# Trong callback hoặc validation
validate -> { errors.add(:base, "Custom error") if some_condition } # Trong scope của ActiveRecord
class Post < ApplicationRecord scope :published, -> { where(published: true) } scope :by_author, ->(author_id) { where(author_id: author_id) }
end Post.published
Post.by_author(1)

II. So Sánh Nhanh: Block vs Proc vs Lambda

Screenshot 2025-06-24 at 01.25.42.png

III . Kết Luận

  • Dùng block khi bạn chỉ cần truyền một đoạn code đơn giản vào method.
  • Dùng proc khi bạn muốn lưu trữ khối code linh hoạt, ít ràng buộc.
  • Dùng lambda khi bạn muốn kiểm soát chặt chẽ số lượng tham số và hành vi return.

Hiểu rõ ba khái niệm này sẽ giúp bạn viết code Ruby/Rails sạch hơn, rõ ràng hơn – và đặc biệt là tránh được những lỗi "khó nhằn" khi làm việc với callback, scope, hay bất kỳ DSL nào của Rails

Tài liệu tham khảo:

https://ruby-doc.org/core-2.6.1/Proc.html

https://viblo.asia/p/block-proc-va-lambda-trong-ruby-jaqG0lQQGEKw#_2-proc-2

Bình luận

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

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

Bài toán tìm đường đi ngắn nhất với giải thuật Dijkstra

Với các bạn sinh viên chuyên ngành công nghệ thông tin, chắc không lạ gì với bài toán tìm đường đi ngắn nhất (Shortest Path Problems) trong đồ thị trọng số nữa. Ở bài viết lần này, mình sẽ làm 3 việc:.

0 0 148

- 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 236

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

Những thay đổi trong ruby 3.0

. 2020 là một năm lớn đối với cộng đồng Ruby. Những người sáng lập Ruby có một món quà thực sự tuyệt vời cho chúng ta vào giáng sinh với việc phát hành Ruby 3.

0 0 61

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

Có gì đặc biệt trong phiên bản Ruby 3x3 ?

Hello guys, chắc hẳn thời gian vừa rồi chúng ta cũng đã nghe qua thông tin Ruby sắp cho ra mắt Ruby version 3, hay còn được gọi là ruby 3x3, vậy liệu Ruby version 3 này có gì mới, và có những update nào đáng phải kể đến, và tại sao mọi người lại gọi nó là ruby version 3x3, thì trong bài ngày hôm nay

0 0 51

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

Cách sử dụng class Time & Date trong Ruby (Phần 1)

Time là một class trong Ruby, nó sẽ giúp chỉnh sửa format, trích xuất thông tin một cách hiệu quả theo ý của bạn. . Topic hôm nay chúng ta có gì nào. .

0 0 109

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

Ruby 3.0 có gì mới

Ruby 3.0.0 đã được ra mới được ra mắt vào tháng 12/2020, mục tiêu của bản 3.0.

0 0 51