我需要一次删除大量记录,我需要根据另一个与“belongs_to”关系相关的模型中的条件来执行此操作。我知道我可以遍历每个检查条件,但这需要我的大记录集永远,因为对于每个“belongs_to”它会进行单独的查询。
这是一个例子。我有一个“产品”模型,“belongs_to”是一个“艺术家”,可以说艺术家有一个属性“is_disabled”。
如果我想删除所有属于残疾艺术家的产品,我希望能够做到这样的事情:
Product.delete_all(:joins => :artist, :conditions => ["artists.is_disabled = ?", true])
这可能吗?我以前在SQL中直接完成了这项工作,但不确定是否可以通过rails完成。
答案 0 :(得分:4)
问题是delete_all会丢弃所有的连接信息(这是正确的)。你想要做的是将其作为一个内部选择。
如果你正在使用Rails 3,你可以创建一个可以满足你想要的范围:
class Product < ActiveRecord::Base
scope :with_disabled_artist, lambda {
where("product_id IN (#{select("product_id").joins(:artist).where("artist.is_disabled = TRUE").to_sql})")
}
end
您查询呼叫然后变为
Product.with_disabled_artist.delete_all
您也可以使用相同的内联查询,但这不是很优雅(或自我记录):
Product.where("product_id IN (#{Product.select("product_id").joins(:artist).where("artist.is_disabled = TRUE").to_sql})").delete_all
答案 1 :(得分:1)
在Rails 4中(我在4.2上测试过)你几乎可以做OP最初想要的方式
Application.joins(:vacancy).where(vacancies: {status: 'draft'}).delete_all
将给出
DELETE FROM `applications` WHERE `applications`.`id` IN (SELECT id FROM (SELECT `applications`.`id` FROM `applications` INNER JOIN `vacancies` ON `vacancies`.`id` = `applications`.`vacancy_id` WHERE `vacancies`.`status` = 'draft') __active_record_temp)
答案 2 :(得分:0)
如果您使用的是Rails 2,则无法执行上述操作。另一种方法是在find方法中使用joins子句,并在每个项目上调用delete。
TellerLocationWidget.find(:all, :joins => [:widget, :teller_location],
:conditions => {:widgets => {:alt_id => params['alt_id']},
:retailer_locations => {:id => @teller_location.id}}).each do |loc|
loc.delete
end