0

我是 Rails 新手,我知道这是一个简单的问题,但它让我发疯。我的应用是用 Ruby 1.9.2 和 Rails 3.1 构建的。我正在编写一个应用程序来管理类似酒店的客房预订。所以这个类代表住宿:

class Accommodation < ActiveRecord::Base
  has_many :reservations, :dependent => :destroy
end

这是预订:

class Reservation < ActiveRecord::Base
  belongs_to :accommodation
end

预订确实有一个名为accommodation_id存储住宿 ID 的字段

现在我必须检查给定日期范围内的可用住宿,所以我写了这个方法:

def self.check_availability(params)
    # This return the unavailables accommodations
    ids_to_exclude = Reservation.select(:accommodation_id).where('start_date < ? AND end_date > ?', params[:reservation_end_date], params[:reservation_start_date])

    # HERE IS THE PROBLEM
    accommodations = Accommodation.where("id NOT IN (?)", ids_to_exclude )

    accommodations
  end

第一个查询有效,但第二个返回:

SELECT `accommodations`.* FROM `accommodation` WHERE (id NOT IN (NULL))

我试图输出ids_to_exclude并且不是NULL

我究竟做错了什么?

更新:

我用 Arel 解决了这个问题。我在下面的评论中写了解决方案

4

3 回答 3

0

ids_to_exclude需要提取ID

尝试

 reservations_to_exclude = Reservation.select(:accommodation_id).where('start_date < ? AND end_date > ?', params[:reservation_end_date], params[:reservation_start_date])

 reservations_to_exclude.each do |r|
    ids_to_exclude << r.accommodation_id
 end
于 2012-06-21T18:23:19.890 回答
0

您不需要为此进行两次数据库命中,并且您可能应该在您在那里时将其设为范围。此外,我将调用传递params给模型方法的错误形式,您应该明确说明参数以使事情更易于理解和维护:

class Accommodation < ActiveRecord::Base
    def self.available_between(start_date, end_date)
        joins(:reservations).where('reservations.start_date >= ? and reservations.end_date <= ?', end_date, start_date)
    end
end

然后你可以这样说:

all_available = Accommodation.available_between(params[:reservation_start_date], params[:reservation_end_date]).all

或这个:

some = Accommodation.available_between(params[:reservation_start_date], params[:reservation_end_date])
                    .where(some_other_conditions)
                    .limit(10)
                    .order(:price)
于 2012-06-21T19:04:42.413 回答
0

最后我找到了 Arel 的解决方案:

reservations = Reservation.arel_table

available_rooms = Accommodation.where(:id => reservations.project(:accommodation_id)
      .where( reservations[:start_date].lt(params[:reservation_end_date]) )
      .where( reservations[:end_date].gt(params[:reservation_start_date]) ))
于 2012-06-21T19:08:04.360 回答