nippo の Gemfile (2017-12-02版)

Rails で使っている gem の知見が欲しいという話をいただいたので、いま開発している nippo という Web アプリの、2017年12月2日時点で master に commit されている Gemfile の中身を解説する。

定義順序について説明してから、個々の gem について簡単に説明する。

定義順序

まず group 指定の無いもの、次に group 指定付きのものという順で定義している。細かいけど group それぞれも辞書順。複数の group を同時に指定する場合は、それらを繋げたものを順序指定時のキーとしてソートする。こういうルールなので、gem メソッドの引数の :group オプションは利用しない。

意図的に順序を気にして定義しないといけないケースが存在するので、各 group ごとにまず順序を気にしないといけないやつを記述して、後に辞書順のやつを記述するようにしている。しかし上例では default (group 指定無し) の場合しかその使い分けは必要になっていない。

Rails では Bundler.require が利用されるので、Gemfile に定義された順に gem が読み込まれていくのだが、読み込み時に if defined?(Rails) のようなコードが実行される Gem というものが存在するので、そういうものを考慮すると幾つかの Gem は順序を気にして先に読んでおく必要がある…というのが Gemfile で定義順序を気にしなければならない理由の一つである。

activerecord-belongs_to_if

これは ActiveRecord で単一テーブル継承を利用しているときに、継承した子クラスごとに belongs_to の先が異なるようなモデルを定義するような場合に利用しているやつ。具体的には belongs_to に :if というオプションを渡せるようにするやつで、Notification.belongs_to(:like, if: -> { is_a?(LikeNotification) }) のように利用する。

別に STI 用途でなくても、モデルの状態に応じて belongs_to の有無が変わる場合に利用できるはず。5% の確率で限定レア親モデルが取得できるとか。belongs_to になってると eager load できるのが嬉しいというのが、メソッド呼び出しに if 文を付けるだけではなくわざわざ belongs_to を利用できるようにしている理由。

利用シーンとしては、Inbox をつくらないタイプの通知とかタイムラインの実装に利用できる。正直何を言ってるか分からないと思うので、興味のある人は以下の記事を読むことをおすすめする。

ActiveRecordでPolymorphicにPreloadする - Qiita

bcrypt

ActiveModel でパスワードの digest を生成 & 保存する機能である has_seucre_password を利用する場合に内部実装で利用するので必要になるやつ。nippo では Twitter や Google の OAuth を利用してアカウント登録を行うこともできるが、他にメールアドレスとパスワードを利用して登録することもできるので、その機能に使っている。

email_validator

ActiveModel で User.valiadtes :mail_address, email: true のような validation が定義できるようにするやつ。前述した用途で、Valid なメールアドレスのみ DB に保存するために利用している。

execjs

Ruby から JavaScript を実行するためのインターフェースを提供するやつ。インターフェースを提供するだけで、利用するためには JavaScript 実行エンジンとして別の Gem を入れたり Node.js と接続したりする必要がある。nippo ではアプリケーションサーバから送信する HTML は全て React.js を利用して Server-Side Rendering で生成していて、その内部実装で利用している。

gravatar-ultimate

Gravatar という、メールアドレスとアイコン画像を紐付けるためのサービスがあって、メールアドレスを元に画像 URL を生成するための Ruby のライブラリがこれ。執筆時点で現行の Ruby バージョンに対応していない部分があって、具体的には xmlrpc という gem を別途インストールしないとこの gem は動かない。

html-pipeline

Markdown を HTML に変換する仕組みの内部実装に使っている。Markdown あるいは XML を入力として別の XML を出力する、という単位のフィルターをパイプライン状に複数重ねあわせるための機構を提供している。次の記事が参考になる。

Markdownを拡張して独自記法をつくる - Qiita

json_world

Web API のレスポンスに使う JSON を生成するのに使っている。宣言的な記法を利用して、あるクラスを JSON 形式の Object に変換可能にするためのライブラリ。JSON Schema の定義を生成する機能も付いているが、今回は使っていない。

kaminari

ページネーション。合計件数が 0 件のときの処理に一貫性が無いように見えてたまに困る。この点については Issue で議論されている。

mem

メソッドの呼び出し結果を memoize するために使っている。引数は無視して、レシーバのインスタンス変数に Hash でメソッド名をキーにして呼び出し結果を入れておこうという素朴な実装。昔は ActiveSupport::Memoizable というのがあった。現在は memoist というのもある。

mini_racer

前述した execjs のための JavaScript 実行エンジンとして利用している。therubyracer の競合みたいなやつ。

nokogiri

前述した、html-pipeline を利用した Markdown の変換処理に使っている。

omniauth

omniauth-google-oauth2 や omniauth-twitter と合わせて、外部サービスと連携してアカウント登録やログインを行う機能のために利用している。

pry-rails

rails console を pry に変える。デバック用途に使うだけなので正直あまり使っていないけれど、素の irb より便利であることが多い。

puma

アプリケーションサーバ。最近 Unicorn を使うことが減ってしまった。

react_on_rails

React.js で Server-Side Rendering を行うために利用している。執筆時点で最新のバージョンの SSR の機能が壊れているのでバージョンを指定せざるを得なくなった。プロジェクトのフロントエンドの様子に応じて react-rails と使い分けることが多い。

SprocketsやWebpackerを使っていないアプリケーションでreact-railsを使う

redcarpet

Markdown コンパイラ。Markdown エディタをやめて WYSIWYG エディタに変えようとしているので、もしかしたら Markdown 関係のライブラリは今後使わなくなるかもしれない。

rouge

Ruby 製のシンタックスハイライタ。Python 製の pygments の Ruby 版みたいなやつ。スレッドベースの Puma で pygements.rb を利用すると問題が多いので、pygments は選択肢には入らなかった。

sanitize

Markdown 経由での XSS を避けるために使っているやつ。ホワイトリスト形式で許可する要素や属性を指定できる。

sentry-raven

エラー監視。

settingslogic

YAML に設定関係の定数を集約しておくためのやつ。

validate_url

ActiveModel で validates :foo, url: true みたいに書けるようにするやつ。

xmlrpc

前述した gravatar-ultimate のために必要な gem。昔は XMLRPC 自体が Ruby に同梱されていたものの、途中から gem に分離されていて、gravatar-ultimate がその変更に追随していないので明示的に入れざるを得なくなった悲しい gem。

newrelic_rpm

パフォーマンス監視。

factory_bot_rails

テスト用の Fixture。正常系のレコードを生成するためのロジックを集約しておくために利用している。

rspec-rails

テスト用のヘルパーライブラリ。テストケースごとのトランザクションを利用した DB の状態管理、テストファイルのパス名に応じた :type metadata の付与、エラー時のスタックトレースの整形などの目的で利用している。

以上です。