1
0

More than 3 years have passed since last update.

Ruby スクリプトで「もしかしてこれ?」と言ってみたい

Posted at

はじめに

Ruby で,メソッド名を少しだけ間違うと,「もしかしてこれ?」と言ってくれる。
たとえば円周率を表示しようとして

puts Math::PI

のつもりで

pots Math::PI

とやったら

NoMethodError (undefined method `pots' for main:Object)
Did you mean?  puts

のように表示される。
意訳すれば

pots なんつーメソッドはねーよ
もしかしてこれ? puts

となる。
存在しないメソッドを呼び出そうとしたときに,存在するメソッドの中からよく似た名前のものを探してきて,候補として表示してくれるンである。

こういう機能を自作のスクリプトにも組み込めないか?
つまり,ユーザーに何か入力させるのだが,受け付ける文字列があらかじめ限られていて,そこから外れているときに,「もしかしてこれ?」とやるわけだ。

お題

こんなプログラムを考える(実用性は考えていない)。
Ruby 関係のよく見るウェブサイトをブラウザーで開くだけ。
サイトにはあらかじめ略称を決めておき,それをコマンドライン引数として与える。
ターミナルで,たとえば

ruby open_site.rb rubima

と打てば Rubyist Magazine のページが開く。
また,

ruby open_site.rb rurema

と打てば Ruby リファレンスマニュアル のページが開く。「rurema」は Ruby リファレンスマニュアルの(たぶん公式の)英字略称だ。

ウェブサイトをブラウザーで開くには,launchy という gem を使う。

こんなコードになる:

open_site.rb
require "launchy"

case ARGV.first
when "rubima"
  Launchy.open "https://magazine.rubyist.net/"
when "rurema"
  Launchy.open "https://docs.ruby-lang.org/ja/"
else
  puts "Unknown"
end

ARGV はコマンドライン引数を収めた文字列配列だ。

ARGV.first がどれにも当てはまらなかった場合,現状では「Unknown」とだけ表示されるが,さらに「もしかしてこれ?」を表示させたい。

実装

Ruby の「Did you mean?」機能は,did_you_mean という gem で実現されている。
この gem は Ruby にバンドルされている。

そして,ありがたいことに,この記事で意図している機能を実現する手助けをしてくれるのだ。

とても簡単なので,修正後のコードをまるごと提示しよう:

open_site.rb
require "launchy"

names = %w[rubima rurema]
checker = DidYouMean::SpellChecker.new(dictionary: names)

name = ARGV.first
case name
when "rubima"
  Launchy.open "https://magazine.rubyist.net/"
when "rurema"
  Launchy.open "https://docs.ruby-lang.org/ja/"
else
  puts "Unknown"

  candidates = checker.correct(name)
  unless candidates.empty?
    puts "Did you mean?"
    candidates.each do |candidate|
      puts "  #{candidate}"
    end
  end
end

簡単に説明する。
まず受け付ける文字列の配列を元に DidYouMean::SpellChecker オブジェクトを作っておく。
そして,そいつの correct メソッドを呼び出す。すると候補の文字列の配列が返る。
近い文字列が存在しないときは空配列が返る。
ただそれだけ。

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0