Ruby gem 開発！中国語（簡体字・繁体字）と日本語を判別するgemを作ってみた（前編）

# Ruby gem 開発！中国語と日本語を判別する gem を作ってみた（前編）

こんにちは、私の名前は九兵衛です。
今回、真面目に Ruby gem を開発することになり、その過程で学んだことを皆さんと共有したいと思います。
私が作ろうとしているのは、[Unihan Database](https://unicode.org/charts/unihan.html) で公開されている `Unihan_Variants.txt` に基づいて中国語（簡体字・繁体字）と日本語を判別する gem です。

## gem って何？なぜ作るの？

最初に、「gem」って何なのか、ぶっちゃけよくわかっていなかったんです 😅
調べてみると、gem は Ruby のライブラリやアプリケーションをパッケージ化したものだと分かりました(それはそう)
つまり、自分で作った便利な機能を、他の人も簡単に使えるようにするためのもの

私がこの gem を作ろうと思ったのは、多言語対応をするのに日本語と中国語を判別する必要があったからです。
既存の gem を探してみたんですが、ピッタリなものが見つからず...
会社のエンジニアの @kaibadash@github さんに一緒に作ろうと言われたのでやってみることにしました。

## プロジェクトの構造：思った以上に複雑！

gem の基本構造を作るのが、思った以上に複雑でした。どんなファイルが必要なのか、どういうディレクトリ構造にすべきか、全然分からない 😭

試行錯誤の末、以下のような構造にたどり着きました：

```bash
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 の「顔」となる重要なファイルだと知り、緊張しながら書きました：

```ruby
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`の部分で思わぬ壁にぶつかりました。

```ruby
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 つのことをしています：

1. `git ls-files`コマンドを使って、Git で管理されているファイルを取得し、テストや spec 関連のファイルを除外しています。
2. `Dir['data/*']`で、`data`ディレクトリ内のすべてのファイルを追加しています。

特に 2 番目の部分、`+ Dir['data/*']`は、私の gem で使用する`Unihan_Variants.txt`ファイルを含めるために追加したものです。これがないと、gem をインストールしたときにデータファイルが含まれず、gem が正常に動作しない...なんてことに！

## 最初のコード：まずは骨組みから

いよいよコードを書き始めます。`lib/unihan_lang.rb`に以下のコードを書きました：

```ruby
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 を使って依存関係を管理することにしました：

```ruby
source 'https://rubygems.org'

gemspec

gem 'rspec', '~> 3.0'
```

そして、以下のコマンドを実行：

```bash
bundle install
```

これにより、開発に必要な gem がすべてインストールされました。

## まとめ：小さな一歩、大きな学び

正直、思っていたよりも複雑で、わからないことだらけでした。でも、一つ一つ調べながら進めていくのは、なんだかワクワクする体験でしたし、Ruby コミュニティの豊富な情報源に助けられました。

次回は、実際に Unihan_Variants.txt ファイルを読み込んで、文字の判別ロジックを実装していきます。果たしてうまくいくでしょうか...？ 続きをお楽しみに！