2014-12-18 2 views
2

У меня есть этот метод в моей модели:Rail TimeWithZone против Дата

def date_ranges 
    reservations = Reservation.where(["transport_id =?", transport_id]) 
    reservations = reservations.where(['id <> ?', id]) if !id.nil? 
    reservations.map { |e| e.reservation_start..e.reservation_end } 
end 

Это работает просто отлично (благодаря некоторой помощи от StackOverflow).

Мой reservation_start и reservation_end столбец date тип. Вот моя миграция:

class CreateReservations < ActiveRecord::Migration 
    def change 
    create_table :reservations do |t| 
     t.references :user, index: true 
     t.references :transport, index: true 

     t.date :reservation_start 
     t.date :reservation_end 
     t.timestamps 
    end 
    end 
end 

Если я пытаюсь запустить этот метод после перехода от типа date колонки для datetime типа я получаю сообщение об ошибке:

can't iterate from ActiveSupport::TimeWithZone 

Это не будет работать, даже если я изменить код в моем методе к:

reservations.map do |e| 
    e.reservation_start.to_datetime..e.reservation_end.to_datetime 
end 
+0

Какие версии Ruby/Rails вы используете? – gmile

+0

Ruby 2.1.4 и Rails 4.1.5 –

ответ

1

к сожалению, диапазон должен иметь детализацию по крайней мере, 1 день, если вы хотите перебрать на диапазоне DateTime. Таким образом, оказывается, что ошибка в том, где вы используете #date_ranges, а не в самом методе.

Поскольку вы используете ActiveSupport::TimeWithZone (это тот объект, который вы получаете при использовании типа SQL-типа datetime), у вас есть что-то более точное, чем просто дата - у вас есть время.

Так что, зависит от способа использования метода.

У вас есть два варианта, чтобы исправить это:

  1. Изменить код на следующее:

    reservations.map do |e| 
        e.reservation_start.to_date..e.reservation_end.to_date 
    end 
    

    Таким образом, вы будете терять точность времени, только отступая к датам.

  2. Измените способ использования метода #date_ranges. Вероятно, лучшим было бы вернуть возвращенные массивы [begin_date, end_date].

    def date_ranges 
        Reservation.where(transport_id: transport_id).pluck(:reservation_start, :reservation_end) 
    end 
    

    В зависимости от того, как вы используете диапазон, вы можете понять это:

    • Если вы проверяете, если определенное время находится в пределах любого из указанных диапазонов дат, вы можете сделать это:

      date_ranges.any? { |date_range| date_range.cover?(my_time) } 
      
    • Если вы отображающие даты:

      date_ranges.each do |date_range| 
          # display the date range 
      end 
      
Смежные вопросы