有许多关联对象计数

时间:2014-05-23 05:10:12

标签: ruby-on-rails ruby activerecord

在我的应用程序中,我有模型Car has_many:reservations

class Car < ActiveRecord::Base
 has_many :reservations
end

class Reservation < Activerecord::Base
  belongs_to :car
end

现在我想从数据库中取出所有没有预约的汽车。我怎么能这样做?

编辑: 感谢大家的帮助,但现在我还有其他问题: 我的搜索方法搜索没有预订或没有预订的汽车我正确的日期。它看起来像这样:

def self.is_not_reservated(handover_date, return_date)
  without_reservation = where("cars.id NOT IN (?)", Reservation.pluck(:car_id)) 
  with_reservation = joins(:reservations).where.not("reservations.reception_time <= ? 
    AND reservations.return_time >= ?", return_date, handover_date) 
end

现在,当我尝试添加这两个ActiveRecordRelation对象时,我将拥有一个数组,但我仍然希望拥有一个ActiveRecordRelation对象...... 有没有办法解决这个问题。 提前谢谢!

我的解决方案: 我不知道这是做这种事情的好方法,但它按预期工作:)

def is_not_reservated(handover_date, return_date)
      without_reservation = where("cars.id NOT IN (?)", Reservation.pluck(:car_id)) 
      with_reservation = joins(:reservations).where.not("reservations.reception_time <= ? 
        AND reservations.return_time >= ?", return_date, handover_date) 
      cars = without_reservation + with_reservation
      where(id: cars.map(&:id))
    end

6 个答案:

答案 0 :(得分:3)

您需要使用左外连接。它应该是下面的内容,

Car.joins('LEFT OUTER JOIN reservations ON reservations.car_id = car.id')

有关详细信息,请参阅此rails文档http://guides.rubyonrails.org/active_record_querying.html#using-a-string-sql-fragment

答案 1 :(得分:3)

您也可以在数据库中完成所有操作,即使不必在查询中使用字符串:

Car.includes(:reservations).where(reservations: {car_id: nil})

# SELECT * FROM "cars"
# LEFT OUTER JOIN "reservations" ON "reservations"."car_id" = "cars"."id"
# WHERE "reservations"."car_id" IS NULL

答案 2 :(得分:2)

你在找这个吗?

Car.where("cars.id NOT IN (?)", Reservation.pluck(:car_id))

答案 3 :(得分:2)

要进一步RSB的回答,您可能还想使用scope(基本上是类方法):

#app/models/car.rb
Class Car < ActiveRecord::Base
   scope :unreserved, -> { where("cars.id NOT IN (?)", Reservation.pluck(:car_id)) }
end

这样您就可以拨打Car.unreserved

答案 4 :(得分:1)

这样的事情?

Car.joins(:reservations).group("cars.id HAVING count(reservations.id) > 0")
Car.joins(:reservations).group("cars.id").having("count(reservations.id) > ?",0)

答案 5 :(得分:0)

您可以创建一个方法,在 apps / models / car.rb 中运行纯SQL查询:

def unreserved_cars
  sql = "Select * from #{self.table_name} where(#{Reservation.table_name}.car_id != id)"
  records_array = ActiveRecord::Base.connection.execute(sql)
end

或者,如果您需要ActiveRecord::Relation个对象,则可以在 apps / models / car.rb 中创建一个范围:

scope :unreserved_cars, -> { where("#{Reservation.table_name}.car_id != id") }

然后你可以做类似的事情:

Car.unreserved_cars