我是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解决了这个问题。我在下面的评论中写了解决方案
答案 0 :(得分: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
答案 1 :(得分: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)
答案 2 :(得分: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]) ))