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 cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.