提问人:Ben 提问时间:8/19/2022 最后编辑:Ben 更新时间:8/19/2022 访问量:270
为商店创建营业时间模型的最佳方法是什么 [已关闭]
What's the best approach to create opening hours model for a store [closed]
问:
我想为商店存储一个显示 OpeningHours,例如以下插槽示例:
星期一 = 9h00 => 12h00, 14h30 => 20h00
星期二 = 9H00 => 20H00
我们 = 14h15 => 20h00
THU = 关闭
我需要将它用于 OpeningOursSpecifications Schema.org
答:
0赞
Les Nightingill
8/19/2022
#1
有趣的问题...
我会按如下方式创建模型:
class Store
has_many :day_hours
end
class DayHour
#columns day, am_open, am_closed, pm_open, pm_closed, store_id
belongs_to :store
enum day: Date::ABBR_DAYNAMES
end
我绝对不会在几个小时内使用 jsonb,为什么不使用列?根据我的经验,jsonb 总是有缺点,以后会出现(搜索记录、更改值、排序......等)
枚举列是可选的,它为您提供了一些不错的使用方法。
2赞
Schwern
8/19/2022
#2
Rails 不能很好地支持 JSONB,这非常适合传统关系。
但是,不要创建包含 28 列的表。如果您发现自己将列表制作为列,则可能存在设计问题。相反,为一周中的每一天/开盘/收盘时间制作一个一行的表格。
create_table :store_hours do |t|
t.references :store, null: false
# Store the day of week using an integer and then
# Use ActiveRecord::Enum to turn it into strings.
t.day_of_week :integer, null: false
# Use the Time and Interval types so you can do time math easily.
t.open_at :time, null: false
t.close_at :time, null: false
end
class StoreHour < ApplicationRecord do
belongs_to :store
enum :day_of_week, monday: 0, tuesday: 1, wednesday: 2, thursday: 3, friday: 4, saturday: 5, sunday: 6
# Check if new hours overlap with exisiting hours.
validates :open_at,
scope: [:store_id, :day_of_week]
conditions: ->(store_hour) {
where(
"open_at <= ? and close_at => ?",
store_hour.close_at, store_hour.open_at
)
}
end
class Store < ApplicationRecord do
# A store has many store hours. They will be deleted when the store is.
# Deleting is ok here, not destroy, because there's nothing special to do
# when the StoreHours are deleted.
has_many :store_hours, dependent: :delete
end
这让商店可以随心所欲地拥有复杂的开门/关门时间。
请参阅构建复杂窗体,了解如何编写控制器和视图以添加、编辑和删除 StoreHours。
一些评论:
- 请参阅活动记录关联,了解依赖项的工作原理以及如何使用关联的 StoreHours。
- 我添加了一个独特的验证,以确保商店没有任何重叠的开门/关门时间。请参阅validates_uniqueness_of和活动记录验证。
- 星期几存储为整数。该类使用 ActiveRecord::Enum 在整数和字符串之间映射。这样一来,您仍然可以将值称为,但它存储为数字以节省空间和时间并防止拼写错误。我已经明确了字符串和数字之间的映射,以防需要添加更多日期(例如:周末、节假日)。
"monday"
- 在这种模式下,商店必须在午夜之前关闭。
- 如果您改为存储商店的营业时间和营业时间,则商店将在午夜之后营业。例如,表示从中午到第二天凌晨 1 点。这更复杂,但也更灵活。
open_at: 12pm, open_for: 13 hours
- 或者,您可以将 open_at/closed_at 存储为时间戳,但始终使用相同的日期:2000-01-01。午夜后关闭的商店将是 2000-01-02。
- Postgres 时间类型映射到 Ruby Time 对象,但日期为 2000-01-01。
- 我们用来确保当商店被销毁时,其 StoreHours 也会被删除。
has_many :store_hours, dependent: :delete
- 下面是时间重叠验证逻辑的演示。
评论
0赞
Ben
8/19/2022
有趣的方法,但是如果商店有午休时间,该怎么办?
1赞
Schwern
8/19/2022
@Ben同一天为同一家商店提供两个 StoreHours。
0赞
Ben
8/19/2022
是的,但是你如何做到这一点,用表格??
0赞
Schwern
8/19/2022
@Ben请参阅构建复杂表单。
0赞
Ben
8/20/2022
问题不在于如何构建表单,而在于 ux 方法;)
0赞
gapsf
8/19/2022
#3
对于关系数据库,请使用 5 列表:
store_id
dayofweek (enumerated type: 1-Sun..7-Sat)
period_begin (time type, including)
period_end (time type, excluding)
period_type (enumerated type: 1-opened, 2-whatever_state1, ...)
默认情况下,将存储视为已关闭,并仅存储具有其他类型(如已打开)的记录。
1 2 9:30 12:00 1 (opened)
1 2 14:00 18:00 1 (opened)
1 3 9:00 20:00 1 (opened)
1 4 0:00 24:00 2 (whatever_state1)
1 5 0:00 24:00 3 (whatever_state2)
如果商店和用户位于不同的时区,您可以以 UTC 存储period_begin/结束,并相应地计算和显示当地时间和星期几。
评论
0赞
Schwern
8/19/2022
“关闭”状态是多余的,并会引发错误:打开和关闭时间重叠,缺少关闭时间。有必要吗?
评论