For the purposes of the discussion I cooked up a test with two tables:
:stones and :bowls (both created with just timestamps - trivial)
create_table :bowls_stones, :id => false do |t|
t.integer :bowl_id, :null => false
t.integer :stone_id, :null => false
end
The models are pretty self-explanatory, and basic, but here they are:
class Stone < ActiveRecord::Base
has_and_belongs_to_many :bowls
end
class Bowl < ActiveRecord::Base
has_and_belongs_to_many :stones
end
Now, the issue is: I want there to be many of the same stone in each bowl. And I want to be able to remove only one, leaving the other identical stones behind. This seems pretty basic, and I'm really hoping that I can both find a solution and not feel like too much of an idiot when I do.
Here's a test run:
@stone = Stone.new
@stone.save
@bowl = Bowl.new
@bowl.save
#test1 - .delete
5.times do
@bowl.stones << @stone
end
@bowl.stones.count
=> 5
@bowl.stones.delete(@stone)
@bowl.stones.count
=> 0
#removed them all!
#test2 - .delete_at
5.times do
@bowl.stones << @stone
end
@bowl.stones.count
=> 5
index = @bowl.stones.index(@stone)
@bowl.stones.delete_at(index)
@bowl.stones.count
=> 5
#not surprising, I guess... delete_at isn't part of habtm. Fails silently, though.
@bowl.stones.clear
#this is ridiculous, but... let's wipe it all out
5.times do
@bowl.stones << @stone
end
@bowl.stones.count
=> 5
ids = @bowl.stone_ids
index = ids.index(@stone.id)
ids.delete_at(index)
@bowl.stones.clear
ids.each do |id|
@bowl.stones << Stone.find(id)
end
@bowl.stones.count
=> 4
#Is this really the only way?
So... is blowing away the whole thing and reconstructing it from keys really the only way?