Sql 更快的数据库,用于Rails可用性日历

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楼等) 每个用户

我正在构建一个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电话(如果需要找到客人的名字,还会打更多)

如果您需要更多信息或解释,请告诉我。谢谢

= 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中,逻辑上只有两个错误:literal
false
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博士!这是一个消除冗余的重构。