Những cách set attributes trong ActiveRecord (Rail 4)
This post hasn't been updated for 5 years
Rails 4 cho phép các Dev thay đổi các thuộc tính ActiveRecord theo nhiều cách khác nhau. Mỗi cách lại có một chút khác biệt, đôi khi lại có các hệ quả khá thú vị . Điều quan trọng nhất ở đây là chúng ta phải hiểu được phương pháp thích hợp nhất cho từng tình huống cụ thể. Do đó mình sẽ giới thiệu cho các bạn 1 bảng cheat sheet mà mình dùng cực kì nhiều, kèm theo chi tiết ở bên dưới. (bow)
Cheat Sheet
Method | Sử dụng Accessor mặc định | Lưu vào Database | Validate | Callback | Cập nhật updated_at | Check readonly |
---|---|---|---|---|---|---|
attribute= | - | - | - | - | ||
write_attribute | - | - | - | - | ||
update_attribute | ||||||
update_attributes | ||||||
attributes= | - | - | - | - | ||
update | ||||||
update_column | ||||||
update_columns | ||||||
User::update | ||||||
User::update_all |
Chi tiết
Sau đây mình sẽ lấy ví dụ về việc cập nhật attribute name
cho object user
.
user.name = "Foo"
Đây là một biểu thức gán hoàn toàn bình thường, dễ hiểu, dễ dùng nhất. Đây là write accessor
mặc địch được Rails tự động tạo ra. Attribute name
sẽ được gắn cờ là dirty
và mọi sự thay đổi đều chưa được lưu vào DB.
Bạn có thể undo thay đổi này bằng việc gọi reload!
hoặc lưu thay đổi vào DB bằng cách gọi save
user.write_attribute(:name, "Foo")
Đây là method được gọi bởi write accessor
bên trên. Alias của method này chính là user[:name] = "Foo"
.
Cũng như bên trên, method này không thay đổi attribute trong DB. Để sử dụng method này bạn phải override lại write accessor
bên trên, ví dụ như khi bạn muốn viết lại write accessor
attribute=
:
def name=(new_name)
write_attribute(:name, new_name.upcase)
# Tương đương với:
# self[:name] = new_name.upcase
end
=> Tự động uppercase attibute name
khi được set
user.update_attribute(:name, "Foo")
Method này sẽ thay đổi attribute trong model và đẩy trực tiếp vào DB mà không qua bất cứ Validation
nào hết. Tuy nhiên vẫn chạy các callback
, tất cả các thay đổi khác cũng sẽ được lưu vào trong DB.
user.attributes = {name: "Foo"}
Method này sẽ cập nhật tất cả những attribute bạn truyền vào. Tuy nhiên, thay đổi cũng sẽ không được lưu vào DB. Những attributes khác không được truyền vào đều được giữ nguyên. Bạn có thể sử dụng assign_attributes
để thay thế cho method này.
user.attributes = {name: "Foo", age: 25}
user.assign_attributes {name: "Foo", age: 25}
# Hai câu này tương đương nhau.
user.update(name: "Foo")
Method này từng được gọi là update_attributes
trong Rails 3. Method này sẽ thay đổi attribute trong model, check validate, chạy callback và đẩy trực tiếp vào DB nếu như validate.
Cũng giống như update_attribute
, method này cũng lưu tất cả những thay đổi khác vào DB
user.update_columns(name: "Foo")
Method này thực thi trực tiếp 1 câu query SQL UPDATE và bỏ qua validate cũng như là callback. Nó chỉ check rằng các cột đó có được đánh readonly
hay không, nêú có thì sẽ raise exception.
user.update_column(:name, "Foo")
Cũng giống như update_columns
, tuy nhiên chỉ update được duy nhất 1 attrbute.
User.update(1, name: "Foo")
Note: Đây là một class method
Method này tìm Object bằng ID và update attribute của nó bằng hash được truyền vào. Method này sử dụng User#update
để update cho nên nó vẫn sẽ chạy qua validate và callback, cũng như là cập nhật lại trường updated_at
Bạn cũng có thể truyền vào 1 mảng ID và params:
User.update(
[1,2,3],
[
{name: "Rob"},
{name: "David", age: 12},
{age: 15, location: "London"},
]
)
# Tham số thứ hai là một mảng các hash
User.update_all(name: "Foo")
Method này giống như update_columns
, sẽ chạy một câu SQL UPDATE và bỏ qua toàn bộ Validate và Callback, tuy nhiên sẽ không check đến cột có readonly
hay không. Bạn có thể sử dụng method này trong một scoped relation:
User.where(name: "Foo").update_all(name: "FooFighter")
Cảm ơn các bạn đã đọc bài viết của mình. (bow)
nguồn: Different Ways to Set Attributes in ActiveRecord (Rails 4)
All Rights Reserved