从 has_one 关系中得到意想不到的结果
Get unexpected result from has_one relationship
我有一个 Selection
模型,它有很多 Choices
和一个 DefaultChoice
。
关系是这样构造的。
模型(我觉得这里有问题)
class Selection < ApplicationRecord
has_many :choices, dependent: :delete_all
has_one :default_choice, class_name: 'Choice'
end
class Choice < ApplicationRecord
belongs_to Selection
end
迁移
create_table :selections do |t|
t.references :default_choice, index: true
end
create_table :choices do |t|
t.belongs_to :selection
end
有点不对:
# let's say:
selection = Selection.find(1)
selection.choices << Choice.find(1)
selection.choices << Choice.find(2)
selection.default_choice = Choice.find(2)
selection.save!
# then
selection.default_choice_id = 2
# but
selection.default_choice.id = 1
怎么会?!
selection.default_choice
生成此查询:
Choice Load (0.5ms) SELECT "choices".* FROM "choices" WHERE "choices"."selection_id" = LIMIT [["selection_id", 1], ["LIMIT", 1]]
您对关系 has_many :choiches
和 has_one :default_choice
使用相同的模型 Choice
。因此,当您查询 has_one :default_choice
结果全部来自 choices
table 并且使用 has_one
时,您只会得到一个结果,这是它找到的第一个引用到 Selection 对象的结果。
更新
要在 has_many 上实现默认设置,您可以执行一些操作,例如在 Choice 模型上添加列,如果它是默认选择,则该列为真。然后 has_one 关系需要有范围才能获得默认为真的选择,如下所示:
has_one :default_choice, -> { where default_choice: true }, class_name: 'Choice'
我有一个 Selection
模型,它有很多 Choices
和一个 DefaultChoice
。
关系是这样构造的。
模型(我觉得这里有问题)
class Selection < ApplicationRecord
has_many :choices, dependent: :delete_all
has_one :default_choice, class_name: 'Choice'
end
class Choice < ApplicationRecord
belongs_to Selection
end
迁移
create_table :selections do |t|
t.references :default_choice, index: true
end
create_table :choices do |t|
t.belongs_to :selection
end
有点不对:
# let's say:
selection = Selection.find(1)
selection.choices << Choice.find(1)
selection.choices << Choice.find(2)
selection.default_choice = Choice.find(2)
selection.save!
# then
selection.default_choice_id = 2
# but
selection.default_choice.id = 1
怎么会?!
selection.default_choice
生成此查询:
Choice Load (0.5ms) SELECT "choices".* FROM "choices" WHERE "choices"."selection_id" = LIMIT [["selection_id", 1], ["LIMIT", 1]]
您对关系 has_many :choiches
和 has_one :default_choice
使用相同的模型 Choice
。因此,当您查询 has_one :default_choice
结果全部来自 choices
table 并且使用 has_one
时,您只会得到一个结果,这是它找到的第一个引用到 Selection 对象的结果。
更新
要在 has_many 上实现默认设置,您可以执行一些操作,例如在 Choice 模型上添加列,如果它是默认选择,则该列为真。然后 has_one 关系需要有范围才能获得默认为真的选择,如下所示:
has_one :default_choice, -> { where default_choice: true }, class_name: 'Choice'