【问题标题】:Rails - belongs_to has_many association errorRails - belongs_to has_many 关联错误
【发布时间】:2016-09-04 02:12:04
【问题描述】:

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

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

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

  1. 对于这种情况,belongs_to / has_many 关联是否正确?这应该是 has_one 吗?
  2. 两个迁移都应该有外键属性吗?
  3. 在GroupsController#create 中设置@group.user_id = current_user.id 是否适合将创建用户分配到组?我尝试在 Groups 模型中使用回调来执行此操作,但我无法访问 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

【问题讨论】:

  • 你是说Group 有很多Users。因此,您的用户表中应该有一个group_id。不在组表中。你可以创建一个Group,比如current_user.group.new(group_params)

标签: ruby-on-rails associations model-associations


【解决方案1】:
  1. 对于这种情况,belongs_to / has_many 关联是否正确?这应该是 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. 两个迁移都应该有外键属性吗?

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

  1. 在GroupsController#create 中设置@group.user_id = current_user.id 是分配创建用户的合适方式吗 加入小组?

否 - 因为 group_id 列在 users 列上,您需要更新用户表 - 而不是组。

if @group.save
  current_user.update(group: @group)
end
  1. 我还想强制(在数据库级别)用户只能属于一个组 - 这是在架构中使用 unique => true 实现的吗?

不-因为users 表上的一行在groups_id 列中只能有一个ID,所以用户无论如何只能属于一个组。使用unique =&gt; true 将在users.groups_id 列上创建一个唯一性索引,该索引仅允许单个用户与组关联。

  1. 如何(在数据库级别)强制组必须有用户?

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

在软件级别添加验证也会造成“鸡对蛋”的情况,其中组不能有效,因为它没有用户,并且用户不能与组关联,因为它没有持久化。

但是,您可以通过将外键列声明为 NOT NULL 来设置 belongs_to 端的约束。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-09-11
    • 2015-04-17
    • 1970-01-01
    • 1970-01-01
    • 2011-04-21
    • 1970-01-01
    • 2023-03-29
    相关资源
    最近更新 更多