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 = ...
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.