Rails - belongs_to has_many 关联错误

Rails - belongs_to has_many association error

目标: 用户可以创建一个用户帐户(设计),然后创建一个组。每个用户只有 belongs_to 一组和一组 has_many 用户。

创建和 运行 迁移后 - 如果我尝试创建用户,我会收到以下错误:“1 个错误禁止保存此用户:组必须存在”。

很明显,当前设置希望在创建用户时存在 group_id。

  1. 对于这种情况,belongs_to / has_many 关联是否正确?这应该是 has_one?
  2. 两个迁移都应该有外键属性吗?
  3. GroupsController#create 中的设置 @group.user_id = current_user.id 是否适合将创建用户分配到组?我试图通过使用回调在群组模型中执行此操作,但我无法访问 current_user 变量。
  4. 我还想强制执行(在数据库级别)用户只能属于一个组 - 这是在架构中使用 unique => true 实现的吗?
  5. 我如何(在数据库级别)强制一个组必须有一个用户?

.

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
  1. 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 列,这将只允许一对一映射 - 一个组只能有一个用户。

  1. Should both migrations have a foreign key attribute?

否 - 只有 users table 应包含外键。 AddUserReferenceToGroup 应该被删除或者你应该编写另一个迁移来删除 groups.user_id 列,如果你已经将它推到生产中。

  1. 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
  1. 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 列上创建唯一性索引,这将只允许单个用户与组相关联。

  1. How can I enforce (at the database level) that a group must have a user?

这实际上是不可能的。为了能够将用户与组相关联,您必须首先将组插入数据库,以便为其分配一个 ID。

在软件级别添加验证也会造成 "chicken vs egg" 情况,其中组因为没有用户而无效,并且用户不能与组相关联,因为它没有持久化。

然而,您可以通过将外键列声明为 NOT NULL.

来在 belongs_to 端设置约束