What I want to do is very simple but I'm trying to find the best or most elegant way to do this. The Rails application I'm building now will have a schedule of daily classes. For each class the fields relevant to this question are:
我想要做的很简单,但我正在努力找到最好或最优雅的方式来做到这一点。我现在正在构建的Rails应用程序将具有每日课程的时间表。对于每个类,与此问题相关的字段为:
- Day of the week
- Starting time
- Ending time
一周中的天
A single entry could be something such as:
单个条目可能是这样的:
- day of week: Wednesday
- starting time: 10:00 am
- ending time: Noon
星期几:星期三
开始时间:上午10:00
结束时间:中午
Also I must mention that it's a bi-lingual Rails 2.2 app and I'm using the native i18n Rails feature. I actually have several questions.
此外,我必须提到它是一个双语Rails 2.2应用程序,我正在使用本机i18n Rails功能。我其实有几个问题。
Regarding the day of the week, should I create an extra table with list of days, or is there a built-in way to create that list on the fly? Keep in mind these days of the week will have to be rendered in English or Spanish in the schedule view depending on the locale variable.
关于一周中的哪一天,我应该创建一个包含日期列表的额外表格,还是有一种内置的方式来动态创建该列表?请记住,一周中的这几天必须在日程表视图中以英语或西班牙语呈现,具体取决于区域设置变量。
While querying the schedule I will need to group and order the results by weekday, from Monday to Sunday, and of course order the classes within each day by starting time.
在查询时间表时,我需要在星期一到星期日的工作日对结果进行分组和排序,当然也可以按照开始时间在每天内订购课程。
Regarding the starting time and ending time of each class would you use datetime fields or integer fields? If the latter how would you implement this exactly?
关于每个类的开始时间和结束时间,您会使用datetime字段还是整数字段?如果是后者你将如何实现这一点?
Looking forward to read the different suggestions you guys will come up with.
期待阅读你们提出的不同建议。
3 个解决方案
#1
I would just store the day of the week as an integer. 0 => Monday ... 6 => Sunday (or any way you want. ie. 0 => Sunday). Then store the start time and end time as Time.
我只是将星期几存储为整数。 0 =>星期一... 6 =>星期日(或任何你想要的方式。即0 =>星期日)。然后将开始时间和结束时间存储为时间。
That would make grouping really easy. All you would have to do is sort by the day of the week and the start time.
这将使分组变得非常简单。您所要做的就是按星期几和开始时间排序。
You can display this in multiple ways, but here is what I would do.
你可以用多种方式显示它,但这就是我要做的。
-
Have functions like:
@sunday_classes = DailyClass.find_sunday_classes
that returns all the classes for Sunday sorted by start time. Then repeat for each day.具有以下函数:@sunday_classes = DailyClass.find_sunday_classes,它返回按开始时间排序的星期日的所有类。然后重复每一天。
def find_sunday_classes find_by_day_of_week(1, :order -> 'start_time') end
Note: find_by probably should have id at the end but that's just preference in how you want to name the column.
注意:find_by可能最后应该有id,但这只是你想要如何命名列的首选项。
-
If you want the full week then call all seven from the controller and loop trough them in the view. You could even create detail pages for each day.
如果你想要整整一周,那么从控制器中调用所有七个,并在视图中循环它们。您甚至可以为每一天创建详细信息页面。
- Translation is the only tricky part. You can create a helper function that takes an integer and returns the text for the appropriate day of the week based on local.
翻译是唯一棘手的部分。您可以创建一个带有整数的辅助函数,并根据本地返回一周中相应日期的文本。
That's very basic. Nothing complicated.
这是非常基本的。没什么复杂的。
#2
If your data is a Time then I would store that as a Time - otherwise you will always have to convert it out of the database when you do date and time related operations on it. The day is redundant data, as it will be part of the time object.
如果您的数据是时间,那么我会将其存储为时间 - 否则,当您对数据库进行日期和时间相关操作时,您将始终必须将其转换出数据库。这一天是冗余数据,因为它将成为时间对象的一部分。
This should mean that you don't need to store a list of days.
这意味着您不需要存储天数列表。
If t is a time then
如果t是时间
t.strftime('%A')
will always give you the day as a string in English. This could then be translated by i18n as required.
总会给你一天英文字符串。然后可以根据需要通过i18n进行翻译。
So you only need to store starting time and ending time, or starting time and duration. Both should be equivalent. I would be tempted to store ending time myself, in case you need to do data manipulations on ending times, which therefore won't have to be calculated.
所以你只需要存储开始时间和结束时间,或者开始时间和持续时间。两者都应该是等价的。我自己会想要存储结束时间,以防你需要对结束时间进行数据处理,因此不必计算。
I think most of the rest of what you describe should also fall out of storing time data as instances of Time.
我认为你所描述的大部分内容也应该不再存储时间数据作为时间的实例。
Ordering by week day and time will just be a matter of ordering by your time column. i.e.
按工作日和时间排序只需按时间栏排序。即
daily_class.find(:all, :conditions => ['whatever'], :order => :starting_time)
Grouping by day is a little more tricky. However this is an excellent post on how to group by week. Grouping by day will be analogous.
白天分组比较棘手。然而,这是一篇关于如何按周分组的优秀文章。白天分组将是类似的。
If you are dealing with non-trivial volumes of data, it may be better to do it in the database, with a find_by_sql
and that may depend on your database's time and date functionality, but again storing the data as a Time will also help you here. For example in Postgresql (which I use), getting the week of a class is
如果你正在处理数据的不平凡的体积,它可能会更好做数据库,用的find_by_sql和可能取决于你的数据库的时间和日期的功能,但同样存储数据的时间也将帮助你这里。例如在Postgresql(我使用的)中,获取课程周
date_trunc('week', starting_time)
which you can use in a Group By clause, or as a value to use in some loop logic in rails.
您可以在Group By子句中使用它,或者作为在rails中的某些循环逻辑中使用的值。
#3
Re days-of-week, if you need to have e.g. classes that meet 09:00-10:00 on MWF, then you could either use a separate table for days a class meets (keyed by both class ID and DOW) or be evil (i.e. non-normalized) and keep the equivalent of an array of DOW in each class. The classic argument is this:
如果你需要,例如每周重复一天在MWF上遇到09:00-10:00的课程,那么你可以在一个班级遇到的日子里使用一个单独的表(由班级ID和DOW键入)或者是邪恶的(即非标准化的)并保持相当于每个班级的DOW数组。经典的论点是这样的:
- The separate table can be indexed in a way to support either class-oriented or DOW-oriented selects, but takes a bit more glue to put the entire picture together for a class.
- The array-of-DOW is simpler to visualize for beginning programmers and slightly simpler to code about, but means that reasoning about DOW requires looking at all classes.
单独的表可以以支持面向类或面向DOW的选择的方式编制索引,但需要更多的粘合剂以将整个图片放在一起用于类。
对于初学程序员来说,DOW数组更容易可视化,而对于代码来说稍微简单一些,但这意味着有关DOW的推理需要查看所有类。
If this is only for your personal class schedule, do what gets you the value you're looking for, and live with the consequences; if you're trying to build a real system for multiple users, I'd go with a separate table. All those normalization rules are there for a reason.
如果这只是为了您的个人课程安排,那么做什么可以让您获得所需的价值,并承担后果;如果你想为多个用户构建一个真实的系统,我会选择一个单独的表。所有这些规范化规则都是有原因的。
As far as (human-readable) DOW names, that's a presentation-layer issue, and shouldn't be in the core concept of DOW. (Suppose you decided to move to Montreal, and needed French? That should be another "face" and not a change to the core implementation.)
至于(人类可读的)DOW名称,这是一个表示层问题,而不应该是DOW的核心概念。 (假设你决定搬到蒙特利尔,需要法国人?这应该是另一个“面子”而不是对核心实施的改变。)
As for starting/ending times, again the issue is your requirements. If all classes begin and end at hour (x:00) boundaries, you could certainly use 0..23 as the hours of the day. But then your life would be miserable as soon as you had to accommodate that 45-minute seminar. As the old commercial said, "Pay me now or pay me later."
至于开始/结束时间,问题再次是您的要求。如果所有类都以小时(x:00)边界开始和结束,那么你当然可以使用0..23作为一天中的小时数。但是,一旦你不得不接受这个45分钟的研讨会,你的生活就会变得悲惨。正如旧商业广告所说:“现在付钱给我,或者以后给我付款。”
One approach would be to define your own ClassTime concept and partition all reasoning about times to that class. It could start with a simplistic representation (integral hours 0..23, or integral minutes after midnight 0..1439) and then "grow" as needed.
一种方法是定义自己的ClassTime概念,并将有关时间的所有推理划分到该类。它可以从简单的表示开始(整数小时0..23,或午夜0..1439之后的整数分钟),然后根据需要“增长”。
#1
I would just store the day of the week as an integer. 0 => Monday ... 6 => Sunday (or any way you want. ie. 0 => Sunday). Then store the start time and end time as Time.
我只是将星期几存储为整数。 0 =>星期一... 6 =>星期日(或任何你想要的方式。即0 =>星期日)。然后将开始时间和结束时间存储为时间。
That would make grouping really easy. All you would have to do is sort by the day of the week and the start time.
这将使分组变得非常简单。您所要做的就是按星期几和开始时间排序。
You can display this in multiple ways, but here is what I would do.
你可以用多种方式显示它,但这就是我要做的。
-
Have functions like:
@sunday_classes = DailyClass.find_sunday_classes
that returns all the classes for Sunday sorted by start time. Then repeat for each day.具有以下函数:@sunday_classes = DailyClass.find_sunday_classes,它返回按开始时间排序的星期日的所有类。然后重复每一天。
def find_sunday_classes find_by_day_of_week(1, :order -> 'start_time') end
Note: find_by probably should have id at the end but that's just preference in how you want to name the column.
注意:find_by可能最后应该有id,但这只是你想要如何命名列的首选项。
-
If you want the full week then call all seven from the controller and loop trough them in the view. You could even create detail pages for each day.
如果你想要整整一周,那么从控制器中调用所有七个,并在视图中循环它们。您甚至可以为每一天创建详细信息页面。
- Translation is the only tricky part. You can create a helper function that takes an integer and returns the text for the appropriate day of the week based on local.
翻译是唯一棘手的部分。您可以创建一个带有整数的辅助函数,并根据本地返回一周中相应日期的文本。
That's very basic. Nothing complicated.
这是非常基本的。没什么复杂的。
#2
If your data is a Time then I would store that as a Time - otherwise you will always have to convert it out of the database when you do date and time related operations on it. The day is redundant data, as it will be part of the time object.
如果您的数据是时间,那么我会将其存储为时间 - 否则,当您对数据库进行日期和时间相关操作时,您将始终必须将其转换出数据库。这一天是冗余数据,因为它将成为时间对象的一部分。
This should mean that you don't need to store a list of days.
这意味着您不需要存储天数列表。
If t is a time then
如果t是时间
t.strftime('%A')
will always give you the day as a string in English. This could then be translated by i18n as required.
总会给你一天英文字符串。然后可以根据需要通过i18n进行翻译。
So you only need to store starting time and ending time, or starting time and duration. Both should be equivalent. I would be tempted to store ending time myself, in case you need to do data manipulations on ending times, which therefore won't have to be calculated.
所以你只需要存储开始时间和结束时间,或者开始时间和持续时间。两者都应该是等价的。我自己会想要存储结束时间,以防你需要对结束时间进行数据处理,因此不必计算。
I think most of the rest of what you describe should also fall out of storing time data as instances of Time.
我认为你所描述的大部分内容也应该不再存储时间数据作为时间的实例。
Ordering by week day and time will just be a matter of ordering by your time column. i.e.
按工作日和时间排序只需按时间栏排序。即
daily_class.find(:all, :conditions => ['whatever'], :order => :starting_time)
Grouping by day is a little more tricky. However this is an excellent post on how to group by week. Grouping by day will be analogous.
白天分组比较棘手。然而,这是一篇关于如何按周分组的优秀文章。白天分组将是类似的。
If you are dealing with non-trivial volumes of data, it may be better to do it in the database, with a find_by_sql
and that may depend on your database's time and date functionality, but again storing the data as a Time will also help you here. For example in Postgresql (which I use), getting the week of a class is
如果你正在处理数据的不平凡的体积,它可能会更好做数据库,用的find_by_sql和可能取决于你的数据库的时间和日期的功能,但同样存储数据的时间也将帮助你这里。例如在Postgresql(我使用的)中,获取课程周
date_trunc('week', starting_time)
which you can use in a Group By clause, or as a value to use in some loop logic in rails.
您可以在Group By子句中使用它,或者作为在rails中的某些循环逻辑中使用的值。
#3
Re days-of-week, if you need to have e.g. classes that meet 09:00-10:00 on MWF, then you could either use a separate table for days a class meets (keyed by both class ID and DOW) or be evil (i.e. non-normalized) and keep the equivalent of an array of DOW in each class. The classic argument is this:
如果你需要,例如每周重复一天在MWF上遇到09:00-10:00的课程,那么你可以在一个班级遇到的日子里使用一个单独的表(由班级ID和DOW键入)或者是邪恶的(即非标准化的)并保持相当于每个班级的DOW数组。经典的论点是这样的:
- The separate table can be indexed in a way to support either class-oriented or DOW-oriented selects, but takes a bit more glue to put the entire picture together for a class.
- The array-of-DOW is simpler to visualize for beginning programmers and slightly simpler to code about, but means that reasoning about DOW requires looking at all classes.
单独的表可以以支持面向类或面向DOW的选择的方式编制索引,但需要更多的粘合剂以将整个图片放在一起用于类。
对于初学程序员来说,DOW数组更容易可视化,而对于代码来说稍微简单一些,但这意味着有关DOW的推理需要查看所有类。
If this is only for your personal class schedule, do what gets you the value you're looking for, and live with the consequences; if you're trying to build a real system for multiple users, I'd go with a separate table. All those normalization rules are there for a reason.
如果这只是为了您的个人课程安排,那么做什么可以让您获得所需的价值,并承担后果;如果你想为多个用户构建一个真实的系统,我会选择一个单独的表。所有这些规范化规则都是有原因的。
As far as (human-readable) DOW names, that's a presentation-layer issue, and shouldn't be in the core concept of DOW. (Suppose you decided to move to Montreal, and needed French? That should be another "face" and not a change to the core implementation.)
至于(人类可读的)DOW名称,这是一个表示层问题,而不应该是DOW的核心概念。 (假设你决定搬到蒙特利尔,需要法国人?这应该是另一个“面子”而不是对核心实施的改变。)
As for starting/ending times, again the issue is your requirements. If all classes begin and end at hour (x:00) boundaries, you could certainly use 0..23 as the hours of the day. But then your life would be miserable as soon as you had to accommodate that 45-minute seminar. As the old commercial said, "Pay me now or pay me later."
至于开始/结束时间,问题再次是您的要求。如果所有类都以小时(x:00)边界开始和结束,那么你当然可以使用0..23作为一天中的小时数。但是,一旦你不得不接受这个45分钟的研讨会,你的生活就会变得悲惨。正如旧商业广告所说:“现在付钱给我,或者以后给我付款。”
One approach would be to define your own ClassTime concept and partition all reasoning about times to that class. It could start with a simplistic representation (integral hours 0..23, or integral minutes after midnight 0..1439) and then "grow" as needed.
一种方法是定义自己的ClassTime概念,并将有关时间的所有推理划分到该类。它可以从简单的表示开始(整数小时0..23,或午夜0..1439之后的整数分钟),然后根据需要“增长”。