Has_many nightmare

Can someone tell me I’m not going mad.

We have a very large rails app, with lots of things like:

Link model

belongs_to :product
belongs_to :content
belongs_to :member
belongs_to :boat

Product model

has_many :links, :foreign_key => :product_id

Content model

has_many :links, :foreign_key => :content_id

Test

Product.new.links.all

If we run this test on Rails 3.0 we get:

SELECT links.* FROM links WHERE (links.product_id = NULL)

If we run this test on Rails 3.2 we get:

SELECT links.* FROM links WHERE links.product_id IS NULL

Notice the VERY BIG change in how Rails check for NULL (it may not look
like a big change, but it is).

In the first case (3.0) we get NO records, as you would expect on a new
record, and as everything in our code assumes.

In the second case (3.2) we get ALL RECORDS that have an empty
product_id
field.

This is obviously quite a change.

We use our ‘links’ table to store many kinds of relationships between
objects in our system.

So for a link between a ‘Member’ and a ‘Boat’, the product_id field
would
be blank and just the member_id and boat_id would be filled in.

Under rails 3.0 this all works fine.

Under rails 3.2, EVERY SINGLE use of has_many / has_many :through now
returns ALL unrelated records for every query on a new record, simply
because of the change in NULL checking.

ps. caps used for highlighting, not shouting.

Does anyone know if this is expected behaviour?

Ian Moody wrote in post #1110472:

Can someone tell me I’m not going mad.

We have a very large rails app, with lots of things like:

Link model

belongs_to :product
belongs_to :content
belongs_to :member
belongs_to :boat

Product model

has_many :links, :foreign_key => :product_id

Content model

has_many :links, :foreign_key => :content_id

Test

Product.new.links.all

If we run this test on Rails 3.0 we get:

SELECT links.* FROM links WHERE (links.product_id = NULL)

If we run this test on Rails 3.2 we get:

SELECT links.* FROM links WHERE links.product_id IS NULL

Notice the VERY BIG change in how Rails check for NULL (it may not look
like a big change, but it is).

In the first case (3.0) we get NO records, as you would expect on a new
record, and as everything in our code assumes.

In the second case (3.2) we get ALL RECORDS that have an empty
product_id
field.

This is very interesting. The 3.2 version “feels” more correct to me,
but I haven’t fully thought it through.

This is obviously quite a change.

We use our ‘links’ table to store many kinds of relationships between
objects in our system.

So for a link between a ‘Member’ and a ‘Boat’, the product_id field
would
be blank and just the member_id and boat_id would be filled in.

Under rails 3.0 this all works fine.

Under rails 3.2, EVERY SINGLE use of has_many / has_many :through now
returns ALL unrelated records for every query on a new record, simply
because of the change in NULL checking.

ps. caps used for highlighting, not shouting.

Does anyone know if this is expected behaviour?

My guess is that the change wasn’t arbitrary. I’m pretty sure the change
was made for a reason that made sense to the core team at the time.

That being said, unless I’m missing something really obvious I would
have used a polymorphic association here:

class Link < ActiveRecord::Base
belongs_to :linkable, :polymorphic => true
end

class Product < ActiveRecord::Base
has_many :links, :as => :linkable
end

class Content < ActiveRecord::Base
has_many :links, :as => :linkable
end