Rails - belongs_to has_many 关联错误
Rails - belongs_to has_many association error
目标: 用户可以创建一个用户帐户(设计),然后创建一个组。每个用户只有 belongs_to
一组和一组 has_many
用户。
创建和 运行 迁移后 - 如果我尝试创建用户,我会收到以下错误:“1 个错误禁止保存此用户:组必须存在”。
很明显,当前设置希望在创建用户时存在 group_id。
- 对于这种情况,belongs_to / has_many 关联是否正确?这应该是 has_one?
- 两个迁移都应该有外键属性吗?
GroupsController#create
中的设置 @group.user_id = current_user.id
是否适合将创建用户分配到组?我试图通过使用回调在群组模型中执行此操作,但我无法访问 current_user
变量。
- 我还想强制执行(在数据库级别)用户只能属于一个组 - 这是在架构中使用
unique => true
实现的吗?
- 我如何(在数据库级别)强制一个组必须有一个用户?
.
class Group < ApplicationRecord
has_many :users
validates :users, presence: true
end
class User < ApplicationRecord
...
belongs_to :group
...
end
class GroupsController < ApplicationController
...
def create
@group = Group.new(group_params)
@group.user_id = current_user.id
...
end
...
private
...
def group_params
params.require(:group).permit(:name, :user_id)
end
...
end
class AddGroupReferenceToUser < ActiveRecord::Migration[5.0]
def change
add_reference :users, :group, foreign_key: true
end
end
class AddUserReferenceToGroup < ActiveRecord::Migration[5.0]
def change
add_reference :groups, :user, foreign_key: true
end
end
ActiveRecord::Schema.define(version: 20160903125553) do
create_table "groups", force: :cascade do |t|
t.string "name"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.integer "user_id"
t.index ["user_id"], name: "index_groups_on_user_id"
end
create_table "users", force: :cascade do |t|
...
t.integer "group_id"
t.index ["email"], name: "index_users_on_email", unique: true
t.index ["group_id"], name: "index_users_on_group_id"
t.index ["reset_password_token"], name: "index_users_on_reset_password_token", unique: true
end
end
- Is a belongs_to / has_many association correct for this situation? Should this be a has_one?
设置一个用户只能属于一个组但组有很多用户的关系,那么你就在正确的轨道上。
class Group < ActiveRecord::Base
has_many :users
end
class User < ActiveRecord::Base
belongs_to :group
end
belongs_to
将外键列作为 users.group_id
。使用 has_one
会将其放置在 groups.user_id
列,这将只允许一对一映射 - 一个组只能有一个用户。
- Should both migrations have a foreign key attribute?
否 - 只有 users
table 应包含外键。 AddUserReferenceToGroup
应该被删除或者你应该编写另一个迁移来删除 groups.user_id
列,如果你已经将它推到生产中。
- Is setting
@group.user_id = current_user.id
in GroupsController#create
a suitable way to assign the creating user
to the group?
否 - 因为 group_id
列在 users
列上,您需要更新用户 table - 而不是组。
if @group.save
current_user.update(group: @group)
end
- I would also like to enforce (at the database level) that a user can only belong to one group - Is this achieved using unique => true in the schema?
否 - 因为 users
table 上的一行在 groups_id
列中只能有一个 ID,所以用户无论如何只能属于一个组。使用 unique => true
将在 users.groups_id
列上创建唯一性索引,这将只允许单个用户与组相关联。
- How can I enforce (at the database level) that a group must have a user?
这实际上是不可能的。为了能够将用户与组相关联,您必须首先将组插入数据库,以便为其分配一个 ID。
在软件级别添加验证也会造成 "chicken vs egg" 情况,其中组因为没有用户而无效,并且用户不能与组相关联,因为它没有持久化。
然而,您可以通过将外键列声明为 NOT NULL
.
来在 belongs_to
端设置约束
目标: 用户可以创建一个用户帐户(设计),然后创建一个组。每个用户只有 belongs_to
一组和一组 has_many
用户。
创建和 运行 迁移后 - 如果我尝试创建用户,我会收到以下错误:“1 个错误禁止保存此用户:组必须存在”。
很明显,当前设置希望在创建用户时存在 group_id。
- 对于这种情况,belongs_to / has_many 关联是否正确?这应该是 has_one?
- 两个迁移都应该有外键属性吗?
GroupsController#create
中的设置@group.user_id = current_user.id
是否适合将创建用户分配到组?我试图通过使用回调在群组模型中执行此操作,但我无法访问current_user
变量。- 我还想强制执行(在数据库级别)用户只能属于一个组 - 这是在架构中使用
unique => true
实现的吗? - 我如何(在数据库级别)强制一个组必须有一个用户?
.
class Group < ApplicationRecord
has_many :users
validates :users, presence: true
end
class User < ApplicationRecord
...
belongs_to :group
...
end
class GroupsController < ApplicationController
...
def create
@group = Group.new(group_params)
@group.user_id = current_user.id
...
end
...
private
...
def group_params
params.require(:group).permit(:name, :user_id)
end
...
end
class AddGroupReferenceToUser < ActiveRecord::Migration[5.0]
def change
add_reference :users, :group, foreign_key: true
end
end
class AddUserReferenceToGroup < ActiveRecord::Migration[5.0]
def change
add_reference :groups, :user, foreign_key: true
end
end
ActiveRecord::Schema.define(version: 20160903125553) do
create_table "groups", force: :cascade do |t|
t.string "name"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.integer "user_id"
t.index ["user_id"], name: "index_groups_on_user_id"
end
create_table "users", force: :cascade do |t|
...
t.integer "group_id"
t.index ["email"], name: "index_users_on_email", unique: true
t.index ["group_id"], name: "index_users_on_group_id"
t.index ["reset_password_token"], name: "index_users_on_reset_password_token", unique: true
end
end
- Is a belongs_to / has_many association correct for this situation? Should this be a has_one?
设置一个用户只能属于一个组但组有很多用户的关系,那么你就在正确的轨道上。
class Group < ActiveRecord::Base
has_many :users
end
class User < ActiveRecord::Base
belongs_to :group
end
belongs_to
将外键列作为 users.group_id
。使用 has_one
会将其放置在 groups.user_id
列,这将只允许一对一映射 - 一个组只能有一个用户。
- Should both migrations have a foreign key attribute?
否 - 只有 users
table 应包含外键。 AddUserReferenceToGroup
应该被删除或者你应该编写另一个迁移来删除 groups.user_id
列,如果你已经将它推到生产中。
- Is setting
@group.user_id = current_user.id
inGroupsController#create
a suitable way to assign the creating user to the group?
否 - 因为 group_id
列在 users
列上,您需要更新用户 table - 而不是组。
if @group.save
current_user.update(group: @group)
end
- I would also like to enforce (at the database level) that a user can only belong to one group - Is this achieved using unique => true in the schema?
否 - 因为 users
table 上的一行在 groups_id
列中只能有一个 ID,所以用户无论如何只能属于一个组。使用 unique => true
将在 users.groups_id
列上创建唯一性索引,这将只允许单个用户与组相关联。
- How can I enforce (at the database level) that a group must have a user?
这实际上是不可能的。为了能够将用户与组相关联,您必须首先将组插入数据库,以便为其分配一个 ID。
在软件级别添加验证也会造成 "chicken vs egg" 情况,其中组因为没有用户而无效,并且用户不能与组相关联,因为它没有持久化。
然而,您可以通过将外键列声明为 NOT NULL
.
belongs_to
端设置约束