Ruby 3.1.2中使用&method(:host_name)处理URI数组莫名报错
URI提取基础域名时第三个元素报错的原因分析
环境信息
- Ruby版本:3.1.2
- 系统:Kubuntu 22.04
问题重现
用于从URI中提取基础域名(不含子域名)的方法:
def host_name(a) URI(a).host.sub(/\Awww\./, '') end
使用示例:
uri_array = ['https://www.example.org', 'http://www.example.net/posts?a=1', 'www.example.com'] uri_array.map!(&method(:host_name))
预期输出:
['example.org', 'example.net', 'example.com']
实际触发报错:
(irb):14:in `host_name': undefined method `sub' for nil:NilClass (NoMethodError)
数组最终修改结果:
[ [0] "example.org", [1] "example.net", [2] "www.example.com" ] ### 提问 为何处理数组第三个元素时失败? ## 原因解析 第三个元素`www.example.com`未携带协议头(http/https),Ruby的`URI`类解析这类字符串时,会将其整体识别为**路径(path)**而非主机名(host),导致`URI(a).host`返回`nil`,后续调用`sub`方法时触发`NoMethodError`。 直接在irb中验证: ```ruby URI('www.example.com').host # => nil URI('www.example.com').path # => "www.example.com"
前两个元素因带有协议头,URI能正确解析出host字段,所以可以正常执行sub操作。
修复方案
给未携带协议头的字符串自动补充默认协议(如http://)后再解析:
def host_name(a) uri_str = a.start_with?('http://', 'https://') ? a : "http://#{a}" URI(uri_str).host.sub(/\Awww\./, '') end
测试修复后的方法:
uri_array = ['https://www.example.org', 'http://www.example.net/posts?a=1', 'www.example.com'] uri_array.map!(&method(:host_name)) # 输出:["example.org", "example.net", "example.com"]
这样即可正确处理所有三种格式的字符串。
内容的提问来源于stack exchange,提问作者willyab
相关产品推荐
相关产品推荐

