Sql 更快的数据库,用于Rails可用性日历
我正在构建一个RubyonRails旅馆床位预订系统,我正在寻找一种更好的方式来加载我的可用日历。下面的代码非常适合显示床的可用性(见附图),但我觉得多个数据库调用对服务器来说太麻烦了,必须有一种更快的方法来处理数据 型号: user.rb bed.rb(用户id、名称) guest.rb(用户id、姓名、电话、地址、电子邮件) reservation.rb(用户id、床id、客人id、日期) 使用者是旅馆的主人。他们创造尽可能多的床,并给他们起个名字(床1、床2、双阁楼、主楼2楼等) 每个用户都有许多客人,这些人在特定日期睡在他们的旅馆里 使用simple_calendar gem,我获得当月的所有预订并处理它们以显示每周视图 排序逻辑: 第1步。在一周的第一天迭代当前用户的床位。(简单日历提供每天的预订) 第2步。如果床上有当天的预订(!=nil),请填写床名和预订客人的姓名 第3步。如果床上没有预约,请填写床名和“空” 第4步。完成一周的第一天后,移动到第二天并重复。(简单的日历会处理这个问题) 正如我所说,下面的代码是有效的,但是当一个用户有50张床位时,它每天会打50个WHERE电话,所以7天的日历会打350个WHERE电话(如果需要找到客人的名字,还会打更多) 如果您需要更多信息或解释,请告诉我。谢谢Sql 更快的数据库,用于Rails可用性日历,sql,ruby-on-rails,ruby,Sql,Ruby On Rails,Ruby,我正在构建一个RubyonRails旅馆床位预订系统,我正在寻找一种更好的方式来加载我的可用日历。下面的代码非常适合显示床的可用性(见附图),但我觉得多个数据库调用对服务器来说太麻烦了,必须有一种更快的方法来处理数据 型号: user.rb bed.rb(用户id、名称) guest.rb(用户id、姓名、电话、地址、电子邮件) reservation.rb(用户id、床id、客人id、日期) 使用者是旅馆的主人。他们创造尽可能多的床,并给他们起个名字(床1、床2、双阁楼、主楼2楼等) 每个用户
= week_calendar events: @monthly_reservations, attribute: :date do |date, appts|
- current_user.beds.each do |bed|
- if bed.reservations.where(date: date).first != nil
- guest_name = bed.reservations.where(date: date).first.guest.abbreviated_name
%p{style: "border: 1px solid black; padding: 5px; font-size: 10px;"}
= "#{bed.name}: #{guest_name}"
- else
%p{style: "border: 1px solid black; padding: 5px; font-size: 10px;"}
= "#{bed.name}: Empty"
编辑:
理想的日历布局如下图所示:
然而,问题是使床位名称与正确的床位预订相符。如果5月2日只预订了两张床,即1号床和4号床,则代码不知道在最后插入4号床的预约之前保留两张空床。有道理吗
编辑#2:
@大卫德里奇,类似这样的:
像这样的
reservs={“[2017-05-01,床位1]”=>“guest_23”、“[2017-05-01,床位2]”=>“empty”}
编辑3
下面是加载一个只有5张床位的旅馆时日志的样子
Bed Load (0.3ms) SELECT "beds".* FROM "beds" WHERE "beds"."user_id" = $1 [["user_id", 1]]
Reservations Load (0.2ms) SELECT "reservations".* FROM "reservations" WHERE "reservations"."bed_id" = $1 AND "reservations"."date" = $2 ORDER BY "reservations"."id" ASC LIMIT 1 [["bed_id", 1], ["date", "2017-07-02"]]
Reservations Load (0.2ms) SELECT "reservations".* FROM "reservations" WHERE "reservations"."bed_id" = $1 AND "reservations"."date" = $2 ORDER BY "reservations"."id" ASC LIMIT 1 [["bed_id", 2], ["date", "2017-07-02"]]
Reservations Load (0.2ms) SELECT "reservations".* FROM "reservations" WHERE "reservations"."bed_id" = $1 AND "reservations"."date" = $2 ORDER BY "reservations"."id" ASC LIMIT 1 [["bed_id", 3], ["date", "2017-07-02"]]
Reservations Load (0.2ms) SELECT "reservations".* FROM "reservations" WHERE "reservations"."bed_id" = $1 AND "reservations"."date" = $2 ORDER BY "reservations"."id" ASC LIMIT 1 [["bed_id", 4], ["date", "2017-07-02"]]
Reservations Load (0.2ms) SELECT "reservations".* FROM "reservations" WHERE "reservations"."bed_id" = $1 AND "reservations"."date" = $2 ORDER BY "reservations"."id" ASC LIMIT 1 [["bed_id", 5], ["date", "2017-07-02"]]
Reservations Load (0.2ms) SELECT "reservations".* FROM "reservations" WHERE "reservations"."bed_id" = $1 AND "reservations"."date" = $2 ORDER BY "reservations"."id" ASC LIMIT 1 [["bed_id", 1], ["date", "2017-07-03"]]
Reservations Load (0.2ms) SELECT "reservations".* FROM "reservations" WHERE "reservations"."bed_id" = $1 AND "reservations"."date" = $2 ORDER BY "reservations"."id" ASC LIMIT 1 [["bed_id", 2], ["date", "2017-07-03"]]
Reservations Load (0.2ms) SELECT "reservations".* FROM "reservations" WHERE "reservations"."bed_id" = $1 AND "reservations"."date" = $2 ORDER BY "reservations"."id" ASC LIMIT 1 [["bed_id", 3], ["date", "2017-07-03"]]
Reservations Load (0.2ms) SELECT "reservations".* FROM "reservations" WHERE "reservations"."bed_id" = $1 AND "reservations"."date" = $2 ORDER BY "reservations"."id" ASC LIMIT 1 [["bed_id", 4], ["date", "2017-07-03"]]
Reservations Load (0.2ms) SELECT "reservations".* FROM "reservations" WHERE "reservations"."bed_id" = $1 AND "reservations"."date" = $2 ORDER BY "reservations"."id" ASC LIMIT 1 [["bed_id", 5], ["date", "2017-07-03"]]
Reservations Load (0.2ms) SELECT "reservations".* FROM "reservations" WHERE "reservations"."bed_id" = $1 AND "reservations"."date" = $2 ORDER BY "reservations"."id" ASC LIMIT 1 [["bed_id", 1], ["date", "2017-07-04"]]
Reservations Load (0.2ms) SELECT "reservations".* FROM "reservations" WHERE "reservations"."bed_id" = $1 AND "reservations"."date" = $2 ORDER BY "reservations"."id" ASC LIMIT 1 [["bed_id", 2], ["date", "2017-07-04"]]
Reservations Load (0.2ms) SELECT "reservations".* FROM "reservations" WHERE "reservations"."bed_id" = $1 AND "reservations"."date" = $2 ORDER BY "reservations"."id" ASC LIMIT 1 [["bed_id", 3], ["date", "2017-07-04"]]
Reservations Load (0.2ms) SELECT "reservations".* FROM "reservations" WHERE "reservations"."bed_id" = $1 AND "reservations"."date" = $2 ORDER BY "reservations"."id" ASC LIMIT 1 [["bed_id", 4], ["date", "2017-07-04"]]
Reservations Load (0.1ms) SELECT "reservations".* FROM "reservations" WHERE "reservations"."bed_id" = $1 AND "reservations"."date" = $2 ORDER BY "reservations"."id" ASC LIMIT 1 [["bed_id", 5], ["date", "2017-07-04"]]
Reservations Load (0.2ms) SELECT "reservations".* FROM "reservations" WHERE "reservations"."bed_id" = $1 AND "reservations"."date" = $2 ORDER BY "reservations"."id" ASC LIMIT 1 [["bed_id", 1], ["date", "2017-07-05"]]
Reservations Load (0.2ms) SELECT "reservations".* FROM "reservations" WHERE "reservations"."bed_id" = $1 AND "reservations"."date" = $2 ORDER BY "reservations"."id" ASC LIMIT 1 [["bed_id", 2], ["date", "2017-07-05"]]
Reservations Load (0.2ms) SELECT "reservations".* FROM "reservations" WHERE "reservations"."bed_id" = $1 AND "reservations"."date" = $2 ORDER BY "reservations"."id" ASC LIMIT 1 [["bed_id", 3], ["date", "2017-07-05"]]
Reservations Load (0.2ms) SELECT "reservations".* FROM "reservations" WHERE "reservations"."bed_id" = $1 AND "reservations"."date" = $2 ORDER BY "reservations"."id" ASC LIMIT 1 [["bed_id", 4], ["date", "2017-07-05"]]
Reservations Load (0.2ms) SELECT "reservations".* FROM "reservations" WHERE "reservations"."bed_id" = $1 AND "reservations"."date" = $2 ORDER BY "reservations"."id" ASC LIMIT 1 [["bed_id", 5], ["date", "2017-07-05"]]
Reservations Load (0.2ms) SELECT "reservations".* FROM "reservations" WHERE "reservations"."bed_id" = $1 AND "reservations"."date" = $2 ORDER BY "reservations"."id" ASC LIMIT 1 [["bed_id", 1], ["date", "2017-07-06"]]
Reservations Load (0.2ms) SELECT "reservations".* FROM "reservations" WHERE "reservations"."bed_id" = $1 AND "reservations"."date" = $2 ORDER BY "reservations"."id" ASC LIMIT 1 [["bed_id", 2], ["date", "2017-07-06"]]
Reservations Load (0.1ms) SELECT "reservations".* FROM "reservations" WHERE "reservations"."bed_id" = $1 AND "reservations"."date" = $2 ORDER BY "reservations"."id" ASC LIMIT 1 [["bed_id", 3], ["date", "2017-07-06"]]
Reservations Load (0.1ms) SELECT "reservations".* FROM "reservations" WHERE "reservations"."bed_id" = $1 AND "reservations"."date" = $2 ORDER BY "reservations"."id" ASC LIMIT 1 [["bed_id", 4], ["date", "2017-07-06"]]
Reservations Load (0.3ms) SELECT "reservations".* FROM "reservations" WHERE "reservations"."bed_id" = $1 AND "reservations"."date" = $2 ORDER BY "reservations"."id" ASC LIMIT 1 [["bed_id", 5], ["date", "2017-07-06"]]
Reservations Load (0.2ms) SELECT "reservations".* FROM "reservations" WHERE "reservations"."bed_id" = $1 AND "reservations"."date" = $2 ORDER BY "reservations"."id" ASC LIMIT 1 [["bed_id", 1], ["date", "2017-07-07"]]
Reservations Load (0.2ms) SELECT "reservations".* FROM "reservations" WHERE "reservations"."bed_id" = $1 AND "reservations"."date" = $2 ORDER BY "reservations"."id" ASC LIMIT 1 [["bed_id", 2], ["date", "2017-07-07"]]
Reservations Load (0.2ms) SELECT "reservations".* FROM "reservations" WHERE "reservations"."bed_id" = $1 AND "reservations"."date" = $2 ORDER BY "reservations"."id" ASC LIMIT 1 [["bed_id", 3], ["date", "2017-07-07"]]
Reservations Load (0.2ms) SELECT "reservations".* FROM "reservations" WHERE "reservations"."bed_id" = $1 AND "reservations"."date" = $2 ORDER BY "reservations"."id" ASC LIMIT 1 [["bed_id", 4], ["date", "2017-07-07"]]
Reservations Load (0.1ms) SELECT "reservations".* FROM "reservations" WHERE "reservations"."bed_id" = $1 AND "reservations"."date" = $2 ORDER BY "reservations"."id" ASC LIMIT 1 [["bed_id", 5], ["date", "2017-07-07"]]
Reservations Load (0.2ms) SELECT "reservations".* FROM "reservations" WHERE "reservations"."bed_id" = $1 AND "reservations"."date" = $2 ORDER BY "reservations"."id" ASC LIMIT 1 [["bed_id", 1], ["date", "2017-07-08"]]
Reservations Load (0.6ms) SELECT "reservations".* FROM "reservations" WHERE "reservations"."bed_id" = $1 AND "reservations"."date" = $2 ORDER BY "reservations"."id" ASC LIMIT 1 [["bed_id", 2], ["date", "2017-07-08"]]
Reservations Load (0.3ms) SELECT "reservations".* FROM "reservations" WHERE "reservations"."bed_id" = $1 AND "reservations"."date" = $2 ORDER BY "reservations"."id" ASC LIMIT 1 [["bed_id", 3], ["date", "2017-07-08"]]
Reservations Load (0.3ms) SELECT "reservations".* FROM "reservations" WHERE "reservations"."bed_id" = $1 AND "reservations"."date" = $2 ORDER BY "reservations"."id" ASC LIMIT 1 [["bed_id", 4], ["date", "2017-07-08"]]
Reservations Load (0.3ms) SELECT "reservations".* FROM "reservations" WHERE "reservations"."bed_id" = $1 AND "reservations"."date" = $2 ORDER BY "reservations"."id" ASC LIMIT 1 [["bed_id", 5], ["date", "2017-07-08"]]
编辑4
根据@davidardridge建议,我在控制器中创建了一个散列,并将其传递到我的视图中。结果非常好
控制器代码:
@reservations = {}
@monthly_reservations.each do |x|
@reservations[[x.date,x.bed_id]] = x.guest.try(:name)
end
以及查看代码:
= week_calendar events: @monthly_reservations, attribute: :date do |date, appts|
- current_user.beds.each do |bed|
- if @reservations[[date, bed.id]] != nil
%p{style: "border: 1px solid black; padding: 5px; font-size: 10px;"}
= "#{bed.name}: #{@reservations[[date, kennel.id]]}"
- else
%p{style: "border: 1px solid black; padding: 5px; font-size: 10px;"}
= "#{bed.name}:"
Robbie所描述的是批量捕获数据,以便在第二次传递时显示。您可以这样做:
@reservations = Reservations.where(bed_id: [ ... ], date: (from..to)).group_by do |r|
[r.bed_id, r.date]
end
其中,它返回一个单一结构,该结构应包含所有保留,并且可以使用bed_id
和日期轻松索引。如果需要,您可以将其转换为两层结构,但通常不是这样
迭代时:
- current_user.beds.each do |bed|
- reservation = @reservations[[bed.id,date]]
- if reservation
# ...
当您处理无法用加载链中的includes(…)
元素轻松表示的复杂相互依赖关系时,这种选择性但积极地加载记录的做法通常非常有效
另外,请记住,在Ruby中,逻辑上只有两个错误:literalfalse
和nil
。其他所有内容的计算结果在逻辑上都为true,包括0、空字符串、数组和散列。因此,比较!=nil几乎总是无关的和令人困惑的,特别是如果你像那样做双重否定,除非(x!=nil)
如果您希望能够根据数据库解析任意多个日期+床位对,您可以制作某种类型的预订密钥,该密钥是日期和床位id的组合,那么扫描这些就容易多了。你可以在(…)
中做一个WHERE-booking\u-token,并将其全部编入索引,性能和简洁。不过,要做好这件事需要一些事先的计划YYYY-MM-DD-bed_id
可以作为第一个通行证。对于您的查看代码,我会尝试:
= week_calendar events: @monthly_reservations, attribute: :date do |date, appts|
- current_user.beds.each do |bed|
%p{style: "border: 1px solid black; padding: 5px; font-size: 10px;"}
= [bed.name, @reservations[[date, bed.id]]].compact.join(":")
“我觉得多个WHERE数据库调用对服务器来说太麻烦了”。这是直觉,可能正确,也可能不正确。找到答案的唯一方法是仔细查看log/development.log
,查看查询的执行情况。通常,最好始终在窗口中打开tail-f log/development.log
,以了解加载页面和开发功能时代码的效率和丑陋程度。为什么不只查询一次表,以获取当前用户当月的所有记录,然后迭代结果?这正是@monthly\u reservations变量所包含的内容,即当前用户当月的所有预订。然而,WHEREs进来了,因为我需要展示旅馆所有的床位,然后是谁,如果有的话,住在这张床上。塔德曼,我完全同意直觉部分。也许这不会让服务器负担太重,但当我查看日志并看到每次加载页面时都会出现无休止的结果时,我很担心。你应该能够运行一个查询,获取bed、date和user,并使用键[bed,date]
和值guest
构建一个散列。然后你可以按你认为最合理的顺序遍历你的床和日期,从散列中查找每个日期/床组合的任何客人。@davidardridge,我认为这听起来是个好主意。我只是需要一些额外的智慧来帮助我思考其他可能的方法。我的代码可以用,但很臭。谢谢@davidridge。这仅仅是一个重构,还是我缺少某种类型的性能增强?我承认,我的Ruby基础知识并不高。看起来我可能需要再次打开POODR!:)@帕特里克·琼斯,可怜的FTW博士!这是一个消除冗余的重构。