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
記事投稿時点では、draperを使っていましたが、結局、モデルが小さければモデル内のメソッドで定義、viewだけで使うということを明示したい場合は、concerに逃すと言った方が実用的と感じ2024年4月現在ではdraperを選択することはほぼなくなりました。一見してdecorateしているかを把握することも面倒です。また、viewだけで使うと思ったらview以外でも使う必要が出てきたということもあるので、draperの問題というより、デコレーターパターンのメリットを感じなくなってきたのが理由です。
データベース系
activerecord-import
RailsでBULK INSERTするにはどうすればいいかなと思ったときに役に立つのがこのgemです。ただし、Rails6以上からは標準でサポートされました(insert_all
やupsert_all
など)ので、不要になってくると思います。
paper_trail
以前、リレーショナルデータベースでの履歴管理を真剣に考えたことがあるのですが、リレーショナルデータベースにおいて履歴管理は苦手分野の一つで結構苦戦して、結局このgemにたどりつきました。
レコードの履歴管理の定番のgemだと思います。yaml形式やjson形式で差分を表示してくれます。jsonをサポートしているデータベースであれば、json形式で保存できるのは便利です。
auto_strip_attributes
フォームからレコードを生成する場合、例えば任意項目などでテキストフィールドに入力が不要な場合、params
には次のような形で入ってきます。注目はcorporate_name
でここが任意の場合、空文字できます。そうすると、レコードには空文字で保存されてしまいますが、null
(rubyではnil
)で保存して欲しいです。
<ActionController::Parameters {"order"=><ActionController::Parameters {"family_name"=>"てすと", "given_name"=>"太郎", "corporate_name"=>""} >
この時に便利なのがこのauto_strip_attributesで、モデルに次のように記述すると空文字を自動でnil
に変換してくれます。
class Order < ApplicationRecord
auto_strip_attributes :family_name, :given_name, :corporate_name
end
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つまで並列実行するとほぼ確実に高速化します。(3並列以上だと必ずしも速くなるとは限りません。)
コマンドの実行の仕方は-n
オプションで並列・平行数を指定します。CPUの数より大きい値を指定した場合は、よしなに平行実行されますが、IO待ちなどがない限り、スピードは上がらないかもしれません。
Rails6ではテストの並列実行ができるようになる予定です。1 そうなれば、このgemは不要になるかもしれません。
bundle exec parallel_rspec -n 4
rspec-retry
rspecでテストが失敗したとき、リトライしてくれます。リトライ単位はit
やscenario
です。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の整合性が取れなくなる可能性がある懸念から、抵抗があります。自分で隣接リストモデルで実装してしまうことが多いです。2
- リレーショナルデータベースで木構造を取り扱う場合の
-
annotate
- データベスを見に行けばわかる情報わざわざモデル内に書き込むのは如何なものかと思いました。
-
better_errors
- Rails5系から、
puma
が利用されることになり、相性の問題からか重くなっているようです。解決する方法も報告されていますが3、binding.pry
などでデバッグできるので、あまり必要性を感じなくなりました。
- Rails5系から、
-
bullet
- N+1を教えてくれるgemですが、個人的にはコード書いてる時やログ見ているときに気づくのではと思いました。とはいえ、見逃す時もあるので、嬉しいときもあります。
-
dotenv-rails
- 開発時にはdirenvを使えばいいかなと思います。本番環境でも、デプロイ時などにうまく環境ごとにセットできる方法があるはず。AWSのElasticBeanstalkでは簡単にセットできます。
-
ransack
- コード的にはシンプルだが重いSQLを生み出し、大幅に速度低下していたのを生SQLで書き直した経験があり、ransackでできることぐらいであれば自分でActiveRecord経由でSQL構築した方がいいと思う派です。
最後に
gem良いですよね。