我是RoR的新手,我正在尝试做一个简单的实验。我想要一个用户模型和一个角色模型。每个用户只有一个角色,但单个角色可能会引用多个用户。
所以,这是我的模特:
class Role < ActiveRecord::Base
has_many :user
end
class User < ActiveRecord::Base
has_one :role
end
以下是迁移:
class CreateRoles < ActiveRecord::Migration
def change
create_table :roles do |t|
t.string :name, null: false, index: true, unique: true, limit: 16
t.integer :permissions, null: false
end
end
end
class CreateUsers < ActiveRecord::Migration
def change
create_table :users do |t|
t.string :email, null: false, index: true, unique: true, limit: 128
t.string :password_digest, null: false, limit: 40
t.string :password_salt, null: false, limit: 40
t.string :screen_name, default: '', limit: 32
t.belongs_to :role, index: true, foreign_key: true
t.timestamps null: false
end
end
end
我想要的是当我尝试将用户与不存在的角色连接时引发异常:
user = User.create(email: 'user@example.com', password_digest: 'pwd_dig',
password_salt: 'salt', role_id: 10)
不幸的是,无论id 10的角色是否存在,都可以创建新用户。
那么,我如何在这里强制执行foreign_key检查?
还有一个问题。如果我尝试这样做:
user = User.create(email: 'user@example.com', password_digest: 'pwd_dig',
password_salt: 'salt', role: role)
它引发了异常,因为role没有属性user_id。没有办法这样做,是吗?
答案 0 :(得分:2)
我是RoR的新手
欢迎!!
http://10.0.2.2/idiomjson/insertnew.php
这将允许您进行以下操作:
#app/models/role.rb
class Role < ActiveRecord::Base
has_many :users
end
#app/models/user.rb
class User < ActiveRecord::Base
belongs_to :role
validates :role_id, presence: true, on: :create
validate :check_role, on: :create
private
def check_role
errors.add(:role_id, "Role doesn't exist") unless Role.exists? role_id
end
end
因为你是新人,我会给你一些信息:
<强> 1。协会强>
您的关联有点不正确 - 您最好使用belongs_to/has_many
relationship:
#app/controllers/users_controller.rb
class UsersController < ApplicationController
def new
@user = User.new
@roles = Role.all
end
def create
@user = User.new user_params
@user.save
end
private
def user_params
params.require(:user).permit(:email, :etc, :role)
end
end
#app/views/users/new.html.erb
<%= form_for @user do |f| %>
<%= f.email_field :email %>
<%= f.collection_select :role_id, @roles, :id, :name %>
<%= f.submit %>
<% end %>
会在belongs_to
模型中分配foreign_key
,允许您引用并验证它。
-
<强> 2。 Custom validator 强>
其次,您将能够使用验证来检查User
是否已正确设置。
每次保存Rails模型时,它都会调用您设置的一系列验证器 - 允许您调用检查角色是否存在等功能。
答案 1 :(得分:2)
您可以做的是添加自定义验证:
class User < ActiveRecord::Base
belongs_to :role
validate :existance_of_role
private
def existance_of_role
if role_id && !Role.exists?(role_id)
errors.add(:role, "must already exist.")
end
end
end
您还需要使用belongs_to :role
。 has_one
会将foreign_key置于Role
模型的关系中而不是用户身上。
此外,如果您想在数据库级别强制执行用户角色,您可以向users.role_id
添加NOT NULL约束。
运行:rails g migration AddNotNullConstraintToUsers
然后编辑创建的迁移文件:
class AddNotNullConstraintToUsers < ActiveRecord::Migration
def change
change_column_null(:users, :role_id, false)
end
end
运行迁移后,您可以更改验证,以便在role_id为nil时也会添加错误。
private
def existance_of_role
errors.add(:role, "must already exist.") unless Role.exists?(role_id)
end
您可以对validates_presence_of :role
执行相同的操作,但这不会强制该角色已预先存在。
答案 2 :(得分:1)
您可以在用户模型中添加此验证器
class User < ActiveRecord::Base
has_one :role
validate :role_id_exists
def role_id_exists
return false if Role.find_by_id(self.role_id).nil?
end
end