"Unable to autoload constant User" 在开发中更改代码时出错
"Unable to autoload constant User" error when changed code in development
我的 rails 应用程序有问题。从 Rails 3 更新到 4 后。
当我在开发模式下启动服务器后浏览页面时,一切都很好。
但是在一次代码更改(甚至添加 space)之后,每个页面请求都会显示以下错误。
Unable to autoload constant User, expected
/path/to/my/rails-app/app/models/user.rb to define it
文件就在那里并定义了 class:
class User < ActiveRecord::Base
…
我在 application.rb
中用 config.autoload_paths
和 config.eager_load_paths
尝试了很多东西,但没有成功。
停用 spring 也无济于事。
开发一个应用程序并在每次更改后都必须重新启动服务器似乎是 90 年代。
$ rails -v
Rails 4.2.4
$ ruby -v
ruby 2.1.7p400 (2015-08-18 revision 51632) [x86_64-linux]
一些相关配置:
development.rb
MyApp::Application.configure do
# Settings specified here will take precedence over those in config/application.rb
# In the development environment your application's code is reloaded on
# every request. This slows down response time but is perfect for development
# since you don't have to restart the webserver when you make code changes.
config.cache_classes = false
# Do not eager load code on boot. This avoids loading your whole application
# just for the purpose of running a single test. If you are using a tool that
# preloads Rails for running tests, you may have to set it to true.
config.eager_load = false
# Show full error reports and disable caching
config.consider_all_requests_local = true
config.action_controller.perform_caching = false
# Don't care if the mailer can't send
config.action_mailer.raise_delivery_errors = false
# Print deprecation notices to the Rails logger
config.active_support.deprecation = :log
# Only use best-standards-support built into browsers
config.action_dispatch.best_standards_support = :builtin
# Do not compress assets
config.assets.compress = false
# Expands the lines which load the assets
config.assets.debug = true
config.action_mailer.delivery_method = :test
config.action_mailer.default_url_options = {
host: 'localhost',
port: 3000
}
end
application.rb
module Serviceportal
class Application < Rails::Application
# Enable the asset pipeline
config.assets.enabled = true
# Version of your assets, change this if you want to expire all your assets
config.assets.version = '1.0'
[… some asset precompile stuff …]
# Configure the default encoding used in templates for Ruby 1.9.
config.encoding = 'utf-8'
# Custom directories with classes and modules you want to be autoloadable.
config.autoload_paths += Dir["#{config.root}/app/mailers",
"#{config.root}/app/controllers/concerns",
"#{config.root}/app/models/concerns",
"#{config.root}/app/decorators/concerns",
"#{config.root}/lib",
"#{config.root}/lib/shared"
]
config.eager_load_paths += Dir["#{config.root}/app/mailers",
"#{config.root}/app/controllers/concerns",
"#{config.root}/app/models/concerns",
"#{config.root}/app/decorators/concerns",
"#{config.root}/lib",
"#{config.root}/lib/shared"]
# Set Time.zone default to the specified zone and make Active Record auto-convert to this zone.
# Run "rake -D time" for a list of tasks for finding time zone names. Default is UTC.
config.time_zone = 'Berlin'
# The default locale is :en and all translations from config/locales/*.rb,yml are auto loaded.
# config.i18n.load_path += Dir[Rails.root.join('my', 'locales', '*.{rb,yml}').to_s]
config.i18n.default_locale = :de
[… some SQL and active support stuff …]
config.action_controller.include_all_helpers = false
config.action_controller.action_on_unpermitted_parameters = :raise
# Do not swallow errors in after_commit/after_rollback callbacks.
config.active_record.raise_in_transactional_callbacks = true
end
end
编辑:错误大部分出现在lib/auth/user_proxy.rb在以下功能中。也许这有助于缩小可能原因的范围。
def self.usertype_allowed?(type)
[ User, TempCustomer ].include? type.classify.safe_constantize rescue false
end
编辑 2: 将编辑 1 中的 class 名称字符串化有帮助(感谢@Benjamin Sinclaire)。但只会导致下一个错误。我也可以避免使用 classes。但是在 app/controllers/concerns/security.rb 中的以下错误没有什么可以改变的?
Unable to autoload constant User, expected
/path/to/my/rails-app/app/models/user.rb to define it
代码:
def set_current_user
User.current = current_user
end
当前用户保存在线程中(代码来自 /path/to/my/rails-app/app/models/user.rb
def self.current
Thread.current['current_user']
end
def self.current=(user)
Thread.current['current_user'] = user
end
再说一遍:它在开发中服务器重启后工作,直到我在某处更改一些代码。
1 看看有没有多级的class或者模块的声明一行一行的改成多行声明的
而不是
class Parent::Sub::Child
end
做
module Parent
module Sub
class Child
end
end
end
2 检查您的模型关联定义,并确保您从不使用常量。请改用字符串。
而不是
belongs_to :manager, class_name: User
做
belongs_to :manager, class_name: 'User'
3 刚刚看到您的编辑。你能这样重构吗?
# I assume `type` is a string or such, so we can compare classes
# names instead of constants, and get rid of `safe_constantize`
def self.usertype_allowed?(type)
['User', 'TempCustomer'].include? type.classify rescue false
end
4 序列化线程存储中的活动记录对象不是一个好主意。改为存储用户 ID,如下所示:
def set_current_user
User.current = current_user.id
end
def self.current
Thread.current['current_user_id']
end
def self.current=(user_id)
Thread.current['current_user_id'] = user_id
end
您不需要在自动加载/预加载路径中包含 app/models/concerns
和 app/controllers/concerns
,因为它们默认包含在 Rails 4: https://signalvnoise.com/posts/3372-put-chubby-models-on-a-diet-with-concerns
还要确保将您的问题定义为模块,扩展 ActiveSupport::Concern
并使用适当的文件名
#taggable.rb
module Taggable
extend ActiveSupport::Concern
end
您的问题的另一个原因可能是 app/decorators/concerns
、lib
、lib/shared
中的某些模块/ class 正在使用 User
class
尚未加载或它的某些依赖项未加载,因此请尝试在这些文件的顶部添加 require_relative path_to_user.rb
-----编辑------
尝试在 lib/auth/user_proxy.rb
的顶部添加
require_dependency 'app/models/user'
这样你就可以消除自动加载 User
class 时的任何歧义,并且你不会乱用 Rails 自动加载,请在此处查看更多信息:http://guides.rubyonrails.org/autoloading_and_reloading_constants.html#require-dependency , http://guides.rubyonrails.org/autoloading_and_reloading_constants.html#common-gotchas
同样的问题,但在带有名称空间的引擎中。在代码更改/自动加载之前,生产或开发中没有问题。
解决方案是
- 检查双重定义(有 none)
- 检查模块嵌套是否严格遵循rails文件系统中的约定。
我在 myengine/app/myns/subns/obj.rb
下有 myns
但是 myns
被忽略了,因为它在 根 的应用程序文件夹,因此将 myns
文件夹移动到 子文件夹 myengine/app/lib/myns
解决了问题。
注意: rails 错误消息非常明确地说明了模块嵌套(同时仍然指向文件系统中错误的 .rb 文件),因此请仔细查看错误。错误是 'Unable to autoload constant subns/obj.rb in .../myns/subns/obj.rb'。 Rails 在这种情况下建议不正确的文件位置(存在)具有误导性。
在 Rails/Ruby 更新期间,我抽空调查了这个问题并最终找到了原因。
用户 class 多年来一直使用 unloadable
。这导致了自 Rails 4 以来的问题。现在我删除了它,之后没有发现任何问题。
我的 rails 应用程序有问题。从 Rails 3 更新到 4 后。 当我在开发模式下启动服务器后浏览页面时,一切都很好。
但是在一次代码更改(甚至添加 space)之后,每个页面请求都会显示以下错误。
Unable to autoload constant User, expected /path/to/my/rails-app/app/models/user.rb to define it
文件就在那里并定义了 class:
class User < ActiveRecord::Base
…
我在 application.rb
中用 config.autoload_paths
和 config.eager_load_paths
尝试了很多东西,但没有成功。
停用 spring 也无济于事。
开发一个应用程序并在每次更改后都必须重新启动服务器似乎是 90 年代。
$ rails -v
Rails 4.2.4
$ ruby -v
ruby 2.1.7p400 (2015-08-18 revision 51632) [x86_64-linux]
一些相关配置:
development.rb
MyApp::Application.configure do
# Settings specified here will take precedence over those in config/application.rb
# In the development environment your application's code is reloaded on
# every request. This slows down response time but is perfect for development
# since you don't have to restart the webserver when you make code changes.
config.cache_classes = false
# Do not eager load code on boot. This avoids loading your whole application
# just for the purpose of running a single test. If you are using a tool that
# preloads Rails for running tests, you may have to set it to true.
config.eager_load = false
# Show full error reports and disable caching
config.consider_all_requests_local = true
config.action_controller.perform_caching = false
# Don't care if the mailer can't send
config.action_mailer.raise_delivery_errors = false
# Print deprecation notices to the Rails logger
config.active_support.deprecation = :log
# Only use best-standards-support built into browsers
config.action_dispatch.best_standards_support = :builtin
# Do not compress assets
config.assets.compress = false
# Expands the lines which load the assets
config.assets.debug = true
config.action_mailer.delivery_method = :test
config.action_mailer.default_url_options = {
host: 'localhost',
port: 3000
}
end
application.rb
module Serviceportal
class Application < Rails::Application
# Enable the asset pipeline
config.assets.enabled = true
# Version of your assets, change this if you want to expire all your assets
config.assets.version = '1.0'
[… some asset precompile stuff …]
# Configure the default encoding used in templates for Ruby 1.9.
config.encoding = 'utf-8'
# Custom directories with classes and modules you want to be autoloadable.
config.autoload_paths += Dir["#{config.root}/app/mailers",
"#{config.root}/app/controllers/concerns",
"#{config.root}/app/models/concerns",
"#{config.root}/app/decorators/concerns",
"#{config.root}/lib",
"#{config.root}/lib/shared"
]
config.eager_load_paths += Dir["#{config.root}/app/mailers",
"#{config.root}/app/controllers/concerns",
"#{config.root}/app/models/concerns",
"#{config.root}/app/decorators/concerns",
"#{config.root}/lib",
"#{config.root}/lib/shared"]
# Set Time.zone default to the specified zone and make Active Record auto-convert to this zone.
# Run "rake -D time" for a list of tasks for finding time zone names. Default is UTC.
config.time_zone = 'Berlin'
# The default locale is :en and all translations from config/locales/*.rb,yml are auto loaded.
# config.i18n.load_path += Dir[Rails.root.join('my', 'locales', '*.{rb,yml}').to_s]
config.i18n.default_locale = :de
[… some SQL and active support stuff …]
config.action_controller.include_all_helpers = false
config.action_controller.action_on_unpermitted_parameters = :raise
# Do not swallow errors in after_commit/after_rollback callbacks.
config.active_record.raise_in_transactional_callbacks = true
end
end
编辑:错误大部分出现在lib/auth/user_proxy.rb在以下功能中。也许这有助于缩小可能原因的范围。
def self.usertype_allowed?(type)
[ User, TempCustomer ].include? type.classify.safe_constantize rescue false
end
编辑 2: 将编辑 1 中的 class 名称字符串化有帮助(感谢@Benjamin Sinclaire)。但只会导致下一个错误。我也可以避免使用 classes。但是在 app/controllers/concerns/security.rb 中的以下错误没有什么可以改变的?
Unable to autoload constant User, expected /path/to/my/rails-app/app/models/user.rb to define it
代码:
def set_current_user
User.current = current_user
end
当前用户保存在线程中(代码来自 /path/to/my/rails-app/app/models/user.rb
def self.current
Thread.current['current_user']
end
def self.current=(user)
Thread.current['current_user'] = user
end
再说一遍:它在开发中服务器重启后工作,直到我在某处更改一些代码。
1 看看有没有多级的class或者模块的声明一行一行的改成多行声明的
而不是
class Parent::Sub::Child
end
做
module Parent
module Sub
class Child
end
end
end
2 检查您的模型关联定义,并确保您从不使用常量。请改用字符串。
而不是
belongs_to :manager, class_name: User
做
belongs_to :manager, class_name: 'User'
3 刚刚看到您的编辑。你能这样重构吗?
# I assume `type` is a string or such, so we can compare classes
# names instead of constants, and get rid of `safe_constantize`
def self.usertype_allowed?(type)
['User', 'TempCustomer'].include? type.classify rescue false
end
4 序列化线程存储中的活动记录对象不是一个好主意。改为存储用户 ID,如下所示:
def set_current_user
User.current = current_user.id
end
def self.current
Thread.current['current_user_id']
end
def self.current=(user_id)
Thread.current['current_user_id'] = user_id
end
您不需要在自动加载/预加载路径中包含 app/models/concerns
和 app/controllers/concerns
,因为它们默认包含在 Rails 4: https://signalvnoise.com/posts/3372-put-chubby-models-on-a-diet-with-concerns
还要确保将您的问题定义为模块,扩展 ActiveSupport::Concern
并使用适当的文件名
#taggable.rb
module Taggable
extend ActiveSupport::Concern
end
您的问题的另一个原因可能是 app/decorators/concerns
、lib
、lib/shared
中的某些模块/ class 正在使用 User
class
尚未加载或它的某些依赖项未加载,因此请尝试在这些文件的顶部添加 require_relative path_to_user.rb
-----编辑------
尝试在 lib/auth/user_proxy.rb
require_dependency 'app/models/user'
这样你就可以消除自动加载 User
class 时的任何歧义,并且你不会乱用 Rails 自动加载,请在此处查看更多信息:http://guides.rubyonrails.org/autoloading_and_reloading_constants.html#require-dependency , http://guides.rubyonrails.org/autoloading_and_reloading_constants.html#common-gotchas
同样的问题,但在带有名称空间的引擎中。在代码更改/自动加载之前,生产或开发中没有问题。
解决方案是
- 检查双重定义(有 none)
- 检查模块嵌套是否严格遵循rails文件系统中的约定。
我在 myengine/app/myns/subns/obj.rb
下有 myns
但是 myns
被忽略了,因为它在 根 的应用程序文件夹,因此将 myns
文件夹移动到 子文件夹 myengine/app/lib/myns
解决了问题。
注意: rails 错误消息非常明确地说明了模块嵌套(同时仍然指向文件系统中错误的 .rb 文件),因此请仔细查看错误。错误是 'Unable to autoload constant subns/obj.rb in .../myns/subns/obj.rb'。 Rails 在这种情况下建议不正确的文件位置(存在)具有误导性。
在 Rails/Ruby 更新期间,我抽空调查了这个问题并最终找到了原因。
用户 class 多年来一直使用 unloadable
。这导致了自 Rails 4 以来的问题。现在我删除了它,之后没有发现任何问题。