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: