NameError - 创建用户时常量名称错误(设计,Rails)

NameError - wrong constant name when creating user (Devise, Rails)

我正在使用 Rails 5.0.5 和 Devise 4.3.0 进行身份验证。这个应用程序已经 运行 顺利运行了几个月,直到我向我的用户模型添加了一个 'type'=>'string' 属性并尝试创建一个新用户。提交表单给我一个 500 内部服务器错误。在这个例子中,User.type = 'hunter'。

 NameError - wrong constant name hunter:

 activesupport (5.0.5) lib/active_support/inflector/methods.rb:268:in `const_get'
  activesupport (5.0.5) lib/active_support/inflector/methods.rb:268:in `block in constantize'
  activesupport (5.0.5) lib/active_support/inflector/methods.rb:266:in `each'
  activesupport (5.0.5) lib/active_support/inflector/methods.rb:266:in `inject'
  activesupport (5.0.5) lib/active_support/inflector/methods.rb:266:in `constantize'
  activesupport (5.0.5) lib/active_support/dependencies.rb:583:in `get'
  activesupport (5.0.5) lib/active_support/dependencies.rb:614:in `constantize'
  activerecord (5.0.5) lib/active_record/inheritance.rb:177:in `find_sti_class'
  activerecord (5.0.5) lib/active_record/inheritance.rb:209:in `subclass_from_attributes'
  activerecord (5.0.5) lib/active_record/inheritance.rb:55:in `new'
  devise (4.3.0) lib/devise/models/registerable.rb:20:in `new_with_session'
  app/models/user.rb:58:in `new_with_session'

user.rb:

def self.new_with_session(params, session)
    if session['devise.user_attributes']
      new(session['devise.user_attributes']) do |user|
        user.attributes = params
        user.valid?
      end
    else
      super
    end
  end

是Rails认为这个属性值是一个ClassName??似乎无法弄清楚这一点。非常感谢任何帮助。

ActiveRecord 默认将 type 列用于单一 Table 继承 (STI),并且 type 值应命名为 class。大概你没有 hunter class 所以你从 ActiveRecord 的内部深处得到一个令人困惑的 NameError

来自fine manual:

inheritance_column()
Defines the name of the table column which will store the class name on single-table inheritance situations.

The default inheritance column name is type, which means it's a reserved word inside Active Record. To be able to use single-table inheritance with another column name, or to use the column type in your own model for something else, you can set inheritance_column:

self.inheritance_column = 'zoink'

要么将您的 type 列重命名为其他名称,要么告诉 ActiveRecord 为 STI 使用其他列名称:

class User < ApplicationRecord
  self.inheritance_column = 'there_is_no_sti_here' # Or whatever you're not using for a column name.
end

使用 self.inheritance_column = nil 也有效。


如果您经常这样做,那么您可以通过添加关注点使其具有声明性:

module STISuppression
  extend ActiveSupport::Concern
  included do
    self.inheritance_column = nil
  end
end

然后说这样的话:

class SomeModel < ApplicationRecord
  include STISuppression
end

同样的效果,但它让你清楚地知道你在做什么。