非Rails Ruby项目中引入Errors模块报uninitialized constant Errors错误
报错原因
非Rails Ruby应用没有自动文件加载机制,运行formatter.rb时errors.rb尚未被加载,因此Ruby无法识别Errors常量,才会抛出该错误。
另外你的代码还有一处隐藏问题:module_function仅会将当前模块内定义的实例方法转为可直接调用的模块方法,从Errors引入的实例方法默认不会被转换,解决常量问题后还会遇到方法不存在的报错。
解决方案
方案1:保留include写法
- 首先在
formatter.rb顶部引入同目录下的errors.rb:
# lib/formatter.rb 首行添加 require_relative 'errors'
- 调整Formatter模块代码,主动将引入的
error_class设为模块方法:
module Formatter module_function include ::Errors # 新增这行,把引入的方法转为模块可调用 module_function :error_class def format(number) number.delete!(' ') raise error_class(:invalid_number), 'Invalid phone number, check your entries' unless valid?(number) end # 补充缺失的valid?方法,否则会报方法不存在错误 def valid?(number) # 此处替换为你的手机号校验逻辑 number.match?(/\A1[3-9]\d{9}\z/) end end
方案2:直接调用Errors模块方法(更简洁,推荐)
不需要引入模块,直接把error_class改为Errors的模块方法调用即可,避免作用域冲突问题:
- 调整
errors.rb代码:
module Errors class FormatterExceptionError < StandardError; end PhoneNumberInvalid = Class.new(FormatterExceptionError) # 方法前加self.转为模块方法 def self.error_class(status) case status when :invalid_number PhoneNumberInvalid end end end
- 调整
formatter.rb代码:
# 首行引入errors文件 require_relative 'errors' module Formatter module_function def format(number) number.delete!(' ') # 直接调用Errors的模块方法,不需要include raise Errors.error_class(:invalid_number), 'Invalid phone number, check your entries' unless valid?(number) end # 补充valid?方法 def valid?(number) # 校验逻辑 number.match?(/\A1[3-9]\d{9}\z/) end end
内容的提问来源于stack exchange,提问作者mr_muscle
相关产品推荐
相关产品推荐

