Railsコードを改善する7つの素敵なGem(翻訳)

概要 原著者の許諾を得て翻訳・公開いたします。 英語記事: 7 Gems Which Will Make Your Rails Code Look Awesome 公開日: 2017/10/14 著者: Val Zavadskiy サイト: https://blog.rubyroidlabs.com/ Rubyroid Labsの別記事「Ruby on Railsで使ってうれしい19のgem(翻訳)」も合わせてどうぞ。 Railsコードを改善する7つの素敵なGem(翻訳) 私たちRubyroid Labはアプリのアーキテクチャに多くの情熱を注ぎ込んでいます。手がけているプロジェクトの多くが長期にわたっているので、設計のどこかで少し油断すると、機能を1つ追加するのにプロジェクトをスクラッチからやり直す方が早い、といった事態になりかねません。こんな目には遭いたくないものです。 新しく参加したメンバーがロジック把握のためにソースコードを読みとおすだけでかなり時間がかかるようなら、それはプロジェクトが病んでいることを示す兆候のひとつです。本記事では、コードを整理してチームメンバーの笑顔を取り戻してくれるさまざまなgemをご紹介いたします。 1. interactor(固定リンク) 何らかの複雑なビジネスロジックを書くときには必ず私たちのリストに入るほど素晴らしいライブラリです。さてinteractorとは何でしょうか?Readmeには「ビジネスロジックのカプセル化というひとつの目的だけを持つシンプルなオブジェクトです」とあります。ビジネスロジックのカプセル化といえば皆さんの大好きなService Objectを連想するかもしれませんが、interactorはずっと機能が豊富です。早速コード例をご覧に入れましょう。 # app/interactors/create_order.rb class CreateOrder include Interactor def call order = Order.create(order_params) if order.persisted? context.order = order else context.fail! end end def rollback context.order.destroy end end # app/interactors/place_order.rb class PlaceOrder include Interactor::Organizer organize CreateOrder, ChargeCard, SendThankYou end コード例を見れば、このgemの実に素晴らしい機能がいくつもあることにお気づきかと思います。 まず、シンプルなinteractorをいくつかまとめて1つの実行可能なチェインにできるという点です。contextという特殊変数は、異なるinteractor同士でステートを共有するのに使われています。 次に、interactorのひとつが何らかの理由で失敗すると、それまでのinteractorはすべてロールバックします。CreateOrderクラスには#rollbackがあり、たとえばChargeCardやSendThankYouが失敗すればorderは破棄されます。 実にクールなgemですね。 2. draper(固定リンク) Railsでヘルパーを自作したことがあれば、時間とともにヘルパーが増えて手に負えなくなったことがあるでしょう。こうしたヘルパーは一部のデータの整形表示に使われることがほとんどです。このようなときはDecoratorデザインパターンの出番です。draperの文法は、見ればだいたいわかるようになっています。 # app/controllers/articles_controller.rb def show @article = Article.find(params[:id]).decorate end # app/decorators/article_decorator.rb class ArticleDecorator < Draper::Decorator delegate_all def publication_status if published? “Published at #{published_at}” else “Unpublished” end end def published_at object.published_at.strftime(“%A, %B %e”) end end <!– app/views/articles/show.html.erb –> <%= @article.publication_status %> 上のコードを見ると、published_at属性を特定のフォーマットで表示するのが目的になっています。古典的なRailsウェイでは、こういう場合に2つの選択肢がありました。 1つ目は単にそれ用のヘルパーを書くことです。この場合、すべてのヘルパーが同じ名前空間に属するので、プロジェクトが長期化するに連れていまいましい名前衝突が発生するようになり、デバッグも非常に困難になります。 2つ目はモデルの中にメソッドを書いてそれを使うことですが、モデルのクラスの責務を超えてしまうのでよろしくありません。モデルのデフォルトの責務は「データのやりとり」であり、データの表現方法ではないからです。 こういう場合にdraperを使うのは、よりエレガントに目的を達成できるからです。 次の素晴らしい記事も合わせてご覧ください。 Ruby on Railsで使ってうれしい19のgem(翻訳) 3. virtus(固定リンク) シンプルなRubyオブジェクトをそのまま使っても要件を満たせないことがあります。たとえば1つのページに複雑なフォームがいくつもあり、フォームごとに異なるモデルとしてデータベースに保存しなければならないとします。こんなときはvirtusです。次の例をご覧ください。 class User include Virtus.model attribute :name, String attribute :age, Integer attribute :birthday, DateTime end user = User.new(:name => ‘Piotr’, :age => 31) user.attributes # => { :name => “Piotr”, :age => 31, :birthday => nil } user.name # => “Piotr” user.age = ’31’ # => 31 user.age.class # => Fixnum user.birthday = ‘November 18th, 1983’ … Continue reading Railsコードを改善する7つの素敵なGem(翻訳)