Rails 中的一对一关系很奇怪
Weirdness with one to one relationship in Rails
我有一个(相对)简单的 Rails 应用程序。我有三个模型,一个评估、一个用户和一个团队。一个团队有很多用户,每个用户都可以有一个评估。以下是模型及其相关模式的截断版本:
class Assessment < ApplicationRecord
belongs_to :user, optional: true
end
create_table "assessments", force: :cascade do |t|
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.string "aasm_state"
t.integer "user_id"
end
class User < ApplicationRecord
has_one :assessment
belongs_to :team, optional: true
end
create_table "users", force: :cascade do |t|
t.string "email"
t.string "name"
t.string "organisation_type"
t.string "position"
t.string "location"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.integer "team_id"
t.string "locale", default: "en", null: false
end
class Team < ApplicationRecord
has_many :users
has_many :assessments, through: :users
end
create_table "teams", force: :cascade do |t|
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
当我尝试获取团队中没有评估的所有用户时 (team.users.where(assessment: nil)
),我收到以下错误:
ActiveRecord::StatementInvalid:
PG::UndefinedColumn: ERROR: column users.user_id does not exist
LINE 1: ...".* FROM "users" WHERE "users"."team_id" = AND "users"."u...
^
: SELECT "users".* FROM "users" WHERE "users"."team_id" = AND "users"."user_id" IS NULL
结果 SQL,如错误所示,有点古怪:
SELECT "users".* FROM "users" WHERE "users"."team_id" = AND "users"."user_id" IS NULL
当我尝试在评估确实存在时从评估中获取用户时,它 returns 无。
我怀疑我在这里做的事情真的很愚蠢,但是有人可以帮忙吗?
我建议您需要在此处使用左外连接。在 Rails 5 中,这可以写成:
users = team.users.left_outer_join(:assessment)
.where(assessments: { id: nil })
.uniq
来源:https://blog.bigbinary.com/2016/03/24/support-for-left-outer-joins-in-rails-5.html
根据您在问题中的解释,我对上述查询所做的更改是:
- 从评估 Table 中删除列 'user_id'。
- 在用户 Table 中添加列 'assessment_id'。
- 从用户模型中删除
has_one :assessment
并在用户模型中添加 belongs_to :assessment
。
- 从评估模型中删除
belongs_to :user
并在评估模型中添加 has_one :user
。
唯一需要注意的是,a.user = u
将提交更改,而不是 u.assessment = a
。 (a是评价,u是用户)
我有一个(相对)简单的 Rails 应用程序。我有三个模型,一个评估、一个用户和一个团队。一个团队有很多用户,每个用户都可以有一个评估。以下是模型及其相关模式的截断版本:
class Assessment < ApplicationRecord
belongs_to :user, optional: true
end
create_table "assessments", force: :cascade do |t|
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.string "aasm_state"
t.integer "user_id"
end
class User < ApplicationRecord
has_one :assessment
belongs_to :team, optional: true
end
create_table "users", force: :cascade do |t|
t.string "email"
t.string "name"
t.string "organisation_type"
t.string "position"
t.string "location"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.integer "team_id"
t.string "locale", default: "en", null: false
end
class Team < ApplicationRecord
has_many :users
has_many :assessments, through: :users
end
create_table "teams", force: :cascade do |t|
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
当我尝试获取团队中没有评估的所有用户时 (team.users.where(assessment: nil)
),我收到以下错误:
ActiveRecord::StatementInvalid:
PG::UndefinedColumn: ERROR: column users.user_id does not exist
LINE 1: ...".* FROM "users" WHERE "users"."team_id" = AND "users"."u...
^
: SELECT "users".* FROM "users" WHERE "users"."team_id" = AND "users"."user_id" IS NULL
结果 SQL,如错误所示,有点古怪:
SELECT "users".* FROM "users" WHERE "users"."team_id" = AND "users"."user_id" IS NULL
当我尝试在评估确实存在时从评估中获取用户时,它 returns 无。
我怀疑我在这里做的事情真的很愚蠢,但是有人可以帮忙吗?
我建议您需要在此处使用左外连接。在 Rails 5 中,这可以写成:
users = team.users.left_outer_join(:assessment)
.where(assessments: { id: nil })
.uniq
来源:https://blog.bigbinary.com/2016/03/24/support-for-left-outer-joins-in-rails-5.html
根据您在问题中的解释,我对上述查询所做的更改是:
- 从评估 Table 中删除列 'user_id'。
- 在用户 Table 中添加列 'assessment_id'。
- 从用户模型中删除
has_one :assessment
并在用户模型中添加belongs_to :assessment
。 - 从评估模型中删除
belongs_to :user
并在评估模型中添加has_one :user
。
唯一需要注意的是,a.user = u
将提交更改,而不是 u.assessment = a
。 (a是评价,u是用户)