Ruby on rails Ruby on Rails外键字段不能为空
我有一个Rails应用程序,其中有一个Ruby on rails Ruby on Rails外键字段不能为空,ruby-on-rails,Ruby On Rails,我有一个Rails应用程序,其中有一个用户模型和一个角色模型 角色可以是超级用户、管理员或用户 “我的用户”表迁移如下所示: class CreateUsers < ActiveRecord::Migration[5.0] def change create_table :users do |t| t.string :first_name t.string :last_name t.string :username t.strin
用户
模型和一个角色
模型
角色可以是超级用户、管理员或用户
“我的用户”表迁移如下所示:
class CreateUsers < ActiveRecord::Migration[5.0]
def change
create_table :users do |t|
t.string :first_name
t.string :last_name
t.string :username
t.string :email
t.string :password
t.string :password_digest
t.boolean :banned
t.references :role, foreign_key: true
t.timestamps
end
end
end
Rails告诉我,我的用户模型的角色
字段不能为空
所以我想,我希望通过HTTP POST创建的用户默认为“用户”角色,所以我的用户模型中有这样一个角色:
class User < ApplicationRecord
belongs_to :role
has_secure_password
# validates :role, allow_nil: true
before_validation do
self.banned = false
# Users created through HTTP POST request should always
# default to 'User' role.
# Rails console created users will be explicitly set
# to 'Superuser' or 'Admin' roles.
self.role = Role.find_by({title: 'User'})
puts "User model set role fired!"
end
end
即使我正在执行更新操作而不是创建用户操作。我想知道Bcrypt是否在干预
当我使用rails控制台命令生成我的用户模型时,也许我只需要password\u digest
字段
需要更多的调查
更新2
我想我解决了…至少我所有的测试现在都通过了,尽管我仍然怀疑:D
我创建了一个新的迁移文件并从Users表中删除了Password列,我的测试仍然通过,包括创建一个新用户
我仍然能够在我的rails控制台--sandbox中创建用户
我认为还有一个错误是我的用户强参数需要将字段从:role
更改为:role\u id
。尽管用户模型字段名为role
,但在数据库中,外键实际上是幕后的role\u id
。您可以根据是否已经存在值来进行赋值
before_validation do
self.banned = false if banned.nil?
self.role ||= Role.find_by(title: 'User')
end
或者,您只能在创建时执行此操作
before_validation do
if new_record?
self.banned = false
self.role = Role.find_by(title: 'User')
end
end
但坦率地说,我通常看到的初始默认设置是在控制器的create
方法中设置的
def create
@user = User.assign_attributes(user_params)
@user.banned = false
@user.role = Role.find_by(title: 'User')
if @user.save
# ...
您只能在创建时使用操作前的:
before_validation :my_action, on: :create
史蒂夫,谢谢你的建议。我试过了,当我尝试更新用户的用户名时,出现了新的错误,关于密码不能为空。我开始想也许我的用户模型创建表不需要密码
和密码_摘要
字段。。。
def create
@user = User.assign_attributes(user_params)
@user.banned = false
@user.role = Role.find_by(title: 'User')
if @user.save
# ...
before_validation :my_action, on: :create