Как бы вы хранили часы работы в db / модели приложения Rails? - PullRequest
16 голосов
/ 28 июля 2010

Я создаю приложение Rails, которое будет хранить часы работы и закрытия для бизнеса.Первоначально я думал просто о том, чтобы использовать текстовый тип данных и позволить ему иметь произвольную форму:

"Monday to Friday 9am to 5pm
Saturday 11am to 4pm
Closed Sundays"

Но требования изменились, и мне нужно сравнить часы с текущей датой и временем и отобразить "Открыть "или" Закрыто "в представлении.Что-то вроде:

class Business < ActiveRecord::Base

  def open?
    # Something like ... 
    Time.now > open_time && Time.now < close_time
  end

end

Итак, что было бы лучшим способом решения этой проблемы с точки зрения хранения часов для каждого дня недели?Должен ли бизнес иметь просто has_many: open_blocks (или что-то еще), у которых есть время открытия и закрытия?Должен ли я просто хранить день как строку?

Ответы [ 5 ]

4 голосов
/ 29 ноября 2016

В настоящее время я настраиваю список каталогов для клиента, и мы хотим предоставить пользователю больше гибкости.Итак: пусть пользователь установит блоки на дни:

У нас есть день (целое число 1-7), открывается (время), закрывается (время), а некоторые магазины или достопримечательности имеют летнее и зимнее время работы, или они проводят отпуск.Согласно schema.org вы должны добавить valid_from (datetime) и valid_through (datetime).

С помощью этой настройки пользователь может создавать все, что он хочет:

# migration
class CreateOpeningHours < ActiveRecord::Migration
  def change
    create_table :opening_hours do |t|
      t.integer :entry_id # your model reference
      t.integer :day
      t.time :closes
      t.time :opens
      t.datetime :valid_from
      t.datetime :valid_through
    end
  end
end

Пример для модели:

class OpeningHour < ActiveRecord::Base

  belongs_to :entry

  validates_presence_of :day, :closes, :opens, :entry_id
  validates_inclusion_of :day, :in => 1..7
  validate :opens_before_closes 
  validate :valid_from_before_valid_through 

  # sample validation for better user feedback
  validates_uniqueness_of :opens, scope: [:entry_id, :day]
  validates_uniqueness_of :closes, scope: [:entry_id, :day]

  protected
  def opens_before_closes
    errors.add(:closes, I18n.t('errors.opens_before_closes')) if opens && closes && opens >= closes
  end

  def valid_from_before_valid_through
    errors.add(:valid_through, I18n.t('errors.valid_from_before_valid_through')) if valid_from && valid_through && valid_from >= valid_through
  end

end

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

1 голос
/ 12 февраля 2015

Я бы сказал, что часы работы принадлежат адресу стороны и должны быть представлены RFC 5455 RRULE и, необязательно, EXRULE или EXDATE с.

Допустим, у вас есть вечеринка:

"Акме, Инк."

У них есть один физический адрес:

"Главная улица 123, Ванкувер"

Их адрес играет две роли:

«Продажи» и «Сервис»

Продажи открыты Mo-Sa 10-8 и Сервис открыт Mo-Fr 9-5

Вот ПРАВИЛА:

(продажи)

startTime:'10:00:00'
endTime:'20:00:00'
RRULE:FREQ=WEEKLY;BYDAY=MO,TU,WE,TH,FR,SA

(Service)

startTime:'09:00:00'
endTime:'17:00:00'
RRULE:FREQ=WEEKLY;BYDAY=MO,TU,WE,TH,FR
1 голос
/ 13 марта 2011

В этом случае я бы, вероятно, сделал что-то относительное, возможно, с STI, если вы хотели бы иметь определенные дни, когда бизнес закрыт (например, неповторяющиеся закрытия)Вот основной пример ИППП:

class Business < ActiveRecord::Base
  has_many :open_time_blocks
  has_many :closed_time_blocks

  def open?(time)
    # false if time is "inside" any of the closed_time_blocks
    # else is true if inside any of the open_time_blocks
    # else is false
  end

  def closed?(time)
    !open?
  end
end

# == Schema Information
#
# Table name: time_blocks
#
#  id          :integer         not null, primary key
#  business_id :integer
#  type        :string(255)
#  start_at    :datetime
#  end_at      :datetime
#  created_at  :datetime
#  updated_at  :datetime
class TimeBlock < ActiveRecord::Base
  belongs_to :business
end

class OpenTimeBlock < TimeBlock; end
class ClosedTimeBlock < TimeBlock; end
0 голосов
/ 13 марта 2011

Итак, я только что узнал, ice_cube может обрабатывать повторяющиеся длительности:

> schedule = IceCube::Schedule.new(Time.now, :duration => 3600)
> schedule.add_recurrence_rule Rule.daily
> schedule.occurs_at?(Time.now + 1000)
true
> schedule.occurs_at?(Time.now + 1.day + 1000)
true
> schedule.occurs_at?(Time.now + 4000)
false

Я подозреваю, что вы можете справиться с множеством различных ситуаций, используя ice_cube таким образом.

Между прочим, я внедряю аналогичное открытое / закрытое рабочее расписание. Мне было бы интересно узнать, как вы это сделали, и если у вас есть репозиторий github, мы можем сотрудничать вместе.

0 голосов
/ 28 июля 2010

Оформить заказ эти библиотеки для обработки повторяющихся дат.

Как только повторение настроено в объекте, скажем office_hours, в ice_cube вы можете запросить его как:

office_hours.occurring_at?(Time.now)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...