我试图为应用程序数据库播种,但是我收到了以下错误:
ActiveRecord::AssociationTypeMismatch: Role(#97332160) expected,
got Fixnum(#76482890)
以下是schema.rb
关于与问题相关的两个表的部分:
create_table "roles", force: :cascade do |t|
t.string "role", limit: 50, null: false
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
create_table "users", force: :cascade do |t|
t.string "first_name", limit: 100, null: false
t.string "surname", limit: 100, null: false
t.string "email", limit: 255
t.integer "role_id", limit: 11
t.string "password", limit: 150
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
add_index "users", ["first_name"], name: "index_users_on_first_name", using: :btree
add_index "users", ["role_id"], name: "index_users_on_role_id", using: :btree
add_index "users", ["surname"], name: "index_users_on_surname", using: :btree
add_foreign_key "users", "roles"
以下是我的seeds.rb
命令:
rl = Role.create(role: "root")
User.create(first_name: "Edvaldo", surname: "Silva de Almeida Júnior", email: "edvaldo@my.domain.com", role_id: rl.id, password: "my_password")
rl = Role.create(role: "admin")
User.create(first_name: "Daiely", surname: "Fanchin", email: "daiely@my.domain.com", role_id: rl.id, password: "other_password")
rl = Role.create(role: "user")
User.create(first_name: "César", surname: "Silva", email: "cesar@my.domain.com", role_id: rl.id, password: "yet_other_password")
我找到了a question,其中接受的答案显示我应该执行以下操作:
rl = Role.create(role: "root")
User.create(first_name: "Edvaldo", surname: "Silva de Almeida Júnior", email: "edvaldo@my.domain.com", role_id: Role.find(rl.id), password: "my_password")
我试过了,但得到了同样的错误!此外,我使用role_id
作为关联,而不是角色本身。因此,就我而言,它应该收到Fixnum
,而不是Role
。
答案 0 :(得分:1)
add_foreign_key "users", "roles"
这会向用户添加role_id
列,无需单独编写t.integer "role_id", limit: 11
应该有一些关联
class User < ActiveRecord::Base
belongs_to :role
end
和
create_table "users", force: :cascade do |t|
t.string "first_name", limit: 100, null: false
t.string "surname", limit: 100, null: false
t.string "email", limit: 255
t.reference "role", index: true
t.string "password", limit: 150
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
add_foreign_key "users", "roles", column: :role_id
希望它可以解决它。
答案 1 :(得分:1)
我在我的用户模型中添加了 set_default_role 方法。
class User < ActiveRecord::Base
has_one :role
after_initialize :set_default_role, :if => :new_record?
def set_default_role
if User.count == 0
self.role ||= 1
else
self.role ||= 2
end
end
end
但是这个方法错误,一旦我把它重写为
def set_default_role
if User.count == 0
self.role_id ||= 1
else
self.role_id ||= 2
end
end
我的播种工作正常。
所以,问题在于我是tryind(在此方法中)将一个角色设置为Fixnum。
这可以作为Rails新手的建议:播种不只是强迫你的数据库。它是对模型的完整评估,有时可能会由于某些方法的执行而导致错误,而不仅仅是您尝试加载的值。
答案 2 :(得分:1)
你遇到的问题很简单:
role_id: Role.find(rl.id)
.find()
返回Role
个对象。
您的create
方法需要foreign_key
(整数)(role_id: [int]
)。
简单的修复方法是:
User.create(... role_id: Role.find(rl.id).id ...)
..或......
User.create(... role_id: rl.id ...)
......甚至更好......
User.create(... role: rl ...)
-
真正的解决方法是 在数据库中设置default
,或者手动设置role_id
,就像在提交的答案中一样。
我强烈建议您使用数据库default
,因为在您的应用中发生的事情并不重要 - 您的数据库将始终&#34;默认&#34;你设定的角色:
$ rails g migration SetDefaultForRole
$ db/migrate/set_default_for_role_____.rb
class SetDefaultForRole < ActiveRecord::Migration
def change
change_column :users, :role_id, :integer, default: 0
end
end
$ rake db:migrate
这样做的缺点是将设置此整数默认值(除非您再次更改了数据库)。虽然本身不是问题,但它会为您的Role
模型创建antipattern(IE可以创建任何角色,只要它在之后 你做的一个)。
-
另一种方法是为用户设置Role
。
你已经拥有了这个;你可以清理它:
#app/models/user.rb
class User < ActiveRecord::Base
before_create :set_role, if: Proc.new { |m| m.role_id.blank? }
private
def set_role
self.role_id = "1" if User.count == 0
end
end