仕事で使うためにgemを作ったったという話です。
自分が担当している製品は、情報を収集して、それを集計して…みたいなことをよくやるのですが、その時の課題が『表記揺れ』だったりします。よくありますよねー。ASUSのことをどう読むのか?みたいな問題。いくら公式が『エイスース』と言っても、『エーサス』『アーサス』『アサス』などと書かれることはあるわけです。情報を収集するときに『エーサス』と書かれているものは『エイスース』として認識したい!ということですが、そのためにはニックネームを管理する仕組みが必要です。
そこで、ニックネームを管理するためのgem imyou(異名)を作りました。
gemの名前はニックネームを被りにくい日本語にしたものです。Rails 4と5に対応しています。
使い方
使い方はREADMEに書いていますが、一応説明を。
インストール
Gemfileに書いてbundle install
してください。
gem 'imyou'
マイグレーション
imyou用のテーブルを生成する必要があります。generatorを定義してあるので、それを使ってmigration用のファイルを生成して、マイグレーションしてください。
$ rails generate imyou:migration $ rails db:migrate
Userモデル
Userモデルには、nameカラムがあるとします。
class User < ApplicationRecord has_imyou end
ニックネーム検索するときの対象として、nameカラムも含めたい場合は以下のように。
class User < ApplicationRecord has_imyou :name end
実際に使う
登録系
登録は、add_nickname
メソッドと、nicknames=
メソッドを定義してあります。
@user = User.create(name: '孫悟空') # ニックネームを登録 @user.add_nickname('カカロット') # ニックネームを取得 @user.nicknames # => ['カカロット'] # ニックネームを配列で登録 @user.nicknames = %w(カカロット 孫くん ゴクウ) @user.nicknames # => ['カカロット', '孫くん', 'ゴクウ']
削除系
削除は、remove_nickname
メソッドと、remove_all_nicknames
メソッドを定義してあります。
@user = User.create(name: '孫悟空') @user.nicknames = %w(カカロット 孫くん ゴクウ) # ニックネームを削除 @user.remove_nickname('孫くん') @user.nicknames # => ['カカロット', 'ゴクウ'] # ニックネームを全て削除 @user.remove_all_nicknames @user.nicknames # => []
検索系
検索系は、完全一致検索と、部分一致検索を定義してあります。本名(?)を検索対象にするためにオプションwith_name_column
があり、デフォルトでtrue
になっています。
もしニックネームのみを検索対象にしたい場合は、false
を設定します。
@user = User.create(name: '孫悟空') @user.add_nickname('カカロット') # 名前とニックネームで完全一致検索 User.match_by_nickname('孫悟空').exists? # => true User.match_by_nickname('カカロット').exists? # => true User.match_by_nickname('悟空').exists? # => 完全一致していないのでfalse # 名前とニックネームで部分一致検索 User.partial_match_by_nickname('悟空').exists? # => 部分一致しているのでtrue User.partial_match_by_nickname('カカ').exists? # => 部分一致しているのでtrue # ニックネームのみを対象にして検索 # 完全一致検索 User.match_by_nickname('孫悟空', with_name_column: false).exists? # => ニックネームはカカロットのためfalse User.match_by_nickname('カカロット', with_name_column: false).exists? # => true # 部分一致検索 User.partial_match_by_nickname('悟空', with_name_column: false).exists? # => ニックネームに部分一致していないのでfalse User.partial_match_by_nickname('カカ', with_name_column: false).exists? # => 部分一致しているのでtrue
参照系
with_nicknames
スコープを定義しているので、これを呼ぶとeager_load
が実行されるのでN+1は起きません。
@user = User.with_nicknames.first
以上です。
こんな機能があったらいいなぁとか、IssueなりPRなりお願いします!