[Có thể bạn chưa biết?] Một vài cách viết ngắn gọn trong Ruby on Rails (phần 1)
Lời nói đầu Thực tế thì những người mới bắt đầu code Ruby sẽ đi theo xu hướng viết "đầy đủ". Theo cái cách tương đối "dài dòng" như các ngôn ngữ họ đã tiếp xúc trước đó, mà không biết rằng có thể viết chúng ngắn gọn hơn với các Syntax Ruby được định nghĩa lên. Bài viết này sẽ tổng hợp 1 vài ...
Lời nói đầu
Thực tế thì những người mới bắt đầu code Ruby sẽ đi theo xu hướng viết "đầy đủ". Theo cái cách tương đối "dài dòng" như các ngôn ngữ họ đã tiếp xúc trước đó, mà không biết rằng có thể viết chúng ngắn gọn hơn với các Syntax Ruby được định nghĩa lên. Bài viết này sẽ tổng hợp 1 vài cách viết ngắn gọn các method trong Ruby on Rails, giúp đoạn code của bạn sẽ ngắn gọn và có vẻ "Pro" hơn phần nào đó. Nào giờ thì chúng ta lên đường ^^
Let's go
Chúng ta sẽ đi từ cái đơn giản nhất, ai cũng biết đến cái không phải ai cũng biết nhé =))
Giảm số dòng code với mệnh đề If
Có quen thuộc quá không?
if user.active? send_mail_to(user) end
send_mail_to(user) if user.active?
Thay thế if + not (!if) bằng unless
Cái này có vẻ ở đâu cũng thế nhỉ =))
user.destroy if !user.active?
user.destroy unless user.active?
Note: Tuy nhiên, nếu các mệnh đề sau If + not khi được kết nối bởi các toán tử && hoặc ||. Thì việc biến đổi sử dụng unless ở đây vô hình chung lại phản tác dụng, và sẽ tạo ra gánh nặng được áp đặt trên não của người đọc code =)), vì vậy nó là tốt hơn để sử dụng nếu điều kiện như là một điều kiện phức tạp và đừng lạm dụng Unless quá. Ví dụ dưới đây là 1 điển hình cho việc đọc hiểu khá thốn khi cố tình dùng unless
## Mệt =)) user.destroy unless (user.active? || user.admin?) && !user.spam?
Giảm số dòng bằng cách sử dụng toán tử tam phân
Tên gọi thuần việt là: toán tử ba ngôi =)), cách dùng này thì cũng khá quen thuộc với anh em từ dev Java sang
if user.admin? "I appreciate for that." else "Thanks." end
user.admin? ? "I appreciate for that." : "Thanks"
Cũng tương tự với việc sử dụng unless ở trên thì khi dùng toán tử tam phân anh em cũng đừng lạm dụng quá, kiểu lồng nhau nested như thế này mình nghĩ là không nên
user.admin? ? user.active? ? "I appreciate for that." : "Are you OK?" : "Thanks."
Khai báo biến và dùng luôn
user = find_user if user send_mail_to(user) end
if user = find_user send_mail_to(user) end
Cách viết này khá thú vị, tuy nhiên có nhiều người lại không thích vì dễ gây hiểu nhầm việc gán giá trị cho biến trong mệnh đề if thành toán tử so sánh ==
Kiểm tra nil của 1 đổi tượng
Viết nếu bạn muốn kiểm tra các điều kiện bằng cách gọi các thuộc tính và phương thức của nó chỉ khi có một đối tượng con Đoạn mã sau đây cho thấy rằng parent.children có thể là nil
if parent.children if parent.children.singleton? singleton = parent.children.first send_mail_to(singleton) end end
if parent.children && parent.children.singleton? singleton = parent.children.first send_mail_to(singleton) end
Trong Ruby 2.3, một toán tử mới &.. Được gọi là toán tử điều hướng an toàn được gọi đã được thêm vào (Mình có 1 bài riêng về toán tử này, ae tìm post cũ, tăng view cho mình nha :v) Với điều này, bạn có thể thử các cuộc gọi phương thức trên các đối tượng có thể là số không. Nếu đối tượng là nil, giá trị trả về cũng là nil
if parent.children&.singleton? singleton = parent.children.first send_mail_to(singleton) end
Note: tuy nhiên cách viết này cũng có 1 vài điểm khá bất cập, ví dụ bạn gọi sai thuộc tính hoặc method sau object thì thay vì raise exception như bình thường thì sẽ vẫn trả về nil, điều này sẽ khiến chúng ta có thể bị "lừa" khi debugger nên mọi người cùng chú ý điểm này
##Ví dụ gõ sai tên method singleton? parent.children.singletom? => raise exception parent.children&.singletom? => nil
Không cần dùng return cuối phương thức
Ruby có cái rất hay là sẽ lấy dòng cuối cùng mỗi phương thức làm giá trị trả về mà không cần dùng return như các ngôn ngữ khác
def build_message(user) message = 'hello' message += '!!' if user.admin? return message end
def build_message(user) message = 'hello' message += '!!' if user.admin? message end
Sử dụng Object #tap, 1 cho tất cả
Thay vì khởi tạo object -> gán giá trị cho các thuộc tính của object đó -> trả về dưới dạng return object
def build_user user = User.new user.email = "hoge@hoge.com" user.name = "Taro Yamada" user end
def build_user User.new.tap do |user| user.email = "hoge@hoge.com" user.name = "Taro Yamada" end end
Lược dấu ngoặc đơn cuối method
Cái này mình thấy cũng có cái hay, cũng có cái không hợp lý, để mình kể 1 câu chuyện nhỏ. Trước convention Ruby công ty mình có yêu cầu là lược bỏ dấu () cuối phương thức, và rồi thì khi Review code ae đều comment yêu cầu nhau remove () khi nhìn thấy. Đến 1 ngày kia, làm việc cùng anh em PHP (anh em PHP sang dev Ruby) cho rằng việc bỏ () đôi khi là k cần thiết, vì nó làm mất đi sự trong sáng của code. => 2 phe bỏ và không bỏ () => sau đó, gọi là "dĩ hòa vĩ quý" chúng mình thống nhất việc bỏ () là optional.
def build_user(params, condition) users = User.get_by_scope(params, condition) ... end
def build_user params, condition users = User.get_by_scope params, condition ... end
Các bạn sẽ chọn cách viết nào?
(còn tiếp, còn rất nhiều =)))