Ruby on Rails ActiveRecord Associations - Những phần ít được biết đến
Bài đăng này đã không được cập nhật trong 7 năm
ActiveRecord associations là một phần cơ bản của Rails, nhưng không phải tất cả chúng được sử dụng rộng rãi. Dưới đây là những phần ít được biết đến của ActiveRecord association.
Customizing Queries
Có lẽ bạn đã từng phát triển một trang blog cho phép comment. Một số comment có thể không phù hợp, vì vậy bạn muốn đảm bảo những comment sẽ chỉ được hiển thị nếu người kiểm duyệt trang web của bạn chấp thuận. Bạn hãy thêm trường boolean approved
vào bảng Comment
của mình.
Vì mỗi bài đăng trên blog bạn chỉ muốn lấy danh sách các comment đã được phê duyệt, bạn có thể tùy chỉnh truy vấn
# app/models/post.rb
class Post < ActiveRecord::Base
has_many :approved_comments, -> { where approved: true }, class_name: 'Comment'
...
Bây giờ bạn đã có một association my_post.approved_comments
mà bạn có thể sử dụng bất cứ nơi nào bạn cần để lấy các bình luận đã được kiểm duyệt của một bài đăng.
Extensions
Có thể bạn muốn có các tùy chọn để hiển thị tất cả comment về bài đăng hoặc hạn chế chỉ cho những bài đăng được tạo ngày hôm nay. Bạn có thể thêm một phần mở rộng, tức là nói một phương pháp tùy chỉnh cho association đặc biệt này.
# app/models/post.rb
class Post < ActiveRecord::Base
has_many :comments do
def today
where("created_at >= ?", Time.zone.now.beginning_of_day)
end
end
...
Bây giờ, ngoài việc có thể gọi my_post.comments
bạn có thể tùy chỉnh các bản ghi được lấy ra bằng cách gọi my_post.comments.today
Callbacks
Có thể gọi các method tự động trước và sau khi bản ghi được thêm vào hoặc gỡ bỏ. Giả sữ bạn có một dự án xây dựng có người lao động... mỗi khi bạn muốn thêm một người lao động mới vào dự án xây dựng mà bạn muốn tính toán các thay đổi cho ngân sách dự án và những thay đổi cho ngày hoàn thành dựa vào loại người lao động, kinh nghiệm của người lao động... một phương pháp phức tạp. Và bạn có thể gọi một cách tự động sau khi nhân viên được thêm vào.
# app/models/building_project.rb
class BuildingProject < ActiveRecord::Base
has_many :workers, after_add: :recalculate_project_status
...
def recalculate_project_status(newly_added_worker)
...
end
...
Inverse Of
inverse_of
là một cách tiện dụng để gắn cờ cho Ruby rằng các đối tượng liên quan có thể được truy cập từ một trong hai hướng. my_post.comments
và my_comment.post
. Tất nhiên, phải chỉ định has_many :comments
trong class Post và belongs_to :post
trong class Comment, bạn phải định nghĩa 2 association... nhưng inverse_of
làm cho nó rõ ràng rằng các đối tượng trong các mối quan hệ thực sự là cùng một đối tượng.
Bạn chỉ định inverse_of
như sau:
# app/models/post.rb
class Post < ActiveRecord.Base
has_many :comments, inverse_of: post
...
Nếu bạn làm làm điều này khi không chỉ định inverse_of
:
post = Post.first
post.update_attribute(:importance, false)
comment = post.comments.first
working_post = comment.post
working_post.update_attribute(:importance, true)
post.importance?
=> false
Nó vẫn nghĩ răng post là unimportant.. đó là bởi vì comment.post
đã thực hiện truy vấn database riêng và có một truy vấn mới và riêng biệt của cùng một bài đăng, và biến post lưu bản gốc không biết rằng bản ghi cơ sở dữ liệu đã được thay đổi.
Bây giờ với inverse_of
, bạn làm theo các bước tương tự :
post = Post.first
post.update_attribute(:importance, false)
comment = post.comments.first
working_post = comment.post
working_post.update_attribute(:importance, true)
post.importance?
=> true
Tốt hơn nhiều! Bởi vì comment.post
không làm một truy vấn cơ sở dử liệu, thay vào đó nó sử dụng cùng một thể hiện của các đối tượng post đã có trong bộ nhớ. Vì vậy, thay đổi trong working_post được tự động hiển thị trong post cùng một lúc, tránh những kết quả bất ngờ.
All rights reserved