播种数据库时输入不匹配

时间:2016-01-01 09:25:01

标签: ruby-on-rails ruby activerecord seeding

我试图为应用程序数据库播种,但是我收到了以下错误:

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

3 个答案:

答案 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