2010-07-28 13 views
13

Estoy creando una aplicación Rails que almacenará la apertura y cierre de un negocio. Originalmente, pensé en el simple uso de un tipo de datos de texto y dejar que sea de forma libre:¿Cómo almacenar horas de un negocio en el db/modelo de una aplicación Rails?

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

embargo, los requisitos han cambiado y tengo que comprobar las horas en contra de la actual fecha y hora & y mostrar un "abierto" o "Cerrado" en la vista. Algo así como:

class Business < ActiveRecord::Base 

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

end 

Entonces, ¿cuál sería la mejor manera de abordar esto en términos de almacenamiento de las horas para cada día de la semana? ¿Debería el negocio simplemente has_many: open_blocks (o lo que sea) que tenga horarios de apertura y cierre? ¿Debería almacenar el día como una cadena?

+0

Posible duplicado de [Almacenando Horas Comerciales en una Base de Datos] (http://stackoverflow.com/questions/1036603/storing-business-hours-in-a-database) –

Respuesta

0

Pedido these libraries para el manejo de fechas recurrentes.

Una vez que la recurrencia se configura en un objeto office_hours decir, en ice_cube puede consultar como:

office_hours.occurring_at?(Time.now) 
+0

Ok, ice_cube se veía bien pero luego me di cuenta solo almacena "tiempos de inicio" recurrentes de eventos. En realidad, no está diseñado para bloques recurrentes de bloques de tiempo de inicio y fin. Todavía buscando ... – Callmeed

2

Este fue el tema de una reciente RubyLearning challenge - podría ser útil :)

+0

Gracias, lo comprobaré ... – Callmeed

+1

La esencia todavía está allí, pero la publicación del blog se ha ido. Es por eso que publicar solo el enlace en lugar de ejemplos de código es una mala idea. :-( –

0

Así me acabo de enterar ice_cube puede manejar duraciones recurrentes:

> 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 

I Sospe t que se puede manejar una gran cantidad de situaciones diferentes que utilizan ice_cube de esta manera.

Por cierto, estoy poniendo en práctica una agenda de negocios abierto/cerrado similar. Me interesaría saber cómo lo has hecho, y si tienes un repositorio de Github, podemos colaborar juntos.

+1

'ice_cube' es una buena alternativa siempre que ** no ** necesite tener duraciones específicas por regla de recurrencia (lo cual es probable). Para más información, consulte [esta respuesta] (http: // stackoverflow.com/a/13539593/2192331). –

1

En este caso, probablemente hacer algo relacional, tal vez con ITS si quería tener ciertos días donde el negocio está cerrado (por ejemplo, el cierre no recurrentes). Aquí hay un ejemplo básico de ITS:

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 
1

yo diría que las horas de servicio pertenecen a una dirección de la parte, y deben ser representados por un RFC 5455 RRULE y opcionalmente un EXRULE o EXDATE s.

Digamos que usted tiene una Parte:

"Acme, Inc."

tienen uno PhysicalAddress:

"123 Main Street, Vancouver"

Su dirección desempeña dos funciones:

"Ventas" y "servicio"

de venta está abierto Mo -Sa 10-8 y el servicio está abierto Mo-Fr 9-5

Estas son las RRULES:

(Sales)

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

(Servicio)

startTime:'09:00:00' 
endTime:'17:00:00' 
RRULE:FREQ=WEEKLY;BYDAY=MO,TU,WE,TH,FR 
2

estoy actualmente la creación de una lista de directorios para un cliente y queremos dar al usuario una mayor flexibilidad. Por lo tanto: permitir al usuario configurar bloques de días:

Tenemos un día (entero 1-7), abre (tiempo), cierra (tiempo) y algunas tiendas o lugares tienen verano e invierno horarios de apertura, o hacen vacaciones. De acuerdo con schema.org, debe agregar un valid_from (datetime) y un valid_through (datetime).

Con esta configuración el usuario puede crear lo que quiera:

# 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 

Ejemplo para el modelo:

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 

Con esa configuración, puede crear fácilmente una is_open? método en su modelo. ¿Actualmente no configuré el is_open? método, pero si alguien necesita, dame un golpe! Creo que lo terminaré en los próximos días.

+0

También permitimos al usuario un campo de texto libre en nuestro modelo de entrada, como lo hizo hasta ahora. –

Cuestiones relacionadas