Rails Seed DB от CSV - Проблем с формата на датата

(Ето моята необходима линия за това, че съм нов в ruby/rails и програмирането като цяло; първият SO въпрос също)

Имам рейк задача да заредя моята MySQL DB от CSV-

...
    CSV.read(uri).each do |row|
      Incident.create(
        :building_address => row[9],
        :agency => row[3],
        :complaint_type => row[6],
        :descriptor => row[5],
        :created => row[1],
        :closed => row[2],
        )
end

:created и :closed се дефинират като полета за дата (и също са отделни от/не са свързани с полетата created_at и updated_at на релсите), но предполагам, че CSV файловете разпознават само низове.

Когато стартирам тази задача, денят и месецът се сменят. Така че 1/12/2010 12:00:00 AM в CSV (което за CSV и мен в САЩ означава 12 януари) в крайна сметка се анализира като 2010-12-1 и всеки ден след 12 връща нула, така че 1/20/2010 12:00:00 AM води до нулев запис в моята база данни.

добавих

date:
    formats:
        default: "%m/%d/%Y"

към моя en.yml, но това изглежда засяга само показването на дата и няма ефект върху създаването на обекти чрез моята рейк задача. След като потърсих около SO и други ресурси, опитах

:created => row[1].strftime,

и

:created => row[1].strptime,

но получи undefined method strptime/strftime for "Created Date":String (Дата на създаване е името на колоната в CSV).

Така че и аз опитах

:created => row[1].to_date

да промените (вероятно) низа "date" в CSV на дата, но получавате грешка undefined method '<' for nil:NilClass

Промяната на полето за дата в CSV изглежда като ненужна, тъй като има над 1 милион записа.

Как мога да редактирам тази рейк задача, за да заредя правилно моята база данни от този CSV? Или трябва да променя :created от дата на низ и да го манипулирам в логиката на приложението?


person sbauch    schedule 18.11.2011    source източник


Отговори (1)


Можете да опитате да използвате DateTime.strptime за да преобразувате вашите низове в екземпляри на DateTime:

:created => DateTime.strptime(row[1], '%m/%d/%Y %H:%M:%S %p'),
:closed  => DateTime.strptime(row[2], '%m/%d/%Y %H:%M:%S %p')

Методът на класа strptime ще ви позволи да посочите точно формата, който използвате, така че никой от софтуера да не се налага да отгатва. Бих препоръчал да се придържате към форматите за дата и час ISO 8601 за вътрешна употреба в бъдеще, оставете двусмислените формати за човешка консумация.

person mu is too short    schedule 18.11.2011
comment
Опитах това и няколко варианта снощи, но продължавам да получавам грешка invalid date. Мислех, че може би защото :created и :closed са клас Date вместо DateTime, но промяната не помогна. Ще продължим да опитваме тази вечер, като същевременно четем повече за Ruby документите, към които сте се свързали. - person sbauch; 19.11.2011
comment
@sbauch: Какъв тип са колоните :created и :closed? Те date, datetime или timestamp ли са? Ако са дати, опитайте Date.strptime(row[1], '%m/%d/%Y') и Date.strptime(row[2], '%m/%d/%Y'), за да игнорирате частта от деня. - person mu is too short; 19.11.2011
comment
Пробвах и с двете. В момента имам и двете колони като date и мога да използвам Date.strptime('12/15/2010 12:00 AM', '%m/%d/%Y') (след като копирах тази дата директно от моя csv) в моята конзола. Но все още получавам грешката invalid date при рейк задачата. - person sbauch; 19.11.2011
comment
@sbauch: Кой се оплаква от невалидна дата, Date или Incident? - person mu is too short; 19.11.2011
comment
Изглежда, че моята заглавка на CSV замазва това. Благодаря за помощта! редактиране - Въпреки че мисля, че разбрах това, как би могъл да се каже? получавах invalid date /Users/Sam/.rvm/rubies/ruby-1.9.2-p290/lib/ruby/1.9.1/date.rb:1022:in new_by_frags' - person sbauch; 19.11.2011
comment
@sbauch: Страхотно. Вие Date.strptime предизвиквате изключение ArgumentError, когато не може да анализира низа; така че можете да добавите rescue ArgumentError => e и да отбележите какво има в e. - person mu is too short; 19.11.2011