Ruby
Gem
RubyOnRails

gem嫌いでも使っているgem

0. はじめに

私は基本的にgemを使うのは好きではありません。個人で開発されているものであれば、いつメンテナンスが終わるかもわかないし、メンテナンスが終わったときに自分がメンテをし続ける自信もありません。もともとデータベース設計に関してはRailsエンジニアになる前から勉強してきたので、データベース設計が絡むgemに関しては躊躇することが多いです。
そんなgem嫌いな私でもgemを使わずにRails開発することは不可能です。今回は、それなりに使ってきてこれは使えると思ったものを私の経験ベースで紹介したいと思います。
pgやslim-railsなど、postgreSQLやslimを使うならこれがないとダメでしょといったものや、pry, rspec-rails, factory_bot_railsなど定番なものを除いています。
思いついたときに逐次追記していきます。

assets系

sassc-rails

Railsで何も考えずにsassを使うときは、sass-railsだと思うのですが、だんだん重くなってきます。assets:precompileに時間がかかったり、sassを編集した後の開発時のリロードが遅くなったときに手を打ちやすい方法がsassc-railsを使うことです。sass-railsはruby実装ですが、sassc-railsはc実装なので処理が早いです。まれに、sass-railsで問題なかった記述がsassc-railsでエラーとなることがあるので、最近では初期の段階からsassc-railsを導入するようにしています。

フロントエンド連携系

gon

サーバーサイドとフロントエンドの値の受け渡し方法はajaxでとってくるなど、いくつか考えられますが、gonはその方法の一つです。renderした段階で値が決まっている場合は便利かと思います。

draper

例えば、モデルのカラムの値をそのままではなく、少し編集をして表示させたいと言った時などに利用します。ビューの表示のためにモデルにメソッドを追加したくないという場合に重宝します。デコレーターパターンの実装法の一つです。

# 一つのActiveRecordをdecorateする場合
@article = Article.first.decorate
## or
@article = ArticleDecorator.decorate(Article.first)

# collectionオブジェクトの一つ一つをdecorateする場合
@articles = Article.all.decorate

# collectionそのものをdecorateする場合
@articles = ArticlesDecorator.decorate(Article.all)
## collectionそのものをdecorateした場合のDecoratorの実装例
## ビューのみに利用する集計などで利用した経験がありますが、viewのrender時に実行されるのであまり良くないかも。
class ArticlesDecorator < Draper::CollectionDecorator
  # objectでcollectionを参照することができる。
  def total_count
    object.count
  end

  def latest_created_at
    object.order(created_at: :desc).first.created_at
  end
end

データベース系

activerecord-import

RailsでBULK INSERTするにはどうすればいいかなと思ったときに役に立つのがこのgemです。

paper_trail

以前、リレーショナルデータベースでの履歴管理を真剣に考えたことがあるのですが、リレーショナルデータベースにおいて履歴管理は苦手分野の一つで結構苦戦して、結局このgemにたどりつきました。
レコードの履歴管理の定番のgemだと思います。yaml形式やjson形式で差分を表示してくれます。jsonをサポートしているデータベースであれば、json形式で保存できるのは便利です。

carrierwave

画像アップロードとかができます。Rail5.2からはActiveStorageが追加されたので、そちらに移行していくのだろうと思いますが、carrierwaveの功績は大きいかと思います。

通信系

typhoeus

libcurlのラッパーです。インタフェースが比較的わかりやすく、並列実行もできるので良く利用しています。

active_elastic_job

ElasticBeanstalkでworkerを利用した時のActiveJobの具体的な実装の一つです。ElasticBeanstalkには環境枠(environment tier)として、webとworkerがあるのですが、worker単独での利用でもいいですし、webとworkerを連動したいときに利用します。GitHubのREADEMEが詳しいのがありがたいです。

認証系

sorcery

devise(やwarden)に悩まされた人も多いはず。sorceryは、シンプルさを保って実装されており、比較的軽量なgemです。にもかかわらず、ログイン・ログアウト情報や、セッションタイムアウト、ブルートフォースアタック対策など嬉しい機能があります。詳しくはsorceryのwikiをご覧ください。
シンプルさを保つため、複数モデルには対応していないのがちょっと困るかもしれません。

テスト支援系

parallel_tests

