Ruby gem 開発!中国語と日本語を判別する gem を作ってみた(前編)
こんにちは、私の名前は九兵衛です。
今回、真面目に Ruby gem を開発することになり、その過程で学んだことを皆さんと共有したいと思います。
私が作ろうとしているのは、Unihan Database で公開されている Unihan_Variants.txt
に基づいて中国語(簡体字・繁体字)と日本語を判別する gem です。
gem って何?なぜ作るの?
最初に、「gem」って何なのか、ぶっちゃけよくわかっていなかったんです 😅
調べてみると、gem は Ruby のライブラリやアプリケーションをパッケージ化したものだと分かりました(それはそう)
つまり、自分で作った便利な機能を、他の人も簡単に使えるようにするためのもの
私がこの gem を作ろうと思ったのは、多言語対応をするのに日本語と中国語を判別する必要があったからです。
既存の gem を探してみたんですが、ピッタリなものが見つからず...
会社のエンジニアの @kaibadash@github さんに一緒に作ろうと言われたのでやってみることにしました。
プロジェクトの構造:思った以上に複雑!
gem の基本構造を作るのが、思った以上に複雑でした。どんなファイルが必要なのか、どういうディレクトリ構造にすべきか、全然分からない 😭
試行錯誤の末、以下のような構造にたどり着きました:
mkdir -p lib/unihan_lang
mkdir spec
touch lib/unihan_lang.rb
touch lib/unihan_lang/version.rb
touch unihan_lang.gemspec
touch Rakefile
touch README.md
ここで学んだのは、gem には一定の規約があるということ。lib
ディレクトリにメインのコードを、spec
ディレクトリにテストを置く(ここまではなんとなくわかる)
gemspec ファイル:gem の「顔」を作る
次に直面したのが、gemspec
ファイルの作成です。これが gem の「顔」となる重要なファイルだと知り、緊張しながら書きました:
require_relative 'lib/unihan_lang/version'
Gem::Specification.new do |spec|
spec.name = "unihan_lang"
spec.version = UnihanLang::VERSION
spec.authors = ["kyubey"]
spec.email = ["kyubey_no@mail.adress"]
spec.summary = %q{Language detection for Chinese and Japanese characters}
spec.description = %q{A gem to detect and differentiate between Traditional Chinese, Simplified Chinese, and Japanese characters based on Unihan data.}
spec.homepage = "https://github.com/kyubey1228/unihan_lang"
spec.license = "MIT"
spec.required_ruby_version = Gem::Requirement.new(">= 2.5.0")
spec.files = Dir.chdir(File.expand_path('..', __FILE__)) do
`git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
end
spec.bindir = "exe"
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
spec.require_paths = ["lib"]
spec.add_development_dependency "bundler", "~> 2.0"
spec.add_development_dependency "rake", "~> 13.0"
spec.add_development_dependency "rspec", "~> 3.0"
end
ここで学んだのは、gem の名前、バージョン、作者情報、依存関係など、gem に関する重要な情報をすべてここで定義するということ。特にspec.add_development_dependency
の部分は、開発時にのみ必要な依存関係を指定するものだと知り、「なるほど!」と思いました。
gem に含めるファイルの指定:思わぬ落とし穴
gemspec ファイルを書いているとき、spec.files
の部分で思わぬ壁にぶつかりました。
spec.files = Dir.chdir(File.expand_path('..', __FILE__)) do
`git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
end + Dir['data/*']
調べてみると、これは gem に含めるファイルを指定する重要な部分で
ここでは主に 2 つのことをしています:
-
git ls-files
コマンドを使って、Git で管理されているファイルを取得し、テストや spec 関連のファイルを除外しています。 -
Dir['data/*']
で、data
ディレクトリ内のすべてのファイルを追加しています。
特に 2 番目の部分、+ Dir['data/*']
は、私の gem で使用するUnihan_Variants.txt
ファイルを含めるために追加したものです。これがないと、gem をインストールしたときにデータファイルが含まれず、gem が正常に動作しない...なんてことに!
最初のコード:まずは骨組みから
いよいよコードを書き始めます。lib/unihan_lang.rb
に以下のコードを書きました:
require_relative "unihan_lang/version"
module UnihanLang
class Error < StandardError; end
class Unihan
def initialize
@zh_tw = Set.new
@zh_cn = Set.new
@ja = Set.new
end
def zh_tw?(word)
# 繁体字中国語かどうかを判定するロジック(まだ未実装)
end
def zh_cn?(word)
# 簡体字中国語かどうかを判定するロジック(まだ未実装)
end
def ja?(word)
# 日本語かどうかを判定するロジック(まだ未実装)
end
end
end
ここで学んだのは、まずは基本的な構造を作ることの重要性です。具体的なロジックはまだ書いていませんが、どんなメソッドが必要かを考えることで、gem の全体像が見えてきました。
Bundler の活用:依存関係を管理する
最後に、Gemfile
を作成し、Bundler を使って依存関係を管理することにしました:
source 'https://rubygems.org'
gemspec
gem 'rspec', '~> 3.0'
そして、以下のコマンドを実行:
bundle install
これにより、開発に必要な gem がすべてインストールされました。
まとめ:小さな一歩、大きな学び
正直、思っていたよりも複雑で、わからないことだらけでした。でも、一つ一つ調べながら進めていくのは、なんだかワクワクする体験でしたし、Ruby コミュニティの豊富な情報源に助けられました。
次回は、実際に Unihan_Variants.txt ファイルを読み込んで、文字の判別ロジックを実装していきます。果たしてうまくいくでしょうか...? 続きをお楽しみに!