2012-01-19 11 views
12

Mam model zwany przesyłkami. Dodałem kilka kolumn do tabeli przesyłek i jest kilka kolumn, które powinny zostać obliczone przed zapisaniem. Teraz muszę edytować każdą aktualizację rekordów i trafień, aby nowe kolumny mogły obliczyć i dodać dane.Szyny 3. Jak wykonać akcję zapisu we wszystkich rekordach?

Czy istnieje sposób na wykonanie zapisu globalnego dla wszystkich rekordów wysyłek, aby dane mogły zostać dodane?

before_save :default_values 
    def default_values 
    self.volume = 1 unless self.volume 
    self.kilograms = 1 unless self.kilograms 
    self.status = "Open" if self.status.blank? 
     if self.mode == "Air" 
     self.estimated_transit_time = self.etd_origin + 7.days 
     self.eta_place_of_delivery = self.etd_origin + 7.days 
     else 
     self.estimated_transit_time = self.etd_origin + (Place.find_by_city(self.place_of_loading).transit_time).days 
     self.eta_place_of_delivery = self.etd_origin + (self.estimated_transit_time).days 
     end 
    end 

Odpowiedz

1

Można zrobić to metoda tak:

def self.save_all 
    Shipment.all.each { |shipment| shipment.save! } 
end 

Następnie wystarczy zadzwonić:

Shipment.save_all 
+0

uzyskać 'SystemStackError (poziom stos zbyt głęboko):' ale jeśli uruchomię 'Shipment.all.each {| transport | shipment.save!} 'w konsoli działa. Dzięki! :) – leonel

13

Załaduj dane przez partię. Nigdy obciążenie naraz

Shipment.find_each(:batch_size => 1000) do |shipment| 
    shipment.save! 
end 

Wtedy, gdy trzeba obliczyć pewne polach po migracji lub coś innego. Po prostu dodaj tę pracę do migracji.

+3

Zadbaj o udostępnienie powodu do użycia partii zamiast Model.all.each {| mdl | mld.save!}? –

+7

@ affinities23 Oczywiście! Model.all załaduje wszystkie rekordy na raz. Będzie to działało dobrze, jeśli masz niewielką ilość rekordów, ale będzie wolniej i wolniej, aw końcu pęknie, jeśli wszystkie rekordy nie zmieszczą się w pamięci w tym samym czasie. find_each ładuje się wsadowo (W moim przykładzie nie ma więcej niż 1000 rekordów w pamięci), co pozwoli uniknąć problemu, który właśnie opisałem. – basgys

34

One liner:

Shipment.find_each(&:save) 
+9

Wszystkie te rozwiązania wykonują n wywołań do bazy danych. Bardziej interesujące byłoby wykonanie tylko jednego połączenia typu 'update_all' w celu aktualizacji kolekcji. –

Powiązane problemy