无法访问具有 has_one 关联的用户角色

Can't access User's Role with has_one association

我有一个用户 table,它引用了角色模型。我希望一个用户只有一个角色,所以我在我的 User 模型中设置了一个 has_one 关联,如下所示:

has_one :role

这是我的 Role 模特协会:

belongs_to :user

这是我的 schema.rb 用户 table:

# other stuff
t.bigint "role_id"
t.index ["role_id"], name: "index_users_on_role_id"

我觉得我的角色系统规划得不好,但我正在努力挽救它。我想通过使用 user.role 来访问用户的角色,其中 userUser 模型的一个实例。

为什么当我调用 user.role 时收到错误提示: ActiveRecord::StatementInvalid (PG::UndefinedColumn: ERROR: column roles.user_id does not exist) LINE 1: SELECT "roles".* FROM "roles" WHERE "roles"."user_id" = L...

更新
用于创建角色的迁移文件 table:

class CreateRoles < ActiveRecord::Migration[6.0]
  def change
    create_table :roles do |t|
      t.string :name, null: false, default: ""
      t.boolean :can_delete_any_job, null: false, default: false
      t.boolean :can_kick_any_user, null: false, default: false
      t.boolean :can_claim_any_application, null: false, default: false
      t.boolean :can_create_events, null: false, default: false
      t.boolean :can_create_news_announcement, null: false, default: false
      t.timestamps
    end
  end
end

您需要在 roles table 上有一个名为 user_id 的列。您可以创建一个新的迁移来解决这个问题。

rails g migration add_missing_columns

# in the migration
add_column :roles, :user_id, :integer
remove_column :users, :role_id

# then in console
rails db:migrate

理想情况下,您希望加入 table 和

之类的东西
create_table :roles_users do |t|
  t.references :user
  t.references :role
end

然后

class User < ApplicationRecord
  has_many :roles_users
  has_many :roles, through: :roles_users
end

class Role < ApplicationRecord
  has_many :roles_users
  has_many :users, through: :roles_users
end

class RolesUser < ApplicationRecord
  belongs_to :user
  belongs_to :role
end

您需要将 'user_id' 字段添加到角色 table。您将模型中的关联保持原样,这将解决问题。这是因为具有 belongs_to 关联的模型将存储外键。

此外,我建议您将 role_id 存储在用户 table 中,因为多个用户将具有相同的角色。因此,这将避免每个用户在 roles table 中重复角色。 因此,角色模型将具有 'has_one' 关联,而用户模型将具有 'belongs_to' 关联。外键 'role_id' 将转到用户 table。并且,最终保持角色 table 不变。

参考帮助文档:https://guides.rubyonrails.org/association_basics.html#the-has-one-association