Ruby on rails 如何对日期范围进行分组、计数和映射?

Ruby on rails 如何对日期范围进行分组、计数和映射?,ruby-on-rails,json,ruby,ruby-on-rails-5,Ruby On Rails,Json,Ruby,Ruby On Rails 5,我正在研究一个预订模型,在这个模型中,物品可以在任意的时间段内租用,每个物品每天都有最大的预订量,这基本上就是物品的数量。显然,我想检查一个项目是否可以预订,或者在预订之前是否已经达到最大容量。我考虑在Booking模型中创建一个方法,该方法返回一个包含所有不可用日期和项目的对象数组,以便所需的输出为: [ {rentalitem_id: 1, unavailable: '01-03-2018'}, {rentalitem_id: 2, unavailable: '02-03-2018'},

我正在研究一个预订模型,在这个模型中,物品可以在任意的时间段内租用,每个物品每天都有最大的预订量,这基本上就是物品的数量。显然,我想检查一个项目是否可以预订,或者在预订之前是否已经达到最大容量。我考虑在Booking模型中创建一个方法,该方法返回一个包含所有不可用日期和项目的对象数组,以便所需的输出为:

[ {rentalitem_id: 1, unavailable: '01-03-2018'},
  {rentalitem_id: 2, unavailable: '02-03-2018'},
  {rentalitem_id: 1, unavailable: '01-03-2018'} ]
然后,我可以使用JSON呈现该方法,以便在我的frontend Vue.js中访问它,在那里我可以简单地禁用相应项目的所有日期。当然,在处理预订时,我还将在后端验证日期是否可用

第一个问题:你觉得这个主意怎么样?也许有更优雅的解决方案如何实现这一点

到目前为止,我编写的预订模型中的方法如下所示:

class Booking < ApplicationRecord

 ...

   scope :future_bookings, -> (time) { where("rental_start >= ?", time) }

 ...

   def self.item_unavailable
      sorted_booking = future_bookings(Time.now).map do |booking|
         { rentalitem_id: booking.rentalitem_id,
           dates: ((booking.rental_start.to_date..booking.rental_end.to_date).map{ |date| date.strftime("%b %d %y") }).to_a }
      end
      merged_bookings = sorted_booking.group_by{ |key| key[:rentalitem_id]}.each do |_, value|
          value.map!{ |arr| arr[:dates] }
      end
   end
end
其思想是计算数组中所有相交的日期,并返回达到相应rentalitem最大容量的日期,而最大容量应该从rentalitem模型中查询。然而,我被困在这里,尝试了我能想象到的一切来完成这个动作。我曾考虑使用inject返回不可用的值,但在此之前,我需要计算相交日期

假设第一个rentalitem的最大容量为每天两次预订,而不是3月1日。此外,假设第二个rentalitem的最大容量为每天三次预订。因此,按照示例,3月2日不可用

在此,我非常感谢您的帮助:-

我将创建一个RentalItemAvailability类,传递rental\u项目和日期,以检查给定日期的可用性,而不是试图制造一些非常奇怪的东西,找出如何通过一系列日期实现相同的功能。。。比如:

class RentalItemAvailability
  delegate :maximum_capacity_per_day, :bookins, to: :@rental_item

  def initialize(rental_item, date)
    @rental_item = rental_item
    @date = date
  end

  def available?
    bookings_on_date < maximum_capacity_per_day
  end

  def bookins_on_date
    bookins
     .where('rental_start between :date and :date and rental_end between :date and :date', @date).count
  end
end      

这样,您可以验证每一天,并将租赁项目标记为可用/不可用

我相信您要求修改项目不可用,以返回每个项目/日期的计数。要做到这一点,您可能需要基于包含日期和计数的item_id在ruby中构建一个哈希。大概是这样的:

{
  1: {
    "Feb 28 18": 1,
    "Mar 01 18": 2
  }
}
另一种方法是为每个日期存储单独的预订,而不是有开始和结束日期。这最终会产生更多的记录,但我相信这将是一种更直观的方法。 查询类似于上述散列的结果的示例:

future_bookings.group(:rentalitem_id, :date).count
# {[1, "date_from_db"]=>2, [2, "date2_from_db"]=>1}

谢谢你的回答!事实上,我一开始就考虑了你建议的方法,我认为这绝对是在服务器端验证预订的最佳方法。但是,为了在客户端实现这一点,我需要执行以下选项之一:每次用户更改日期时执行API调用。B在页面加载时呈现所有未来预订,并使用Vue评估日期是否可用。对于前端,您建议采用哪种方法?我会选择选项A,并可能会寻找一种使用redis缓存某些数据的方法,例如,谢谢您的帮助!构建一个包含日期和计数而不是不可用日期的哈希也是一个好主意。我要玩玩这个,看看它能把我带到哪里去。不过,我不太喜欢单独存储日期的想法,即使查询可能更简单。
future_bookings.group(:rentalitem_id, :date).count
# {[1, "date_from_db"]=>2, [2, "date2_from_db"]=>1}