是否可以使用内连接条件delete_all?

时间:2010-11-21 00:46:37

标签: ruby-on-rails inner-join

我需要一次删除大量记录,我需要根据另一个与“belongs_to”关系相关的模型中的条件来执行此操作。我知道我可以遍历每个检查条件,但这需要我的大记录集永远,因为对于每个“belongs_to”它会进行单独的查询。

这是一个例子。我有一个“产品”模型,“belongs_to”是一个“艺术家”,可以说艺术家有一个属性“is_disabled”。

如果我想删除所有属于残疾艺术家的产品,我希望能够做到这样的事情:

Product.delete_all(:joins => :artist, :conditions => ["artists.is_disabled = ?", true])

这可能吗?我以前在SQL中直接完成了这项工作,但不确定是否可以通过rails完成。

3 个答案:

答案 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