本には ISBN というものが付いていて、 末尾のチェックディジットは仕様を参照すれば 簡単に計算出来そうです。

10 桁のものと新しい 13 桁のものがあったり、 出版者の部分の桁数が違ったりして ちゃんとハイフンを入れるのは面倒そうです。

チェックディジットの方も自分で実装すると バグっていたときに面倒なので、 良さそうな gem がないか探してみました。

最終的にはいくつかの理由から lisbn という gem を使いました。

gem の選択

まず rubygems.org の右上で isbn と検索 するところから始めました。

インストール数の多い順に見ていくと、

  • isbn10
    • インストール数は一番多い
    • 10桁のみ
    • 古い
  • isbn-tools
    • 古い
    • Not Maintained
    • lisbn が後継
  • isbn
    • 画像対応とかいろいろ高機能っぽいけど今回は不要
    • with_dashes というメソッドは桁数決めうちで不適切
  • isbn_validation
    • ActiveRecord の validates
    • ISBN ではない ASIN も扱いたかったので今回は不適当
  • lisbn
    • 比較的新しい
    • 10桁と13桁の両対応
    • ハイフンを入れるために必要な分解処理がある (後は join('-') すれば良いだけ)
    • data/RangeMessage.xml というファイルを持っていて適切にわけてくれる

という感じでした。

lisbn の使用例

データベースに保存するのに統一されていると validates :isbn, uniqueness: true が使えるので、 以下のように ISBN13 に統一する処理を入れました。

それ以外の場合は ASIN と見なしてそのまま返しています。

  def isbn_unify(isbn)
    # Convert JISX0208 alphabet to ASCII.
    isbn = NKF.nkf('-Ww -Z0', isbn).delete("^A-Za-z0-9")

    # Convert to isbn13
    lisbn = Lisbn.new(isbn)
    if lisbn.valid?
      lisbn.isbn13
    else
      isbn
    end
  end

出力する側では parts は常に ISBN13 のものだけのようなので、 ISBN10 に出来るときは 頭の ‘978’ を外して チェックディジットを付け直すようにしました。

- lisbn = Lisbn.new(isbn_or_asin)
- if lisbn.valid?
  - parts = lisbn.parts
  - if parts[0] == '978'
    %p.isbn10 ISBN10: #{parts[1..-2].join('-')}-#{lisbn.isbn10[-1]}
  %p.isbn13 ISBN13: #{lisbn.parts.join('-')}
- else
  %p.asin ASIN: #{isbn_or_asin}
Disqus Comments

Kazuhiro NISHIYAMA

Ruby のコミッターとかやってます。 フルスタックエンジニア(って何?)かもしれません。 About znzに主なアカウントをまとめました。

znz znz


Published