Mam tabelę w aplikacji Rails z setkami tysięcy rekordów i mają one tylko created_at
znacznik czasu. Dodam możliwość edycji tych rekordów, więc chcę dodać updated_at
sygnaturę czasową do tabeli. Podczas migracji, aby dodać kolumnę, chcę zaktualizować wszystkie wiersze, aby nowy updated_at
pasował do starego created_at
, ponieważ jest to domyślne dla nowo utworzonych wierszy w Railsach. Mógłbym zrobić find(:all)
i iterować przez rekordy, ale zajęłoby to godziny ze względu na rozmiar tabeli. To, co naprawdę chcę zrobić, to:
UPDATE table_name SET updated_at = created_at;
Czy istnieje lepszy sposób na zrobienie tego w migracji Railsów przy użyciu ActiveRecord zamiast wykonywania surowego SQL?
Yourmodel.update_all 'update_at=created_at'
jest ładniej, nie? Działa też na zakres.up
po którym nastąpi adown
” . Więc rozważdef change
tylko zamiast tego.change
metoda jeszcze nie istniała, ale w tym przypadku nadal wolę używać wyrażenia jawnegoup
idown
być bardziej wyraźnym (jeśli chcesz kontrolować, codown
należy zrobić).Możesz użyć update_all, który działa bardzo podobnie do surowego SQL. To wszystkie opcje, które masz.
Swoją drogą osobiście nie przywiązuję tak dużej wagi do migracji. Czasami surowy SQL jest naprawdę najlepszym rozwiązaniem. Zwykle kod migracji nie jest ponownie używany. To jest jednorazowa akcja, więc nie przejmuję się czystością kodu.
źródło
update_all
wewnątrz pliku migracyjnego :-) Można również wykonać surowy SQL w pliku migracyjnym. Jednakupdate_all
jest trochę bardziej elegancki. Oba będą działać dokładnie tak samo.update_all
mam pojęcia, jak ustawić wartość kolumny na inną, zgodnie z żądaniem PO. Proszę zademonstrować.Jak napisał gregdan, możesz użyć
update_all
. Możesz zrobić coś takiego:Model.where(...).update_all('updated_at = created_at')
Pierwsza część to typowy zestaw warunków. Ostatnia część mówi, jak wykonać zadania. Spowoduje to wyświetlenie
UPDATE
instrukcji, przynajmniej w Rails 4.źródło
SET'posts'.'email' = 'options'
, opcje to dosłowny ciągUser.update_all('updated_at = created_at')
SQL (0.4ms) UPDATE "users" SET updated_at = created_at
Możesz bezpośrednio uruchomić następujące polecenie do swojego
rails console
ActiveRecord::Base.connection.execute("UPDATE TABLE_NAME SET COL2 = COL1")
Na przykład: Chcę zaktualizować SKU mojej tabeli elementów o zdalny_id tabel elementów. polecenie będzie następujące:
ActiveRecord::Base.connection.execute("UPDATE items SET sku = remote_id")
źródło
Yourmodel
można już usunąć. Staraj się unikać używania modeli w migracjach).Jest to ogólny sposób rozwiązywania problemów, bez konieczności pisania zapytań, ponieważ zapytania są narażone na ryzyko.
class Demo < ActiveRecord::Migration def change add_column :events, :time_zone, :string Test.all.each do |p| p.update_attributes(time_zone: p.check.last.time_zone) end remove_column :sessions, :time_zone end end
źródło
Jako operacja jednorazowa zrobiłbym to po prostu w
rails console
. Czy to naprawdę zajmie godziny? Może jeśli są miliony rekordów…records = ModelName.all; records do |r|; r.update_attributes(:updated_at => r.created_at); r.save!; end;`
źródło