Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Unearth Ruby builtin Gems
 發掘 Ruby 的內建 Gems

Johnlin
December 16, 2023
120

Unearth Ruby builtin Gems
 發掘 Ruby 的內建 Gems

Johnlin

December 16, 2023
Tweet

Transcript

  1. Ruby Conf Taiwan 2023 About ME 關於我 • John Lin

    • @johnlinvc • Principle Architect @ West Pharma 西 式亞洲 • https://johnlin.vc
  2. Ruby Conf Taiwan 2023 Agenda 大 綱 • What is

    builtin gem?
 什麼是內建 gems • Introduce some useful / interesting builtin gems.
 介紹有 用 /有趣的內建 gems。 • Slide 投影片 : https://johnlin.vc/ruby-conf-tw-2023/
  3. Ruby Conf Taiwan 2023 What is builtin Gem? 什麼是內建 Gems?

    • Gems that come with the default ruby installation.
 安裝 Ruby 時就會預設安裝的 Gems。 • Part of the Standard library.
 Standard library 的 一 部分。 • To provide extended features. 
 提供額外功能。 • 3 types of Standard libraries. 有 3 種 Standard libraries
 Default Library, Default Gem & Bundled Gem.
  4. Ruby Conf Taiwan 2023 Default Library • Ruby version/implementation related

    library. Will NOT become Gems.
 Ruby 版本/實作相關的 library。不會變成 Gems。 • Example 範例 • mkmf: Generate Make fi le for C extensions (only in MRI)
 幫 C extension 產 生 Make fi le (只有 MRI 有) • rbcon fi g: List system info like size of Long. (JRuby use FFI) (MRI use c extension)
 列舉系統資訊,像是 long 的 大 小 。 (JRuby 用 FFI) (MRI 用 c extension)
  5. Ruby Conf Taiwan 2023 Default gem • Installed by default.

    預設就會安裝。 • Can be upgraded. 可以升級。 • Can NOT be deleted. 不能被刪除。 • Maintained by ruby core. 由 Ruby core 維護。
  6. Ruby Conf Taiwan 2023 Bundled gem • Starting from 2.2.0

    https://bugs.ruby-lang.org/issues/9852 
 2.2.0 開始 • Installed by default. 預設就會安裝 • Can be upgraded & uninstalled. 可以升級或刪除。 • Need to be added to Gem fi le when using Bundler。 
 用 Bundler 的時候需要加進 Gem fi le 裏。 • Not maintained by Ruby core. 不由 Ruby core 維護。
  7. Ruby Conf Taiwan 2023 Why default/bundled gems? • To provide

    extra features. 提供額外功能。 • Unbind the development of these gem from the interpreter itself. 
 讓這些 Gem 可以獨立於直譯器外開發。
  8. Ruby Conf Taiwan 2023 Default vs bundled gems • Bundled

    gems can be uninstalled.
 Bundled gems 可以被反安裝。 • Bundled gems need to be added to Gem fi le when using Bundler。 
 bundled gems 在 用 Bundler 的時候需要加進 Gem fi le 裏。 • There's an e ff ort to promote default gem into bundled gem by @hsbt.
 @hsbt 正在努 力 的把 default gem 升格為 bundled gem。
  9. Ruby Conf Taiwan 2023 Find out builtin gems • https://stdgems.org/

    • Or Use the source.
 或是看原始碼。
  10. Ruby Conf Taiwan 2023 Builtin gems by buried level 埋藏深度

    • Surface 地表 • Crust 地殼 • Mantle 地函 • Core 地核
  11. Ruby Conf Taiwan 2023 Surface 地表 • Too famous to

    be in this talk. 太有名了,就不講了。 • irb • rake • rbs • minitest
  12. Ruby Conf Taiwan 2023 Crust 地殼 A lot of people

    are using them. 
 滿多 人 在 用 的。 • Base64 • Set • OpenStruct • Secure Random
  13. Ruby Conf Taiwan 2023 base64 • Convert to & from

    base64 encoding.
 64進位編碼轉換器。 • Maintainer: Yusuke Endoh (@mametter). World No.1 IOCCC player.
  14. Ruby Conf Taiwan 2023 base64 • base64 encoding is not

    encryption, more like binary or hexadecimal .
 base64 不是加密,比較像是 二 進位或 十 六進 位。 • Don't use it for encryption / hashing !
 不要 用 它來加密或是計算雜湊!

  15. Ruby Conf Taiwan 2023 base64 • encode64: output splitted with

    newline if too long, have an ending newline
 編碼的輸出會 自 動換 行 。結尾也有換 行 。 • decode64, ignore any none base64 chars & newline.
 會忽略輸入中的不合格字元和換 行 。 require 'base64' # => true binary = "\x0a\x1b\x2c\x3d\x4e\x5f" # => "\n" + "\e,=N_" b64 = Base64.encode64(binary) # => "ChssPU5f\n" Base64.decode64(b64)==binary # => true
  16. Ruby Conf Taiwan 2023 base64 • Very dense implementation.
 實作超級簡潔。

    • Likely because it's Mr. Endo?
 大 概因為是 Endo 寫的? def encode64(bin) [bin].pack("m") end def decode64(str) str.unpack1("m") end
  17. Ruby Conf Taiwan 2023 base64 • strict_encode64, output without any

    newline.
 輸出不會有任何換 行 。 • strict_decode64, raise error when there's any non base64 chars
 當有任何不合格字元時,會 raise error。 Base64.encode64("a"*50) # => "YWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYW FhYWFhYWFhYWFhYWFhYWFhYWFh\n" + "YWFhYWE=\n" Base64.strict_encode64("a"*50) # => "YWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYW FhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWE=" Base64.strict_decode64("aaaa\n") # => <internal:pack>:29:in `unpack1': invalid base64 (ArgumentError)
  18. Ruby Conf Taiwan 2023 base64 • urlsafe_encode64, same as strict,

    but use - instead of +, _ instead of / to avoid url encoding issue
 和strict 一 樣,但是 用 - 取代 +, 用 _ 取代 / 來避免 URL 編碼問題。 • urlsafe_encode64, decode data encoded by urlsafe_encode64
 用 來解上 面 的輸出。 plus_slash = "+/+/" # => "+/+/" b64_plus_slash = Base64.decode64(plus_slash) # => "\xFB\xFF\xBF" Base64.encode64(b64_plus_slash) # => "+/+/\n" Base64.urlsafe_encode64(b64_plus_sl ash) # => "-_-_"
  19. Ruby Conf Taiwan 2023 Set • A data stucture that

    contains only uniq values.
 只包含獨特值的資料結構。 • Useful when doing interview questions.
 面 試的時候很有 用 。 • Maintainer: Akinori MUSHA (@knu) •
  20. Ruby Conf Taiwan 2023 Set • Set#add to add new

    value.
 加入新的值 • Set#delete to delete value.
 刪除 一 個值 • Set#include? to check if values inside
 檢查有沒有某個值 set = Set.new # => #<Set: {}> set.add("rubyconf") # => #<Set: {"rubyconf"}> set.add("tw") # => #<Set: {"rubyconf", "tw"}> set.include?("tw") # => true set.delete("tw") # => #<Set: {"rubyconf"}>
  21. Ruby Conf Taiwan 2023 Set • Actually implemented with Hash.


    實際上是 用 Hash 實作的。 • store ture as the value.
 Hash 存的值是 true。 def initialize(enum = nil, &block) @hash ||= Hash.new(false) ... end def add(o) @hash[o] = true self end def include?(o) @hash[o] end
  22. Ruby Conf Taiwan 2023 Set • Set.add? returns self if

    add successfully.
 可以邊加值邊檢查裡 面 現在是不是已經有 了。 • set = Set.new # => #<Set: {}> set.add?("tw") # => #<Set: {"tw"}> set.add?("tw") # => nil
  23. Ruby Conf Taiwan 2023 Set • Set#intersection, & : fi

    nd intersection.
 找交集。 • Set#union, | : fi nd union.
 找聯集。 • Set#di ff erence, - : fi nd di ff erence.
 找差集。 japan = Set.new(%w{japan rubykaigi ruby}) # => #<Set: {"japan", "rubykaigi", "ruby"}> tw = Set.new(%w{tw rubyconfg ruby}) # => #<Set: {"tw", "rubyconfg", "ruby"}> japan & tw # => #<Set: {"ruby"}> japan | tw # => #<Set: {"japan", "rubykaigi", "ruby", "tw", "rubyconfg"}> japan - tw # => #<Set: {"japan", "rubykaigi"}>
  24. Ruby Conf Taiwan 2023 OpenStruct • A Struct with dynamic

    member, allow using dot to access member. 
 有動態元素的 struct,可以 用 "." 來存取。 • Maintainer: Marc-André Lafortune(@malafortune)
  25. Ruby Conf Taiwan 2023 OpenStruct • Allow direct access with

    dot .
 可以 用 "." 來存取。 • Can be accessed with [] as well.
 也可以 用 [] 來存取。 • Don't work if the key have weird stu ff .
 不過如果 key 太奇怪就會壞掉。 require 'ostruct' # => true person = OpenStruct.new # => #<OpenStruct> person.name = "John Smith" # => "John Smith" person.name # => "John Smith" person.address # => nil person[:name] # => "John Smith"
  26. Ruby Conf Taiwan 2023 secure random • Generate random number

    using CPRNG(https://en.wikipedia.org/wiki/ Cryptographically_secure_pseudorandom_number_generator)
 產 生 密碼學安全的亂數。 • Maintainer: Tanaka Akira (@tanaka_akr)
  27. Ruby Conf Taiwan 2023 Secure Random vs Random • Random#rand

    : • Use Mersenne Twister, need a seed.
 用 Mersenne Twister,需要 seed。 • Can be predicted after 624 calls.
 觀察輸出 624 次後就可以預測下 一 個值。 • Secure Random • Use /dev/urandom, Win32 or openssl
 使 用 /dev/urandom, Win32 or openssl • Hard to predict next output
 很難預測下 一 個值。
  28. Ruby Conf Taiwan 2023 Secure random • Provide some wrapper

    around the generated random number
 亂數的輸出有 一 些 方 便使 用 的格式。 • rand to return a value between 0 and 1
 回傳 0 到 1 之間的值。 • bytes to return some bytes
 回傳 一 些 byte。 • uuid, alphanumeric, base64. require 'securerandom' # => true SecureRandom.rand # => 0.46760427030684526 SecureRandom.bytes(8) # => "K+ \xE1\xA2Q\xCFm\xBD" SecureRandom.uuid # => "73f0a178-3745-48eb-8a30-0f7364760b 47" SecureRandom.alphanumeric # => "IRCQihGOALKHhuf7" SecureRandom.base64 # => "cnBxZuU93ZqbRqolOYNmxA=="
  29. Ruby Conf Taiwan 2023 Mantle 地函 Useful in some situation.

    less people know about them.
 有的時候有 用 ,比較少 人 知道。 • tsort • FileUtils • IPAddr • abbrev • un
  30. Ruby Conf Taiwan 2023 tsort • Topological sort for graph.


    用 來找 graph 裡 面 的拓墣排序。 • Topological sort is the order of nodes by it's dependency.
 拓墣排序是節點 用 相依性排列後的順序。 • Maintainer: Akira Tanaka (@tanaka_akr)
  31. Ruby Conf Taiwan 2023 tsort • It's a mixin module,

    require your class to provide 2 methods
 是 一 個 mixin module。需要 自己 實作兩個 method。 • tsort_each_node to provoide a list of nodes.
 提供所有的 node • tsort_each_child to provide a list of children for a speci fi c node.
 提供某 一 個 node 的所有 child。 • Call tsort to get reversed topological sort order.
 回傳反轉過的拓墣排序。 require 'tsort' # => true class Hash include TSort alias tsort_each_node each_key def tsort_each_child(node, &block) fetch(node).each(&block) end end # => :tsort_each_child {1=>[2, 3], 2=>[3], 3=>[], 4=>[]}.tsort # => [3, 2, 1, 4]
  32. Ruby Conf Taiwan 2023 tsort • By name, it's doing

    topological sort. But actually it's running a Strongly connected components algorithm, Tarjan's strongly connected components algorithm.
 看起來好像是跑 topological sort 。但實際上是跑 Tarjan's 演算法來找 Strongly connected components 。 • There's a Bug section about naming in README.
 說明裡有 一 個 Bug 段落來講命名。 • Tarjan's algorithm also outputs a
 reversed topological sort
 剛好會輸出反轉過的拓墣排序
  33. Ruby Conf Taiwan 2023 tsort • Call strongly_connected_components to get

    Strongly connected components .
 回傳 Strongly connected components。 require 'tsort' # => true class Hash include TSort alias tsort_each_node each_key def tsort_each_child(node, &block) fetch(node).each(&block) end end # => :tsort_each_child {1=>[2], 2=>[3, 4], 3=>[2], 4=>[]}.strongly_connected_component s # => [[4], [2, 3], [1]]
  34. Ruby Conf Taiwan 2023 Fileutils • Handle common fi le

    operations across platforms.
 可以跨平台處理檔案。 • Maintainer: Minero Aoki (@mineroaoki).
  35. Ruby Conf Taiwan 2023 Fileutils • FileUitls.rm_rf to delete folder

    and all it's contents.
 刪除 目 錄和之下的所有檔案。 • cp_r to copy folder and all it's contents.
 複製 目 錄和之下的所有檔案。 • mkdir_p to create folder and all it's parent if not exists.
 創造 目 錄,包含所有的 母目 錄。 • touch to update modify time
 更新修改時間。 require 'fileutils' # => true FileUtils.mkdir_p("test/ file_utils") # => ["test/ file_utils"] FileUtils.touch("test/ file_utils/.keep") # => ["test/ file_utils/.keep"] FileUtils.cp_r("test/file_utils", "test/copy") # => nil FileUtils.rm_rf("test") # => ["test"]
  36. Ruby Conf Taiwan 2023 ipaddr • Operations on IP address

    .
 操作 IP 位置。 • Maintainers: Akinori MUSHA (@knu) & Hajimu UMEMOTO (@h_ume)
  37. Ruby Conf Taiwan 2023 ipaddr • & to fi nd

    bitwise AND, NOT intersection
 對位元作AND,不是交集。 • | to fi nd bitwise OR, NOT union
 對位元作AND,不是聯集。 • include? to check if IP is in a CIDR
 檢查IP是不是在區塊內。 require 'ipaddr' # => true addr1 = IPAddr.new("10.1.10.1/24") # => #<IPAddr: IPv4:10.1.10.0/255.255.255.0> addr2 = IPAddr.new("10.1.20.1/24") # => #<IPAddr: IPv4:10.1.20.0/255.255.255.0> addr1 | addr2 # => #<IPAddr: IPv4:10.1.30.0/255.255.255.0> addr1 & addr2 # => #<IPAddr: IPv4:10.1.0.0/255.255.255.0> addr1.include? (IPAddr.new("10.1.10.20")) # => true
  38. Ruby Conf Taiwan 2023 ipaddr • private? to check if

    it's a private IP.
 檢查是否是私有網路IP • loopback? to check if it's a loopback IP.
 檢查是否是環回 IP • to_range to cast it to a range for iteration.
 可以轉換成 range。 ip172 = IPAddr.new("172.25.3.4") # => #<IPAddr: IPv4:172.25.3.4/255.255.255.255> ip172.private? # => true local = IPAddr.new("127.0.0.4") # => #<IPAddr: IPv4:127.0.0.4/255.255.255.255> local.loopback? # => true block192 = IPAddr.new("192.168.3.32/28") # => #<IPAddr: IPv4:192.168.3.32/255.255.255.240> block192.to_range # => #<IPAddr: IPv4:192.168.3.32/255.255.255.255> .. #<IPAddr: IPv4:192.168.3.47/255.255.255.255> block192.to_range.count # => 16
  39. Ruby Conf Taiwan 2023 abbrev • Find all the possible

    uniq abbreviation for a set of string.
 幫 一 組字串找出所有可能的縮寫。 • Useful for CLI arguments, for example ./my_cmd u can be expanded into ./my_cmd update using abbrev.
 處理命令列參數時很好 用 ,./my_cmd update 可以縮寫成 ./my_cmd u。 • Maintainer: Akinori MUSHA (@knu) •
  40. Ruby Conf Taiwan 2023 abbrev • .abbrev take a array

    of stings.
 輸入是 一 個字串陣列。 • returns a Hash as lookup table.
 回傳 一 個Hash 查找表。 • No ambiguous pre fi x in the lookup table.
 表裡 面 沒有會對到不同字串的 pre fi x Abbrev.abbrev(%w{ install update upgrade }) # => {"install"=>"install", "instal"=>"install", "insta"=>"install", "inst"=>"install", "ins"=>"install", "in"=>"install", "i"=>"install", "update"=>"update", "updat"=>"update", "upda"=>"update", "upd"=>"update", "upgrade"=>"upgrade", "upgrad"=>"upgrade", "upgra"=>"upgrade", "upgr"=>"upgrade", "upg"=>"upgrade"}
  41. Ruby Conf Taiwan 2023 un • Useful to do things

    as cli one liner. 
 提供 一 些命令列的指令。 • Useful in Make fi le for cross platform。
 寫跨平台 Make fi le 的時候很好 用 。 • When combined with the require -r fl ag, looks like -run
 當和 require 用 的 -r 參數放在 一 起的時候。看起來像 -run。 • Maintainer: WATANABE Hirofumi
  42. Ruby Conf Taiwan 2023 un • ruby -run -e cp

    -- [OPTION] SOURCE DEST to copy fi les
 複製檔案 • ruby -run -e mv -- [OPTION] SOURCE DEST to move fi le/folder
 移動檔案 • ruby -run -e httpd -- [OPTION] [DocumentRoot] start a http server at DocumentRoot, but need to install webrick after Ruby 3.0.0. Useful to transfer fi le in local network.
 開 一 個 http server。不過在 Ruby 3.0.0 之後需要額外裝 webrick。 用 來在區網傳檔案很好 用 。
  43. Ruby Conf Taiwan 2023 Core 地核 Most people don't know

    Ruby have this as builtin.
 大 部分 人 不知道 Ruby 有內建 Or don't know we can use it directly.
 或是不知道可以直接拿來 用 。 • prime • Forwardable • Delegate • Singleton • did_you_mean
  44. Ruby Conf Taiwan 2023 Prime • Bundled gem • Generate

    prime number, checks prime number, prime factorization.
 產 生 質數,檢查質數,質因數分解。 • Maintainer: Marc-Andre Lafortune(@malafortune)
  45. Ruby Conf Taiwan 2023 Prime • Use Miller–Rabin primality test

    to check prime, 
 用 Miller-Rabin 來檢查是否是質數。 • Become very slow after reaching limit of Miller–Rabin. 3_317_044_064_679_887_385_961_981
 超過 Miller-Rabin 的極限後就會變慢。 • 
 require 'prime' # => true Prime.prime?(7) # => true 8.prime? # => false
  46. Ruby Conf Taiwan 2023 Prime • Use Sieve of Eratosthenes

    to generate Primes 
 用 埃拉托斯特尼篩法 來產 生 質數。 Prime.take(4) # => [2, 3, 5, 7] Prime.each(7).to_a # => [2, 3, 5, 7]
  47. Ruby Conf Taiwan 2023 Prime • Use Wheel factorization for

    prime division.
 用車 輪分解來產 生 質因數分解 用 的因數。
 Prime.prime_division(8959) # => [[17, 2], [31, 1]]
  48. Ruby Conf Taiwan 2023 Forwardable • Forward speci fi c

    method calls to another object.
 轉發特定 method 給其他物件。 • Maintainer: Keiju Ishitsuka, Ruby' god father. Who coined the name Ruby with Matz
 Ruby 的教 父 ,和 Matz 一 起討論了 Ruby 這個名字。
  49. Ruby Conf Taiwan 2023 Forwardable • def_delegator , delegate to

    another object with di ff erent name
 轉發呼叫給另 一 個物件的特定 method。
 class RecordCollection attr_accessor :records extend Forwardable def_delegator :@records, : [], :record_number end # => :record_number r = RecordCollection.new # => #<RecordCollection:0x00000001050618 40> r.records = [4,5,6] # => [4, 5, 6] r.record_number(0) # => 4
  50. Ruby Conf Taiwan 2023 Forwardable • def_delegators, delegate methods to

    another object.
 轉發呼叫給其他物件。
 class RecordCollection def_delegators :@records, :size, :<<, :map end # => [:size, :<<, :map] r = RecordCollection.new # => #<RecordCollection:0x0000000104eed3 10> r.records = [1,2,3] # => [1, 2, 3] r.size # => 3 r << 4 # => [1, 2, 3, 4] r.map { |x| x * 2 } # => [2, 4, 6, 8]
  51. Ruby Conf Taiwan 2023 Delegate • Delegate all unde fi

    ned methods.
 轉發所有未定義的 method。 • Maintainer: Yukihiro Matsumoto (@yukihiro_matz) , Ruby's Father.
  52. Ruby Conf Taiwan 2023 Delegate • DelegateClass: create a super

    class that wraps the Delegated class.
 創造 一 個新的 class ,把轉發的 目 標包住。 • Main interface
 主要的 用 法。 class TimeWithAgo < DelegateClass(Time) def initialize(arg) @t = Time.new(arg) super(@t) end def years_ago = Time.now.year - year end # => :years_ago t = TimeWithAgo.new("1993-02-24 UTC") # => 1993-02-24 00:00:00 UTC t.year # => 1993 t.years_ago # => 30 ~
  53. Ruby Conf Taiwan 2023 Delegate • Simple delegator , forward

    all unde fi ned methods to the the target object.
 轉發所有未定義的 method 給 目 標物件。 class TimeDecorator < SimpleDelegator def years_ago = Time.now.year - year end # => :years_ago t = TimeDecorator.new(Time.new("1993-02 -24 UTC")) # => 1993-02-24 00:00:00 UTC t.year # => 1993 t.years_ago # => 30
  54. Ruby Conf Taiwan 2023 Delegate vs inheritance • Delegate only

    delegate public methods, protecting private methods from send calls.
 Delegate 只會轉發給 public method,可以 用 來讓 send 呼叫不到 private method。 • "Has a" vs "Is a"
 有 一 個 vs 是 一 個。 • Delegate can be recon fi gured during runtime easily.
 Delegate 可以在執 行 期動態修改 目 標。
  55. Ruby Conf Taiwan 2023 Singleton • Provide Singleton pattern. 提供單例模式

    支 援。 • Maintainer: Yukihiro Matsumoto (@yukihiro_matz) , Ruby's Father.
  56. Ruby Conf Taiwan 2023 Singleton • #instance returns the singleton

    instance.
 回傳單例實體。 • .new is marked private.
 .new 變成 private • Easier to understand than class instance variable @@var.
 比起 用 class instance varible 容易理解。 • Thread safe
 執 行 序安全。 class BDFL include Singleton def name = "Matz" end # => :name BDFL.instance.name # => "Matz" BDFL.new # => (...:in `<main>': private method `new' called for class BDFL (NoMethodError)
  57. Ruby Conf Taiwan 2023 Did you Mean • Help user

    fi nd typos in their code.
 幫助使 用 者尋找錯字。 • Maintainer: Yuki Nishijima (@yuki24)
  58. Ruby Conf Taiwan 2023 Did you Mean • Generates suggestion

    in error messages.
 在錯誤訊息中產 生 建議。 • Works for methods & constants etc.
 對 method 和 constant 名都有效。 3.3.0-preview3 :001 > evel(1) (irb):1:in `<main>': undefined method `evel' for main (NoMethodError) Did you mean? eval 3.3.0-preview3 :003 > Irb (irb):3:in `<main>': uninitialized constant Irb (NameError) Did you mean? IRB
  59. Ruby Conf Taiwan 2023 Did you Mean • You can

    call it's word comparing methods directly.
 可以直接呼叫他的字串比對 method。 • Levenshtein distance, also known as edit distance.
 萊 文 斯坦距離 , 又 叫編輯距離。 • Jaro–Winkler distance, normalized similarity.
 Jaro–Winkler 距離,正規化的相似度。 DidYouMean::Levenshtein.distance("r ubyconf tw", "rubykaigi") # => 7 DidYouMean::Jaro.distance("rubyconf tw", "rubykaigi") # => 0.6026936026936026 DidYouMean::JaroWinkler.distance("r ubyconf tw", "rubykaigi") # => 0.6026936026936026
  60. Ruby Conf Taiwan 2023 Customize Did you Mean to find

    path error class EnoentChecker def initialize(exception) @rel_path = exception.message.split("-")[1].strip @path = File.expand_path(@rel_path, File.dirname(__FILE__)) end def dictionary = Dir.foreach(File.dirname(@path)).to_a def corrections = DidYouMean::SpellChecker.new(dictionary:).correct(@rel_path).uniq end # => :corrections DidYouMean.correct_error Errno::ENOENT, EnoentChecker # => Errno::ENOENT File.read("hallo.txt") # => didyoumean.rb:14:in `read': No such file or directory @ rb_sysopen - hallo.txt (Errno::ENOENT) Did you mean? hello.txt
  61. Ruby Conf Taiwan 2023 Takeaway 結論 • Ruby is battery-included.

    Tons of good stu ff s in standard libraries.
 Ruby 內建很多功能。標準函式庫裡有很多好東 西 。 • There's an ongoing e ff ort of promoting standard libraries to bundled gems.
 正在努 力 把標準函式庫升級成 bundled gems。 • https://stdgems.org/ have a list of standard libraries.
 有標準函式庫的清單。 • Next time you can check the Standard library before searching for 3rd party gems.
 下 一 次在 用 第三 方 Gem 之前,可以先看看標準函式庫有沒有。 •