Search code examples
ruby-on-railsnamed-scopefindbyactiverecord-relation

How to delete objects through a named scope?


There is a join table with three columns: id, product_a_id, product_b_id

class ProductConnection < ActiveRecord::Base
  belongs_to :product_a, class_name: :Product
  belongs_to :product_b, class_name: :Product    
end

I would like to filter the table by a specific product regardless in which column the product id is contained. How can I write a named scope which respects that a product can be nil? The following draft is inspired by a post by Zack Holman though it does not work:

scope :find_by_product, \
  lambda {|p| p.nil? ? { \
    where(["product_a_id = ? OR product_b_id = ?", p.id, p.id]) : {} \
  }

Then I would like to know how I can delete all products returned in the ActiveRecord::Relation?


Solution

  • It sounds like the issue is with how to make your find_by_product scope work when the passed in product is nil? I think your curly braces are a little mixed up. Either way, here's how I'd write it in case this helps:

    ProductConnection
    
    scope :for_product, ->(product) {
      if product_id = product.try(:id)
        where(arel_table[:product_a_id].eq(product_id).
                or(arel_table[:product_b_id].eq(produt_id))
      end
    }
    

    Then, once that works, you can just call destroy_all on the scope to destroy all the records.

    ProductConnection.for_product(my_product).destroy_all
    

    There is also delete_all, which you can use in the same way, if you really don't want the ActiveRecord callbacks included with destroy.