Chỉ chạy một lệnh gọi lại nếu một thuộc tính đã thay đổi trong Rails


100

Tôi có liên kết sau trong ứng dụng của mình:

# Page 
belongs_to :status

Tôi muốn chạy một cuộc gọi lại bất cứ lúc nào thay đổi status_idcủa a page.

Vì vậy, nếu page.status_idđi từ 4 đến 5, tôi muốn có thể bắt được.

Làm thế nào để làm như vậy?

Câu trả lời:


209

Đường ray 5.1+

class Page < ActiveRecord::Base
  before_save :do_something, if: :will_save_change_to_status_id?

  private

  def do_something
    # ...
  end
end

Cam kết đã thay đổi ActiveRecord :: Dirty ở đây: https://github.com/rails/rails/commit/16ae3db5a5c6a08383b974ae6c96faac5b4a3c81

Đây là một bài đăng trên blog về những thay đổi này: https://www.ombulabs.com/blog/rails/upgrades/active-record-5-1-api-changes.html

Đây là bản tóm tắt tôi đã thực hiện cho chính mình về các thay đổi đối với ActiveRecord :: Dirty in Rails 5.1+:

ActiveRecord :: Dirty

https://api.rubyonrails.org/classes/ActiveRecord/AttributeMethods/Dirty.html

Trước khi lưu (TÙY CHỌN THAY ĐỔI)

Sau khi sửa đổi một đối tượng và trước khi lưu vào cơ sở dữ liệu hoặc trong before_savebộ lọc:

  • changes bây giờ nên changes_to_save
  • changed? bây giờ nên has_changes_to_save?
  • changed bây giờ nên changed_attribute_names_to_save
  • <attribute>_change bây giờ nên <attribute>_change_to_be_saved
  • <attribute>_changed? bây giờ nên will_save_change_to_<attribute>?
  • <attribute>_was bây giờ nên <attribute>_in_database

Sau khi lưu (THAY ĐỔI ĐỘT PHÁ)

Sau khi sửa đổi một đối tượng và sau khi lưu vào cơ sở dữ liệu hoặc trong after_savebộ lọc:

  • saved_changes(thay thế previous_changes)
  • saved_changes?
  • saved_change_to_<attribute>
  • saved_change_to_<attribute>?
  • <attribute>_before_last_save

Đường ray <= 5.0

class Page < ActiveRecord::Base
  before_save :do_something, if: :status_id_changed?

  private

  def do_something
    # ...
  end
end

Điều này sử dụng thực tế là lệnh before_savegọi lại có thể thực thi có điều kiện dựa trên giá trị trả về của một lệnh gọi phương thức. Các status_id_changed?phương pháp xuất phát từ ActiveModel :: bẩn , cho phép chúng ta kiểm tra xem một thuộc tính cụ thể đã thay đổi bằng cách gắn thêm _changed?vào tên thuộc tính.

Khi nào do_somethingphương thức nên được gọi là tùy thuộc vào nhu cầu của bạn. Nó có thể là before_savehoặc after_savehoặc bất kỳ ActiveRecord :: Callbacks đã xác định .


4
Giải pháp này không được chấp nhận trong các phiên bản mới hơn.
— Mateus Luiz,

6
Cập nhật với thông tin Rails 5.1+.
— pdobb

16

Không attribute_changed?dùng nữa trong Rails 5.1, bây giờ chỉ cần sử dụng will_save_change_to_attribute?.

Để biết thêm thông tin, hãy xem vấn đề này .


Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookie và Chính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.