flyerhzm/bullet

Rails 7.1 composite primary keys break N+1 detection

BytewaveMLP opened this issue · 0 comments

Hey there! We recently upgraded our codebase to Rails 7.1, and have migrated a couple of our database models to use the new support for composite primary keys. Following the upgrade, we noticed errors being thrown in bullet for these models; specifically, we ran into the case where a HABTM join table was raising during creation, but it's likely that this affects other N+1 detection code paths as well. The stack trace we received is below:

["foo", "bar"] is not a symbol nor a string
 /.rbenv/versions/3.2.2/lib/ruby/gems/3.2.0/gems/bullet-7.1.1/lib/bullet/ext/object.rb:15:in `bullet_primary_key_value'
 /.rbenv/versions/3.2.2/lib/ruby/gems/3.2.0/gems/bullet-7.1.1/lib/bullet/detector/n_plus_one_query.rb:58:in `add_impossible_object'
 /.rbenv/versions/3.2.2/lib/ruby/gems/3.2.0/gems/bullet-7.1.1/lib/bullet/active_record71.rb:7:in `block in _create_record'
 /.rbenv/versions/3.2.2/lib/ruby/gems/3.2.0/gems/activerecord-7.1.0/lib/active_record/persistence.rb:1263:in `_create_record'
 /.rbenv/versions/3.2.2/lib/ruby/gems/3.2.0/gems/activerecord-7.1.0/lib/active_record/counter_cache.rb:187:in `_create_record'
 /.rbenv/versions/3.2.2/lib/ruby/gems/3.2.0/gems/activerecord-7.1.0/lib/active_record/locking/optimistic.rb:84:in `_create_record'
 /.rbenv/versions/3.2.2/lib/ruby/gems/3.2.0/gems/activerecord-7.1.0/lib/active_record/encryption/encryptable_record.rb:178:in `_create_record'
 /.rbenv/versions/3.2.2/lib/ruby/gems/3.2.0/gems/activerecord-7.1.0/lib/active_record/attribute_methods/dirty.rb:236:in `_create_record'
 /.rbenv/versions/3.2.2/lib/ruby/gems/3.2.0/gems/activerecord-7.1.0/lib/active_record/callbacks.rb:445:in `block in _create_record'
 /.rbenv/versions/3.2.2/lib/ruby/gems/3.2.0/gems/activesupport-7.1.0/lib/active_support/callbacks.rb:101:in `run_callbacks'
 /.rbenv/versions/3.2.2/lib/ruby/gems/3.2.0/gems/activesupport-7.1.0/lib/active_support/callbacks.rb:952:in `_run_create_callbacks'
 /.rbenv/versions/3.2.2/lib/ruby/gems/3.2.0/gems/activerecord-7.1.0/lib/active_record/callbacks.rb:445:in `_create_record'
 /.rbenv/versions/3.2.2/lib/ruby/gems/3.2.0/gems/activerecord-7.1.0/lib/active_record/timestamp.rb:114:in `_create_record'
 /.rbenv/versions/3.2.2/lib/ruby/gems/3.2.0/gems/bullet-7.1.1/lib/bullet/active_record71.rb:6:in `_create_record'
 ...

Tracing this back, this appears to be a simple bug in the bullet_primary_key_value object extension here. I might take a peek at fixing this tomorrow, but in case someone gets to it before me, this looks relatively simple; if the primary_key value is a tuple, join the individual values with ,, as is done with primary_keys for the composite_primary_keys gem.