+2

persisted? vs new_record?

1. persisted? vs new_record?

2 hàm này mình thường xuyên sử dụng, nhiều lúc hay nhầm lẫn. persisted? để mình xác định record đã được lưu ở database chưa. new_record? xác định record vừa được new ra và chưa lưu ở database

user = User.new
user.new_record?  # true
user.persisted?   # false

user = User.first
user.new_record?  # false
user.persisted?   # true

2. delete vs destroy

Về cơ bản thì destroy nó sẽ gọi callbacks khi được thực thi còn delete thì không. Mình xin trích dẫn từ Rails API như sau:

  • ActiveRecord::Persistance.delete

Deletes the record in the database and freezes this instance to reflect that no changes should be made (since they can't be persisted). Returns the frozen instance. The row is simply removed with an SQL DELETE statement on the record's primary key, and no callbacks are executed. To enforce the object's before_destroy and after_destroy callbacks or any :dependent association options, use #destroy.

Khi delete thì nó trả về cho bạn một frozen instance, tức là bạn không làm gì ngoài read nó, và không có callbacks nào được chạy.

color = Color.find 2
deleted_red = color.delete
deleted_red                         #print deleted record
Color.find 2                        #Couldnt find Color with id=2

Nếu cố gắng update nó thì sẽ như thế này.

deleted_red.update name: "red"      #Cant modify frozen hash

  • ActiveRecord::Persistance.destroy

Deletes the record in the database and freezes this instance to reflect that no changes should be made (since they can't be persisted). There's a series of callbacks associated with destroy. If the before_destroy callback return false the action is cancelled and destroy returns false. See ActiveRecord::Callbacks for further details.

Cũng giống như delete, destroy sẽ trả về cho bạn 1 frozen instance. Nhưng nó sẽ gọi các callbacks (before_destroy, after_destroy, ...), nếu như 1 trong các callback return false thì việc destroy coi như không thành công.

3. where vs where.not

Thay vì phải sử dụng điều kiện phủ định ở trong điều kiện where thì ta có dùng where.not

User.where('name != ?', 'Duc')
User.where.not(name: 'Duc')

4 . scope vs class.method

Mình thường hay bị hỏi 2 cái này khác nhau cái gì, lúc đó mình chả biết gì nên trả lời "cái nào cũng được, miền sao không bug là được". Vô trách nhiệm vại. Thực ra mình thấy ưu điểm lớn nhất của scope hơn với class.method đó khi sử dụng method chain, kiểu như gọi hàm liên tục trong 1 câu lệnh.

class Post
  scope :recent, -> { order(created_at: :desc) }
  scope :by_gender, -> gender {where(gender: gender) if (gender == :male || gender == :female)}
  def self.by_gender_class_method gender
    where(gender: gender) if (gender == :male || gender == :female)
  end
end

Ở đoạn code trên nếu mình không thêm đoạn if (gender == :male || gender == :female) thì scope và class.method đều giống nhau chạy method chain một cách bình thường. Nhưng vì có đoạn này, thì scope thể hiện tính an toàn hơn class method. Nếu mình chạy câu lệnh dưới đây sẽ bị lỗi như sau:

Post.by_gender_class_method(:unisex).recent
NoMethodError: undefined method `recent' for nil:NilClass

Lúc get post bằng method by_gender_class_method thì nó không thực thi nên trả về nil, rồi gọi tiếp recent nên bị lỗi.

Còn nếu mình thực hiện bằng scope

Post.by_gender(:unisex).recent

thì câu lệnh by_gender sẽ bị skip, và thực hiện chỉ mỗi recent mà thôi.

Kết: Nếu có time sẽ cập nhập một số khác biệt biết được vào đây.


All rights reserved

Viblo
Hãy đăng ký một tài khoản Viblo để nhận được nhiều bài viết thú vị hơn.
Đăng kí