2013-04-25 26 views
7

Có cách nào để bỏ qua cập nhật liên kết với hiệp hội :touch khi lưu không?Bỏ qua: liên lạc khi lưu đối tượng ActiveRecord

Setup:

class School < ActiveRecord::Base 
    has_many :students 
end 

class Student < ActiveRecord::Base 
    belongs_to :school, touch: true 
end 

Tôi muốn để có thể làm điều gì đó như sau đây mà các liên lạc được bỏ qua.

@school = School.create 
@student = Student.create(school_id: @school.id) 
@student.name = "Trevor" 
@student.save # Can I do this without touching the @school record? 

Bạn có thể làm việc này không? Một cái gì đó như @student.save(skip_touch: true) sẽ là tuyệt vời nhưng tôi đã không tìm thấy bất cứ điều gì như thế.

Tôi không muốn sử dụng một cái gì đó như update_column vì tôi không muốn bỏ qua các cuộc gọi lại AR.

+1

Vì vậy, bạn thường muốn chạm vào, nhưng đôi khi bỏ qua các liên lạc? – AlexBrand

+0

Vâng, chính xác. Về cơ bản tôi có một tình huống mà tôi đang cập nhật nhiều mô hình mà tất cả các liên lạc cùng một mối quan hệ. Tôi muốn tránh sự đụng chạm trong tình huống đó. –

Trả lời

2

Một tùy chọn tránh việc vá trực tiếp khỉ là ghi đè phương thức được tạo khi bạn có quan hệ với thuộc tính :touch.

Với thiết lập từ OP:

class Student < ActiveRecord::Base 
    belongs_to :school, touch: true 

    attr_accessor :skip_touch 

    def belongs_to_touch_after_save_or_destroy_for_school 
    super unless skip_touch 
    end 

    after_commit :reset_skip_touch 

    def reset_skip_touch 
    skip_touch = false 
    end 
end 

@student.skip_touch = true 
@student.save # touch will be skipped for this save 

này rõ ràng là khá hacky và phụ thuộc vào chi tiết thực hiện nội bộ thực sự cụ thể trong AR.

+0

Định nghĩa 'thuộc_to_touch_after_save_or_destroy_for_school' ở đâu? –

+0

Nó được định nghĩa bởi hàm 'thuộc_to'. Tùy thuộc vào phiên bản Rails của bạn, bạn có thể tìm thấy nó ở đâu đó như 'activerecord-3.2.19/lib/active_record/associations/builder/owned_to.rb: 51' –

1

Thật không may, không. save không cung cấp tùy chọn như vậy.

Làm việc xung quanh việc này sẽ có thuộc tính dấu thời gian khác có chức năng như updated_at nhưng không giống như updated_at, nó chỉ cập nhật trên một số trường hợp theo ý thích của bạn.

0

Tính đến Rails v4.1.0.beta1, cách thích hợp để làm điều này sẽ là:

@school = School.create 
@student = Student.create(school_id: @school.id) 

ActiveRecord::Base.no_touching do 
    @student.name = "Trevor" 
    @student.save 
end 
Các vấn đề liên quan