Polymorphic join query returns wrong result
A bit of context:
Our system tracks users' achievements. These may have other achievements as conditions (to track prerequisites). A resource which has_many conditions is called a conditional.
There are several different types of condition and conditional, so the associations are polymorphic in both directions (using active_record-acts_as). This is managed via the conditions table.
# Schema
create_table "achievements", force: :cascade do |t|
t.string "title"
end
create_table "conditions", force: :cascade do |t|
t.integer "actable_id"
t.string "actable_type"
t.integer "conditional_id"
t.string "conditional_type"
end
create_table "achievement_conditions", force: :cascade do |t|
t.integer "achievement_id"
end
# Models
class Achievement < ActiveRecord::Base
has_many :conditions, -> { includes :actable },
class_name: Condition.name, as: :conditional, dependent: :destroy
end
class Condition < ActiveRecord::Base
actable
belongs_to :conditional, polymorphic: true
end
class AchievementCondition < ActiveRecord::Base
acts_as :condition, class_name: Condition.name
belongs_to :achievement, class_name: Achievement.name
default_scope { includes(:achievement) }
end
With this setup, if achievement 2 has achievement 1 as a condition, Achievement.find(2).conditions.first.actable.achievement would return achievement 1.
The bug happens with the following query, which we use to find all achievemnt conditions of a given achievement (2 in this case):
AchievementCondition.joins { condition.conditional(Achievement) }.where { condition.conditional.id == 2 }.map(&:achievement).first
It should return achievement 1, but returns achievement 2. The following fixes the problem, however reloading every object is prohibitively expensive:
a = AchievementCondition.joins { condition.conditional(Achievement) }.where { condition.conditional.id == 2 }.first
a.reload.achievement # correct result
Would anyone have insight into why this happens and if it can be fixed?
There's a minimal Rails project here with the models and schema set up. The problem is also described in Coursemology/coursemology2#443.
Apologies for the exposition. This is an obscure case and I wasn't sure how to frame it more briefly, or come up with a smaller example.