I have a collection class called MySet:
class MySet
include DataMapper::Resource
property :id, Serial
has n, :my_elements, :through => Resource
def add integer
unless my_elements.first(:integer => integer)
my_element = MyElement.create :integer => integer
my_elements << my_element
my_elements.save
end
self
end
def has_integer? integer
!my_elements.first(:integer => integer).nil?
end
def delete integer
if has_integer? integer
my_elements.first(:integer => integer).destroy
my_elements.save
end
self
end
def size
my_elements.size
end
end
and an element class called MyElement:
class MyElement
include DataMapper::Resource
property :id, Serial
property :integer, Integer
end
I want to be able to add and delete elements to and from MySet. However, the following spec:
describe MySet do
subject do
MySet.create
end
it "adds and deletes" do
subject.add 1
subject.delete 1
subject.size.should == 0
end
end
fails with:
Failure/Error: subject.size.should == 0
expected: 0
got: 1 (using ==)
This is similar to the problem described in DataMapper has n through Resource DELETE (Remove from association) not working except that MyElement does not specify an association with MySet. However, I think the solution in that post is what I am using and it does not appear to work.
Take a look at the Collection documentation:
http://rubydoc.info/github/datamapper/dm-core/master/DataMapper/Collection
http://rubydoc.info/github/datamapper/dm-core/master/DataMapper/Associations/ManyToMany/Collection
I think some of the things you're doing are extraneous, and MyElement.create
should probably be MyElement.first_or_create
but more importantly, the part where you destroy one of the MyElement's is not quite right. It seems like what you're trying to do is remove it from the "my_elements" collection, so you should find it, and then "delete" it from the collection:
def delete integer
element = my_elements.first(:integer => integer)
my_elements.delete(element)
self
end
(destroying it may also be part of what you're trying to do, and you can do that separately).
Just destroying it like you were doing may actually work (I'm not sure), but you'd probably have to reload the resource in your test to see the updated size:
subject.reload
subject.size.should == 0