Muszę dodać znaczniki czasu ( created_at
& updated_at
) do istniejącej tabeli. Wypróbowałem następujący kod, ale nie zadziałał.
class AddTimestampsToUser < ActiveRecord::Migration
def change_table
add_timestamps(:users)
end
end
Muszę dodać znaczniki czasu ( created_at
& updated_at
) do istniejącej tabeli. Wypróbowałem następujący kod, ale nie zadziałał.
class AddTimestampsToUser < ActiveRecord::Migration
def change_table
add_timestamps(:users)
end
end
Pomocnik znacznika czasu jest dostępny tylko w create_table
bloku. Możesz dodać te kolumny, określając typy kolumn ręcznie:
class AddTimestampsToUser < ActiveRecord::Migration
def change_table
add_column :users, :created_at, :datetime, null: false
add_column :users, :updated_at, :datetime, null: false
end
end
Chociaż nie ma tej samej zwięzłej składni, co add_timestamps
metoda, którą określiłeś powyżej, Railsy nadal będą traktować te kolumny jako kolumny ze znacznikami czasu i normalnie aktualizować wartości.
rails g migration AddTimestampsToUser created_at:datetime updated_at:datetime
- skrót do wygenerowania migracji powyżej.PG::NotNullViolation: ERROR: column "created_at" contains null value
ponieważ moja tabela zawiera już dane, które naruszają ograniczenie niepuste. Czy jest jakiś lepszy sposób na zrobienie tego niż najpierw usunięcie niezerowego ograniczenia, a następnie dodanie go później?add_column :users, :updated_at, :datetime, null: false, default: Time.zone.now
.Time.zone.now
to tylko przykład, powinieneś użyć dowolnej wartości, która ma sens dla twojej logiki.Migracje to tylko dwie metody klas (lub metody instancji w 3.1):
up
idown
(a czasamichange
metoda instancji w 3.1). Chcesz, aby zmiany zostały wprowadzone doup
metody:Jeśli jesteś w wersji 3.1, możesz również użyć
change
(dzięki Dave):Być może jesteś mylące
def change
,def change_table
ichange_table
.Więcej informacji zawiera przewodnik migracji .
źródło
change
metoda, chociaż w tym przypadku nie problem :)change
warto o tym wspomnieć, więc też to dodam.Twój oryginalny kod jest bardzo zbliżony do właściwego, wystarczy użyć innej nazwy metody. Jeśli używasz Railsów 3.1 lub nowszych, musisz zdefiniować
change
metodę zamiastchange_table
:Jeśli używasz starszej wersji, musisz zdefiniować
up
idown
metody zamiastchange_table
:źródło
@ user1899434 odpowiedział na fakt, że „istniejąca” tabela może oznaczać tabelę z już zawartymi rekordami, których możesz nie chcieć usunąć. Dlatego po dodaniu znaczników czasu z wartością null: false, która jest wartością domyślną i często pożądaną, wszystkie istniejące rekordy są nieprawidłowe.
Ale myślę, że odpowiedź można poprawić, łącząc dwa kroki w jedną migrację, a także używając bardziej semantycznej metody add_timestamps:
Możesz zastąpić inną sygnaturę czasową
DateTime.now
, na przykład gdybyś chciał zamiast tego utworzyć / zaktualizować istniejące wcześniej rekordy.źródło
Time.zone.now
tego należy użyć, jeśli chcemy, aby nasz kod działał zgodnie z właściwą strefą czasową.Time.zone.now
która polega na zwróceniu instancji Time, która jest tworzona podczas uruchamiania migracji, i po prostu używa tego czasu jako domyślnego. Nowe obiekty nie otrzymają nowej instancji Time.Dostępne są transformacje
http://api.rubyonrails.org/classes/ActiveRecord/ConnectionAdapters/Table.html
źródło
Odpowiedź Nicka Daviesa jest najbardziej kompletna pod względem dodawania kolumn sygnatur czasowych do tabeli z istniejącymi danymi. Jedynym minusem jest to, że wzrośnie
ActiveRecord::IrreversibleMigration
nadb:rollback
.Należy go tak zmodyfikować, aby działał w obu kierunkach:
źródło
change_column_default
nie obsługujefrom
iwto
tej wersji?), Ale wziąłem ten pomysł i stworzyłemup/down
metody zamiast jednejchange
metody i działało to jak urok!źródło
nie jestem pewien, kiedy dokładnie to zostało wprowadzone, ale w railsach 5.2.1 możesz to zrobić:
aby uzyskać więcej informacji, zobacz „ Korzystanie z metody zmiany ” w dokumentacji migracji aktywnych rekordów.
źródło
, null: true
po:my_table
Zrobiłem prostą funkcję, że można zadzwonić, aby dodać do każdej tabeli (zakładając, że masz istniejącej bazy danych) created_at i updated_at dziedzinach:
źródło
Dodaje kolumny sygnatur czasowych (created_at i updated_at) do table_name. Dodatkowe opcje (takie jak null: false) są przekazywane do #add_column.
źródło
Odpowiedzi podane wcześniej wydają się prawidłowe, jednak napotkałem problemy, jeśli moja tabela zawiera już wpisy.
Otrzymałbym „BŁĄD: kolumna
created_at
zawieranull
wartości”.Aby naprawić, użyłem:
Następnie użyłem gem migracji_data, aby dodać czas dla bieżących projektów migracji, takich jak:
Wtedy wszystkie projekty utworzone po tej migracji zostaną poprawnie zaktualizowane. Upewnij się, że serwer również został zrestartowany, aby Railsy
ActiveRecord
zaczęły śledzić sygnatury czasowe w rekordzie.źródło
Wiele odpowiedzi tutaj, ale swoją też opublikuję, ponieważ żadna z poprzednich naprawdę nie zadziałała :)
Jak niektórzy zauważyli,
#add_timestamps
niestety dodajenull: false
ograniczenie, co spowoduje, że stare wiersze będą nieprawidłowe, ponieważ nie zawierają tych wartości. Większość odpowiedzi sugeruje, że ustawiliśmy jakąś domyślną wartość (Time.zone.now
), ale nie chciałbym tego robić, ponieważ te domyślne znaczniki czasu dla starych danych nie będą poprawne. Nie widzę wartości dodawania nieprawidłowych danych do tabeli.Więc moja migracja była po prostu:
Nie
null: false
, żadnych innych ograniczeń. Stare wiersze będą nadal obowiązywały zcreated_at
asNULL
iupdate_at
asNULL
(do czasu wykonania aktualizacji wiersza). Nowe wiersze będą miałycreated_at
iupdated_at
wypełnione zgodnie z oczekiwaniami.źródło
Problem z większością odpowiedzi tutaj polega na tym, że jeśli domyślnie
Time.zone.now
wszystkie rekordy będą miały czas uruchomienia migracji jako domyślny czas, co prawdopodobnie nie jest tym, czego chcesz. W szynach 5 możesz zamiast tego użyćnow()
. Spowoduje to ustawienie sygnatur czasowych dla istniejących rekordów jako czasu uruchomienia migracji i jako czasu rozpoczęcia transakcji zatwierdzania dla nowo wstawianych rekordów.class AddTimestampsToUsers < ActiveRecord::Migration def change add_timestamps :users, default: -> { 'now()' }, null: false end end
źródło
Używanie
Time.current
to dobry styl https://github.com/rubocop-hq/rails-style-guide#timenowlub
źródło
To proste, aby dodać znacznik czasu do istniejącej tabeli.
źródło
Dla tych, którzy nie używają Railsów, ale używają activerecord, poniżej również dodaje się kolumnę do istniejącego modelu, na przykład dla pola liczb całkowitych.
źródło
To
change
nie jestchange_table
dla Railsów 4.2:źródło
Wydaje się, że to czyste rozwiązanie w Railsach 5.0.7 (odkryłem metodę change_column_null):
źródło
Jestem na szynach 5.0 i żadna z tych opcji nie działała.
Jedyną rzeczą, która działała, było użycie typu: timestamp, a nie: datetime
źródło
Osobiście korzystałem z następujących i zaktualizowałem wszystkie poprzednie rekordy o aktualną godzinę / datę:
źródło
Napotkałem ten sam problem na Rails 5, próbując użyć
Udało mi się ręcznie dodać kolumny sygnatur czasowych za pomocą następujących elementów:
źródło