テストを並列・平行実行してくれます。たとえばCircleCI2.0では1コンテナあたり2CPUなので2つまで並列可能です。
コマンドの実行の仕方は-nオプションで並列・平行数を指定します。CPUの数より大きい値を指定した場合は、よしなに平行実行されますが、IO待ちなどがない限り、スピードは上がらないかもしれません。

bundle exec parallel_rspec -n 4

rspec-retry

rspecでテストが失敗したとき、リトライしてくれます。リトライ単位はitscenarioです。feature specやsystem specではNetTimeoutやJavascriptの微妙な挙動でランダムで失敗したりします。1回の失敗ごときで失敗するな!もう一度実行して成功したら成功とみなしてもよいというテストケースにはリトライを仕込むと良いでしょう。

開発支援系

rails-erd

私はER図が好きなので、Railsの中で適切にリレーション(has_manyなど)を設定してあげれば、よしなにいい感じのER図を描いてくれるこのgemの存在は大変ありがたいです。

rack-mini-profiler

処理速度を知ることができます。ボトルネックを探したいときに重宝します。

sitemap_generator

SEO対策の基本の一つがsitemap.xmlを作成することです。rubyには、sitemap_generatorというgemが非常に便利です。

rake sitemap:refresh

でsitemap.xml.gzを作成しGoogleやbingにpingも飛ばしてくれるのですが、開発時にはpingは飛ばして欲しくありません。

bin/rake -vT | grep sitemap

でsitemap_generatorのrakeタスクが見れますが、開発時によく使うのは、検索エンジンにpingを飛ばさずにsitemap.xmlを作成することでしょう。
ですので、

rake sitemap:refresh:no_ping

で作成した後、

cat tmp/sitemap.xml.gz | xmllint --format --encode utf-8 - | less

で確認するという感じで使用しています。

appraisal

  • 主にgemを作るときに用いるgemです。
  • gemを作る際、依存するgemの様々なバージョンに対応しないといけません。そのときにテストを楽にしてくれるのが、appraisalです。
  • 使い方はAppraisalsファイルに次の様に記載します。(READMEから拝借)例では、rails-3とrails-4の最新のバージョンでテストしたい場合になります。
appraise "rails-3" do
  gem "rails", "~> 3.2.0"
end

appraise "rails-4" do
  gem "rails", "~> 4.2.0"
end
  • その後、bundle exec appraisal installコマンドを打つと、gemfilesというディレクトリができ、その中にrails-3.gemfileやrails-4.gemfileが追加されます。
  • 全てのバージョンでのテストをしたいときは、次の様なコマンドが用意されています。
bundle exec appraisal rake test  # minitestの場合
bundle exec appraisal rspec spec # rspecの場合
  • 特定のバージョンをテストしたいときは次の様になります。
bundle exec appraisal rails-3 rake test  # minitestの場合
bundle exec appraisal rails-3 rspec spec # rspecの場合

そのほかコメント

  • ancestry
    • リレーショナルデータベースで木構造を取り扱う場合の系列列挙モデルで実装したgem。系列列挙モデルの場合、pathの整合性が取れなくなる可能性がある懸念から、抵抗があります。自分で隣接リストモデルで実装してしまうことが多いです。
  • annotate
    • データベスを見に行けばわかる情報わざわざモデル内に書き込むのは如何なものかと思いました。
  • better_errors
    • Rails5系から、pumaが利用されることになり、相性の問題からか重くなっているようです。解決する方法も報告されていますが1binding.pryなどでデバッグできるので、あまり必要性を感じなくなりました。
  • bullet
    • N+1を教えてくれるgemですが、個人的にはコード書いてる時やログ見ているときに気づくのではと思いました。とはいえ、見逃す時もあるので、嬉しいときもあります。
  • dotenv-rails
    • 開発時にはdirenvを使えばいいかなと思います。本番環境でも、デプロイ時などにうまく環境ごとにセットできる方法があるはず。AWSのElasticBeanstalkでは簡単にセットできます。
  • ransack
    • コード的にはシンプルだが重いSQLを生み出し、大幅に速度低下していたのを生SQLで書き直した経験があり、ransackでできることぐらいであれば自分でActiveRecord経由でSQL構築した方がいいと思う派です。

最後に

gem良いですよね。