Many_to_many delete bug

Just for reference – the other showstopper is in
http://rubyforge.org/pipermail/nitro-general/2007-November/008957.html

The new issue is delete in a many_to_many relation:

robert-melas-computer:~/projects/og rmela$ ruby tagtest.rb INFO: Og
uses the Sqlite store.
Program inserting tag1
Collection#initialize: Collection initialized with remove_proc =
remove_tag
Created tags collection with remove proc=remove_tags
Collection#push Entered Collection.push(tag1) with tag=tag1. Owner is
#Post:0x15911e4
Program calling save
Deleting tag
/Users/rmela/nitro/branch/script/lib/…/…/og/lib/og/store/sql.rb:144:in
og_delete': uninitialized constant Og::SqlEnchantmentMixin::BelongsTo (NameError) from /Users/rmela/nitro/branch/script/lib/../../og/lib/og/store/sql.rb:139:in each’
from
/Users/rmela/nitro/branch/script/lib/…/…/og/lib/og/store/sql.rb:139:in
og_delete' from /Users/rmela/nitro/branch/script/lib/../../og/lib/og/store.rb:216:in transaction_raise’
from
/Users/rmela/nitro/branch/script/lib/…/…/og/lib/og/model.rb:196:in
transaction_raise' from /Users/rmela/nitro/branch/script/lib/../../og/lib/og/manager.rb:118:in with_store’
from
/Users/rmela/nitro/branch/script/lib/…/…/og/lib/og/model.rb:195:in
transaction_raise' from /Users/rmela/nitro/branch/script/lib/../../og/lib/og/store/sql.rb:137:in og_delete’
from
/Users/rmela/nitro/branch/script/lib/…/…/og/lib/og/store.rb:153:in
delete' from /Users/rmela/nitro/branch/script/lib/../../og/lib/og/model.rb:181:in delete’
from
/Users/rmela/nitro/branch/script/lib/…/…/og/lib/og/manager.rb:118:in
with_store' from /Users/rmela/nitro/branch/script/lib/../../og/lib/og/model.rb:180:in delete’
from tagtest.rb:31

Here’s code that triggers it. I tried p.remove_tag(t1) and p.save!
before the delete – still no dice. Even if that did work it’d be a
workaround, and unintuitive.

#!/opt/local/bin/ruby
require ‘og’
require ‘sqlite3’

class Post
attr_accessor :name, String
is Taggable
end

Og.start(
:adapter => ‘sqlite’,
:name => ‘tagtest’,
:destroy_schema => true,
:create_schema => true
)
p=Post.new
p.name = ‘post1’
t1 = Tag.new
t1.name = ‘tag1’

puts “Program inserting tag1”
p.tags << t1
puts “Program calling save”
p.save!
puts “Deleting tag”
t1.delete

I will fix this (it is a showstopper for my current application too!!)

-g.

Hi Robert,
I’m still working through some DBI stuff and am just on the ‘single
table cases’ so can’t help you immediately, but hope to get to this
area shortly (whatever that means)…
Any chance you could commit a spec - there are several failing specs
there now so I think George would accept this if it targets a bug.

Cheers
Mark

For the curious. The last run of (many of these speca are from
Sequel, and yes some Og behavior is changed - for the better I
think):

rake test:og

Running og… [ 2
specs - all passed ]
Running og/adapter/dbi… [ 456
specs - all passed ]
Running og/adapter/dbi/create… [ 26
specs - all passed ]
Running og/adapter/dbi/dbd/mysql… [ 2
specs - all passed ]
Running og/adapter/dbi/dbd/sqlite… [ 1
specs - all passed ]
Running og/adapter/dbi/override… [ 0
specs - 0 failed ]
Running og/adapter/dbi/sequel/array_keys_spec… [ 0
specs - 0 failed ]
Running og/adapter/dbi/sequel/connection_pool… [ 24
specs - all passed ]
Running og/adapter/dbi/sequel/core_ext… [ 35
specs - all passed ]
Running og/adapter/dbi/sequel/database… [ 71
specs - 2 failed ]
Running og/adapter/dbi/sequel/dataset… [ 209
specs - all passed ]
Running og/adapter/dbi/sequel/migration_spec… [ 0
specs - 0 failed ]
Running og/adapter/dbi/sequel/model_spec… [ 0
specs - 0 failed ]
Running og/adapter/dbi/sequel/pretty_table_spec… [ 0
specs - 0 failed ]
Running og/adapter/dbi/sequel/schema_generator_spec… [ 0
specs - 0 failed ]
Running og/adapter/dbi/sequel/schema_spec… [ 0
specs - 0 failed ]
Running og/adapter/dbi/sequel/sequelizer… [ 41
specs - all passed ]
Running og/adapter/dbi/utils… [ 0
specs - 0 failed ]
Running og/adapter/oracle… [ 0
specs - 0 failed ]
Running og/adapter/postgresql… [ 0
specs - 0 failed ]
Running og/model… [ 2
specs - 1 failed ]
Running og/model/orderable… [ 6
specs - 3 failed ]
Running og/model/taggable… [ 2
specs - all passed ]
Running og/model/timestamped… [ 2
specs - 1 failed ]
Running og/model/uuid… [ 0
specs - 0 failed ]
Running og/relation/has_many… [ 2
specs - 1 failed ]
Running og/store/sql… [ 0
specs - 0 failed ]
Running og/store/sql/utils… [ 0
specs - 0 failed ]
Running og/util/ann_attr… [ 2
specs - 1 failed ]
Running og/validation… [ 2
specs - all passed ]

While you’re in there there’s an oddity in Collection#push.

post.tags << tag1 # ‘<<’ is alias for ‘push’
post.tags << tag2

Collection has an array of objects called ‘members’. With each object
addition, Collection#push calls members.include? to see if the object is
already in the array. If so, it removes the object before re-adding.

The odd thing is that, even though tag2 had not been previously added,
members.include? returns true. This traces back to the fact that

t1 === t2

returns true if the tags have not yet been saved to the database, and
returns false if they have been saved and reloaded. So it’s probably
using the database ID.

Fortunately for my workaround (members.delete) the internal search in
Array#delete unsaved Tag objects doesn’t use the same comparison!