Атрибут времени Rails postgres не сохраняется

#ruby-on-rails #postgresql #timezone

#ruby-on-rails #postgresql #Часовой пояс

Вопрос:

Я схожу с ума? time атрибуты теряют свое значение и сбрасываются до 1 января 2000 года после сохранения активного объекта записи. База данных — Postgres. Rails 5.2 и pg gem 1.1.3

 2.6.6 :019 > obj.end_time = Date.new(2019, 9,9)
 => Mon, 09 Sep 2019 
2.6.6 :020 > obj.save
 => true 
2.6.6 :021 > obj.end_time
 => Mon, 09 Sep 2019 00:00:00 UTC  00:00 
2.6.6 :022 > obj.end_time.class
 => ActiveSupport::TimeWithZone 
  

Но теперь, если я перезагружаюсь из базы данных, значение сбрасывается:

 2.6.6 :023 > obj.reload
2.6.6 :024 > obj.end_time
 => Sat, 01 Jan 2000 00:00:00 UTC  00:00
2.6.6 :025 > obj.end_time.class
 => ActiveSupport::TimeWithZone 
  

Тип столбца postgres отображается в psql как «время без часового пояса». Я думаю, мне просто нужно указать datetime вместо time в миграциях, если я хочу установить часть даты?

Я попытался изменить тип столбца при миграции change_column :school_courses, :start_time, :datetime , но получил:

PG::DatatypeMismatch: ОШИБКА: столбец «start_time» не может быть автоматически преобразован в тип timestamp без часового пояса ПОДСКАЗКА: возможно, вам потребуется указать «ИСПОЛЬЗОВАНИЕ start_time::timestamp без часового пояса»

Не уверен, как это сделать

Комментарии:

1. Я не могу воспроизвести это с помощью базовой модели, вы делаете что-то в своем классе модели, что может повлиять на это?

2. Должно быть, это как-то связано с типом столбца в Postgres. У меня ничего нет в модели, и это происходит в другом месте. Попробую проверить в psql

3. Тогда вам было бы полезно опубликовать модель и определения таблиц postgres (DDL).

4. В Rails схема просто указывает «время» для столбца. Запуск d в psql в таблице дает тип столбца как «время без часового пояса», как я уже упоминал. Есть ли другая команда psql, которую вы рекомендуете, которая могла бы предоставить больше информации?

5. @rigyt можете ли вы, пожалуйста, опубликовать, как вы написали свою рабочую миграцию (решение)?

Ответ №1:

Используйте datetime тип столбца для хранения даты и времени, используйте только time при переносе, если вам не нужна дата (хотите сохранить только часть времени)

В любом случае это относится к postgres

Пример миграции:

 create_table "school_years" do |t|
    t.integer "year"
    t.integer "minimum_candidates_per_exam"
    t.time "am_start_time"
    t.time "pm_start_time"
    t.datetime "created_at", null: false
    t.datetime "updated_at", null: false
  end
  

Хотя я обычно просто использую datetime и также устанавливаю часть года и избегаю использования time

Комментарии:

1. Спасибо за ответ. Вы когда-нибудь использовали подсказку, описанную «ПОДСКАЗКА: возможно, вам потребуется указать «ИСПОЛЬЗОВАНИЕ start_time::timestamp без часового пояса»» внутри самой миграции с помощью ключевого слова USING?