【问题标题】:Type mismatch when seeding database播种数据库时类型不匹配
【发布时间】:2016-01-01 09:25:00
【问题描述】:

我正在尝试为应用程序数据库添加种子,但出现以下错误:

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

【问题讨论】:

  • 感谢您的友好纠正,@Drenmi。
  • 而不是role_id: Role.find(rl.id)你可以试试role: r1
  • 请发布关联add_foreign_key "users", "roles" 这将添加role_id 无需单独写t.integer "role_id", limit: 11
  • 试过了,@Rots,但现在我得到 ActiveRecord::UnknownAttributeError: unknown attribute 'role' for User。
  • 你是说模特,@RajarshiDas?

标签: ruby-on-rails ruby activerecord seeding


【解决方案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

希望它能解决它。

【讨论】:

  • 这已经完成了。协会没问题。当我去检查我的用户模型时,我发现了真正的问题,我将把它作为未来参考的答案发布。非常感谢!
【解决方案2】:

我在我的用户模型中添加了一个方法 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

我的播种工作正常。

所以,问题在于我试图(在此方法中)将 Role 设置为 Fixnum。

这是对 Rails 新手的建议播种不只是将某些内容强加到您的数据库中。这是对您的模型的全面评估,有时错误可能是由某些方法的执行引起的,而不仅仅是您尝试加载的值。

【讨论】:

  • 这里可能还有另一节课。堆栈跟踪是否告诉您错误发生在哪一行代码和哪个文件中?在这种情况下,课程是如何正确解释错误日志/消息。
  • 是的!这里真的是一个新手错误。我做到了!哈哈
【解决方案3】:

你的问题很简单:

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,因为这样您的应用中发生的事情并不重要 - 您的数据库将始终“默认”为您设置的角色:

$ 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(即您可以创建任何角色,只要它在您创建的初始角色之后)。

--

另一种方法是为用户设置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

【讨论】:

  • 抱歉,Role.find(rl.id).id 完全没有意义。如果我已经有 rl.id 可以搜索,我为什么要搜索只是为了找到相应的角色,然后选择我在 r.id 中已有的 id?
  • 这是你的代码。我只是解释你将如何解决它。毕竟是你用Role.find(rl.id).......
  • 是的。我得到了这个部分。我只是问这样做有什么好处。搜索知道其 id 的角色只是为了再次选择此 id。也许我错过了一些东西,但在我看来,我会这样做。不过还是谢谢。
  • 一点优势都没有。我只是说你不能用对象填充role_id,它必须是一个整数值。您会从Role.find(x).idrl.id 获得该整数要么
  • 你不会在圈子里跑,我在解释你错了什么,以及解决它的简单方法。你的模式完全不同
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-08-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多