STI and Joins Broken

Tagging belongs_to Tag which is an STI model.

Tagging.find_by_sql("SELECT * FROM taggings INNER JOIN tags ON tags.id
= taggings.tag_id").each {|t|
  puts t.inspect
}

# #<TopicTag:0x2369974 @attributes={"name"=>"ruby", "tag_id"=>"1",
"type"=>"TopicTag", "id"=>"1", "taggable_type"=>"Book",
"taggable_id"=>"1"}>
# #<TopicTag:0x2368efc @attributes={"name"=>"agile", "tag_id"=>"2",
"type"=>"TopicTag", "id"=>"2", "taggable_type"=>"Book",
"taggable_id"=>"1"}>
# #<TopicTag:0x236845c @attributes={"name"=>"web", "tag_id"=>"3",
"type"=>"TopicTag", "id"=>"3", "taggable_type"=>"Book",
"taggable_id"=>"1"}>

It sees the type column in the result (because of the join) and assumes
I'm asking for that type.
http://dev.rubyonrails.org/ticket/5838

This can be worked around by setting the inheritance column on
Tagging, but we should fix this :wink:

Tagging belongs_to Tag which is an STI model.

Tagging.find_by_sql("SELECT * FROM taggings INNER JOIN tags ON tags.id
= taggings.tag_id").each {|t|
  puts t.inspect
}

That's the thing about joins, those pesky columns get mixed up.

Tagging.find_by_sql("SELECT taggings.* FROM taggings INNER JOIN tags
ON tags.id = taggings.tag_id").each {|t|
  puts t.inspect
}

Tagging.find(:all, :select => 'taggings.*', :joins => 'INNER JOIN tags
ON tags.id = taggings.tag_id')

Tagging.find(:all, :include => :tags)

I've got a workaround Rick. My query actually gets more complex,
that's just the important bits. It's still a bug :wink:

I've got a workaround Rick. My query actually gets more complex,
that's just the important bits. It's still a bug :wink:

I'd prefer to describe it as an unintended implementation specific feature. :slight_smile:

What's the solution to this though? Can it be repaired without
breaking backwards compatibility for people who rely on find_by_sql
and STI? If you're using find_by_sql there are a few areas where you
have to be careful, I'm tempted to say that this is one of them...

Koz,
Can't this be detected from the calling class? If the calling class
isn't STI, it shouldn't worry about the type column (which is in the
other table anyway). I'll PDI it.

Kev

Can't this be detected from the calling class? If the calling class
isn't STI, it shouldn't worry about the type column (which is in the
other table anyway). I'll PDI it.

This isn't an issue with type really. AR will clobber your id column
too. I think this is an issue with the db adapters not returning
table names with the column name.

In this case it turned out that if an inheritance_column existed it'd
just assume it was sti and allocate that way. My patch
(http://dev.rubyonrails.org/attachment/ticket/5838/make_find_by_sql_join_with_sti_safe.diff)
makes it check to be sure that this is actually an STI model before
doing so.

I've made a inheritance rework some weeks ago that would possible fix
it since it only loads the inheritance support in the class that'll use
it.
In STI case, it would load only if the class that descends directly
from AR has been inherited and the column specified in the
inheritance_column is available.
People here told me to wait until next release so we can dig into this,
but if you've interesting in testing it out send me a message and i'll
send you the patch.

Rodrigo,
If you'd like, grab the test case in my patch and see what happens
with your inheritance impl.

Kev

Can I get some feedback on ticket 5838? I've got a patch and testcase
that works. Rick seems to be opposed to the patch because I'm not
solving all the join issues, but I'd argue that you should at the very
least get the sort of object your asked for back.

Account.find_by_sql() should -never- return something other than
Account objects.

Agreed: http://dev.rubyonrails.org/changeset/4813

jeremy

My patch seems to work properly.
I've opened a ticket with my patch, in case anyone is interested.
http://dev.rubyonrails.org/ticket/5991

Cheers.

Kevin Clark wrote: