Ruby on Rails中已定义方法仍报undefined method错误
问题:Rails开发中修改代码后出现NoMethodError,重启Puma才能恢复
修改代码(比如将控制器第5行从i = c.f1改为i = c.f2)后,出现以下错误:
NoMethodError in Api::V1::AppController#login
undefined method `f2' for #Master::Utilities:0x00007fdb6ceb42c8
即使撤销代码修改,错误依然存在,只有重启Puma后才能恢复正常。
相关代码
控制器代码(app/controllers/api/v1/app_controller.rb)
class Api::V1::AppController < ApplicationController def login c = Master::Utilities.new i = c.f1 z = c.f2 render json: {m: 'login' , msg: "hello" , data: "#{z} - #{i}" } , status: :ok end end
Lib目录代码结构及文件内容
- lib/master/utilities.rb
module Master class Utilities Dir[File.join(__dir__, 'code', '*.rb')].each { |file| require file } end end
- lib/master/code/1.rb
module Master class Utilities def f1 "Function 1" end end end
- lib/master/code/2.rb
module Master class Utilities def f2 "Function 2" end end end
自动加载配置(config/application.rb)
config.paths.add Rails.root.join('lib').to_s, eager_load: true
问题原因
- 手动require导致加载跟踪失效:你在
Master::Utilities类内部手动require子目录文件,Rails自动加载机制无法跟踪这类手动加载的文件变化。开发环境下,Rails只会重新加载它自动管理的文件,手动require的文件在启动后不会被重新加载。 - eager_load配置不符合开发环境需求:给lib目录设置
eager_load: true,会让Rails在启动时一次性加载所有lib文件,之后即使修改文件也不会重新加载——eager_load是启动时的一次性行为,开发环境应保持懒加载模式。 - 内存类定义未更新:修改代码后,内存中的
Master::Utilities类还是旧版本,撤销修改也不会刷新内存中的类,只有重启Puma才能重新加载所有文件、更新类定义。
解决方案
方案一:调整Rails自动加载配置(推荐)
- 修改
config/application.rb中的配置,移除eager_load: true,改为添加自动加载路径:
config.autoload_paths << Rails.root.join('lib')
- 在
config/environments/development.rb中确保eager_load为false(开发环境默认即为false,明确设置更稳妥):
config.eager_load = false
- 修改
lib/master/utilities.rb,删除手动require代码,让Rails自动加载子目录文件:
module Master class Utilities end end
Rails自动加载会根据模块结构,自动识别并加载lib/master/code下的文件——这些文件都属于Master::Utilities模块,符合自动加载的命名规则。
方案二:手动触发重新加载(临时方案)
如果不想调整配置,修改lib文件后可通过以下方式手动刷新:
- 在Rails控制台执行
load 'lib/master/utilities.rb'及对应子文件,但容易遗漏,不长期推荐。 - 执行
spring stop重启Spring,再重新启动服务器,Spring会重新加载所有文件。
内容的提问来源于stack exchange,提问作者Hadi Barak
相关产品推荐
相关产品推荐

