Rails 7:代码放/lib/而非写gem时遭遇NoMethodError问题
问题分析与解决方案
1. 先解决NoMethodError的核心问题
你写的Github::Auth模块里定义的是实例方法,但调用时直接用模块名调用(Github::Auth.authorize),相当于在调用类方法,这就触发了NoMethodError。给你三种修正方式:
方式一:直接定义为类方法(加self前缀)
# frozen_string_literal: true module Github module Auth def self.connection Faraday.new(url: 'https://github.com') end def self.authorize connection.get( '/login/oauth/authorize', params: { client_id: '<My client id here>', redirect_uri: '<My callback here>' } ) end end end
方式二:用module_function共享方法
# frozen_string_literal: true module Github module Auth def connection Faraday.new(url: 'https://github.com') end def authorize connection.get( '/login/oauth/authorize', params: { client_id: '<My client id here>', redirect_uri: '<My callback here>' } ) end module_function :connection, :authorize end end
方式三:用extend self转类方法
# frozen_string_literal: true module Github module Auth extend self def connection Faraday.new(url: 'https://github.com') end def authorize connection.get( '/login/oauth/authorize', params: { client_id: '<My client id here>', redirect_uri: '<My callback here>' } ) end end end
2. Rails中/lib目录代码的加载最佳实践
完全不用把代码移去/app/lib,按下面的配置让Rails正确加载/lib下的代码:
步骤1:配置自动加载路径
打开config/application.rb,添加以下配置,让Rails识别/lib目录:
# config/application.rb module YourAppName class Application < Rails::Application # 其他原有配置... # 把/lib加入自动加载路径 config.autoload_paths << Rails.root.join('lib') # 如果/lib下有子目录(比如/lib/github),也可以单独加: # config.autoload_paths << Rails.root.join('lib/github') end end
步骤2:遵循文件名与模块名的对应规则
Rails自动加载依赖约定,文件名要和模块层级匹配:
- 外层模块
Github对应文件lib/github.rb - 子模块
Github::Auth对应文件lib/github/auth.rb
按这个规则拆分文件,Rails就能自动识别加载,不用手动require。
步骤3:生产环境预加载(可选)
如果是生产环境,要让Rails提前加载/lib代码,避免运行时延迟,在config/application.rb再加一行:
config.eager_load_paths << Rails.root.join('lib')
3. 为什么不推荐移到/app/lib?
/app目录下的文件是Rails默认自动加载的,但/app/lib更适合和业务强绑定的工具类;而/lib专门放通用的、和业务耦合度低的代码(比如第三方API封装),更符合Rails的目录规范。
内容的提问来源于stack exchange,提问作者Luke
相关产品推荐
相关产品推荐

