2013-04-25 23 views
7

Gibt es eine Möglichkeit, übersprungen zu aktualisieren Verbindungen mit einer :touch Zuordnung beim Speichern?Überspringen: Berührungen beim Speichern eines ActiveRecord-Objekts

Setup:

class School < ActiveRecord::Base 
    has_many :students 
end 

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

Ich möchte in der Lage sein, etwas zu tun wie folgt aus, wo die Berührung übersprungen.

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

Können Sie das tun? Etwas wie @student.save(skip_touch: true) wäre fantastisch, aber ich habe nichts dergleichen gefunden.

Ich möchte nicht so etwas wie update_column verwenden, weil ich die AR-Callbacks nicht überspringen möchte.

+1

Also in der Regel Sie berühren wollen, aber manchmal die Berührung überspringen? – AlexBrand

+0

Ja, genau. Grundsätzlich habe ich eine Situation, in der ich mehrere Modelle aktualisiere, die alle dieselbe Beziehung berühren. Ich möchte die Berührung in dieser Situation vermeiden. –

Antwort

2

Eine Option, die direktes Affepatching vermeidet, ist das Überschreiben der Methode, die erstellt wird, wenn Sie eine Beziehung mit einem :touch-Attribut haben.

das Setup aus dem OP Gegeben:

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 

Das ist offensichtlich ziemlich hacky und hängt von wirklich spezifischen internen Implementierungsdetails in AR.

+0

Wo ist die Definition von 'gehört_to_touch_after_save_or_destroy_for_school'? –

+0

Es wird durch die Funktion 'gehört_to' definiert. Abhängig von Ihrer Version von Rails, können Sie es irgendwo finden wie 'activecord-3.2.19/lib/active_record/associations/builder/gehört_to.rb: 51' –

1

Leider nein. save bietet keine solche Option.

Um dies zu arbeiten wäre ein anderes Zeitstempel-Attribut, das wie updated_at funktioniert, aber im Gegensatz zu updated_at, aktualisiert es nur in bestimmten Situationen für Ihren Geschmack.

0

Ab Rails v4.1.0.beta1, der richtige Weg, dies zu tun wäre:

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

ActiveRecord::Base.no_touching do 
    @student.name = "Trevor" 
    @student.save 
end 
Verwandte Themen