Rozwiązanie po stronie Rails
Wygląda na to, że ActiveRecord używany w Railsach (5.2) automatycznie dodaje sekundy dziesiętne do 1 ms przy zapisywaniu created_at
i updated_at
lub dowolne inne kolumny sygnatury czasowej w DB, które akceptują podsekundy, zgodnie z definicją w pliku active_record/connection_adapters/abstract/quoting.rb
Obejście to jest. Dodaj tę linię na najwyższym poziomie w dowolnym pliku, który byłby zawsze odczytywany przez Railsy podczas uzyskiwania dostępu do modelu (takiego jak plik modelu ApplicationRecord).
Time::DATE_FORMATS[:db] = '%Y-%m-%d %H:%M:%S.000000000'
module ActiveRecord::ConnectionAdapters::Quoting
alias_method :quoted_date_orig, :quoted_date if ! self.method_defined?(:quoted_date_orig)
def quoted_date(*rest, **kwd)
quoted = quoted_date_orig(*rest, **kwd)
quoted.sub(/(\.\d*)\.\d{6}$/, '\1')
end
end
Możesz to potwierdzić z konsoli Rails, po utworzeniu nowego rekordu,
MyModel.last.created_at.nsec # => 0
lub po prostu uzyskaj bezpośredni dostęp do bazy danych, aby ją zobaczyć.
Ostrzeżenie
Ta zmiana dotyczy nie tylko created_at
i updated_at
ale także wszystkie inne kolumny sygnatury czasowej w bazie danych. Myślę, że nadal możesz zapisać wartość do precyzji msec (lub nsec) w takiej kolumnie, ustawiając String w przeciwieństwie do instancji Time do instancji modelu, takiej jak my_model.col_msec_desired = "2018-01-02 03:04:05.678"
; następnie Time::DATE_FORMATS[:db]
nie zostanie przywołany podczas zapisywania rekordu.
Potencjalne rozwiązanie po stronie Laravela
Może to być trudne w momencie pisania (2018-10-18), ale wydaje się, że praca jest w toku, zgodnie z bardzo niedawny post Laracast napisany przez cmbertsch01
(Uwaga:ważna aktualizacja dokonana dzień po oryginalnym poście, po komentarzu.)