Rails - belongs_to has_many关联错误

时间:2016-09-04 02:12:04

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

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

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

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

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

答案 0 :(得分:0)

  
      
  1. 这种情况的belongs_to / has_many关联是否正确?这应该是一个has_one吗?
  2.   

要设置用户只能属于单个群组但群组拥有多个用户的关系,那么您就是在正确的轨道上。

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. 两个迁移都应该具有外键属性吗?
  2.   

否 - 只有users表应包含外键。应删除AddUserReferenceToGroup,或者如果您已将其推送到生产状态,则应编写另一个删除groups.user_id列的迁移。

  
      
  1. @group.user_id = current_user.id中设置GroupsController#create是指定创建用户的合适方式   到小组?
  2.   

否 - 由于group_id列位于users列,您需要更新用户表,而不是组。

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

否 - 由于users表上的一行只能在groups_id列中有一个ID,因此用户只能属于一个组。使用unique => true会在users.groups_id列上创建唯一性索引,该索引只允许单个用户与某个组关联。

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

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

在软件级别添加验证还会产生“鸡与鸡蛋”的情况,其中一个群组无法生效,因为它没有用户且用户无法与群组关联,因为它不会保留。

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