Reputation: 123
I have a project based on Rails 4.2.
I have defined two models like this:
class Option < ActiveRecord::Base
has_many :item_options
has_many :items, through: :item_options, source: :item
scope :materials, -> { where(category: 'material') }
scope :types, -> { where(category: 'type') }
class Item < ActiveRecord::Base
has_many :item_options
has_many :options, through: :item_options
I'm not able to delete association's join records through the scopes of the Option model.
If I do:
Item.first.options.materials.delete_all
the executed query is:
DELETE FROM "options" WHERE "options"."id" IN (SELECT "options"."id" FROM "options" INNER JOIN "item_options" ON "options"."id" = "item_options"."option_id" WHERE "item_options"."item_id" = $1 AND "options"."category" = $2)
That removes records from the Option model and it's not what I was expecting.
If I try to delete association records without using a scope, like this:
Item.first.options.delete_all
that correctly executes the query:
DELETE FROM "item_options" WHERE "item_options"."item_id" = $1
Effectively removing only the join records.
Why does delete behave differently if called through a scope?
(edited, contained a pasting error with old name LabelItem for one of the models)
Upvotes: 1
Views: 270
Reputation: 4802
When you call the method materials
in the options
relation it returns an Option
relation instance. That's why it won't work.
It might work:
class Item < ActiveRecord::Base
has_many :item_options
has_many :options, through: :item_options
has_many :material_options, -> { materials }, through: :item_options, source: :option
Then:
Item.first.material_options.delete_all
Upvotes: 1