Gunosy Tech Blog

Gunosy Tech Blogは株式会社Gunosyのエンジニアが知見を共有する技術ブログです。

Gunosy管理画面を支えるRails技術

広告技術部の toshimaru です。この記事はGunosy Advent Calendarの24日目の記事です。

qiita.com

はじめに

Gunosyではいくつかの管理画面においてRuby on Rails(以降Rails)を利用しています。具体的には下記の管理画面においてRailsが利用されています。

  • 社内メンバー向け管理画面: 社内の担当者が記事の管理を行ったり、Gunosyアプリのユーザーの管理を行ったりできる管理画面です
  • メディア様向け管理画面: Gunosyに記事を提供していただいているメディア様向け管理画面で、レポート閲覧や記事管理を行うことができます
  • 広告主様向け管理画面: Gunosy Adsに広告を配信していただいている広告様向けの管理画面で、広告出稿やレポート閲覧を行うことができます

今日はそんなGunosy管理画面を支えているRails技術をいくつかピックアップして紹介してみたいと思います。

デプロイ

Rails的にはcapistranoを使ったデプロイが推奨方法のように見受けられますが、弊社でのRailsアプリケーションのデプロイは弊社おなじみのOpsWorksを通じて行っています。

【図】GitHubの特定ブランチの変更を行ったらCircleCIでテスト通過後、OpsWorksにデプロイリクエストが飛びます

OpsWorksではサーバープロビジョニングやアプリケーションデプロイのタスクがChefのレシピとして管理されているので、デプロイ時に何かカスタマイズを加えたい場合はChefのレシピをアップデートする形となります。

【図】OpsWorksを通してChefでサーバーサーバーのセットアップ、コンフィギュレーション、デプロイまで担っています(図は私の発表資料から引用)

認証・ログイン

管理画面といえばまず真っ先に実装することになるのが認証・ログイン機能だと思います。

弊社のRailsアプリケーションのログイン機能は、Railsエンジニアであればおなじみのdeviseを使うことが多いです。

deviseのメリットはなんといっても導入の手軽さではないでしょうか。deviseをインストールした後に、rails generate devise:installすれば必要なファイルや設定がまるっと作成されログイン機能が利用できるようになる―この手軽さは他の認証系gemではなかなか得られません。

一方でそのカスタマイズのしにくさやヘビーな実装からdeviseの導入を忌避する向きもあります。

そこで弊社の最近の管理画面では認証gemとしてsorceryも使っています。 sorceryはLess is moreを哲学として謳っている通り、ミニマルでクリーンな実装が特徴的です。

このsorcery gemの導入によりカスタマイズしやすいシンプルな認証ロジックを構築することができるようになりました。

認可

管理画面で認証の次に欠かせないのは認可です。

管理画面において「X機能はAさんに使わせたいが、Bさんには使わせたくない」みたいなケースはよくあるかと思います。

認可系gemはいくつかありますが、弊社ではかつてauthorityを使っていましたが(本gemは現在UNMAINTAINEDなステータスなので本記事執筆時点でのこのgemの採用は推奨しません)、今はpunditを使うケースが多いです。

punditはapp下にpoliciesという新たなレイヤーを作成しそのポリシーを前提として動作します。こうすることで認可ポリシーを分離して開発できるというメリットがあります。シンプルな使い勝手ながら強力なgemなので認可においては非常に重宝するgemです。

権限管理

認可の分類を権限(role)にて管理するケースはよくあると思います。User has_many rolesの関係性の場合の権限管理はrolifyを使っています。このgemを導入することでroleを扱う上での様々な便利メソッドをモデルに生やしてくれます。

User has_one roleの関係性においては、権限ごとにnamespaceを切って開発したりもしています。この構成にすることでControllerやViewで生じがちな権限による分岐をなくすことができ、権限チェック漏れなどによる事故は防ぐことができます。

非同期ジョブ

非同期ジョブに関してはsidekiqresqueを併用しています。

それぞれsidekiqは比較的軽めの処理で処理スループットが求められるような非同期ジョブに使っており、resqueは一時間毎に一回走るような重めの処理において使っています。

なお定期ジョブのスケジューリングはwheneverを使って管理しています。

テスト

RailsのテストにはRSpecを採用しており、E2EテストではCapybara、フィクスチャーにはfactory_botを採用しています。CIはCircleCI(version2)を使って回しています。テストカバレッジ計測にはcoverallsというサービスを利用しています。

JavaScript Driverについてはpoltergeistを利用していましたが、最近はChrome Headlessを使うようにしています。このへんに関しては弊社の hoshitocat が知見をまとめてくれていますので是非ご参照ください。

qiita.com

また複雑化しがちなCapybara Feature Specのコードを管理しやすくするためにsite_prismを一部で導入しています。urlやsection, elementをPageオブジェクトとして管理することでFeature Specのテストケースを読みやすく、シンプルなものに保つことができています。

追記】site_prismに関しては別途記事にまとめましたのでご参照ください。

tech.gunosy.io

レビューに関する取り組み

現在私の所属する広告技術部の管理画面においてはレビューに関する様々な取り組みも行っています。

自動bot通知

レビュワーとしてアサインされている人のレビュー漏れがないようにアサインされている人にはbot通知を送るようにしています。

【図】レビュー待ちのPRがない時のメッセージ

自動レビュー

弊社のRailsプロジェクトのコーディングルールはRuboCopを用いて標準化しているのですが、RuboCopルール違反が見つかった時は、ruby-saddler-reporter-githubを使ってCircleCIから自動でコメントするようにしています。

【図】RuboCop違反の自動レビューコメント

RuboCopの他にもrubycriticでコード品質チェックを行ったり、brakemanを使ってセキュリティチェックを行っています。そしてこれらをCircleCIのArtifactsに載せてチェック結果を閲覧できるようにしています。

今後の課題

今後の課題もいくつかあります。

  • 2016年以降rails newしたプロジェクトはRails5だが、それ以前のプロダクトはRails4.x
    • 現在この問題を解消すべく、古い管理画面のRails4.x から Rails5 にupgradeするプロジェクトが動いています。そのへんの知見もアップデートがあれば本ブログに書こうと思います。
  • OpsWorks Ruby Version
    • OpsWorksをChef11.10のバージョンで運用しているのですが、そのバージョンのRailsアプリケーションだとRubyのバージョンに制限があります。(参考 GihHub Issue)これを解決するためにChef12で動くOpsWorksに移行する必要があります。
    • 同時に Kubernetes などのコンテナベースのデプロイの仕組みも検討しています。
  • フロントエンドのモダン化
    • 一部の管理画面でReact.jsを導入したりもしていますが、Railsフロントエンドのモダン化をどうしていくかは未だ模索中です。

追記】管理画面のRailsバージョンをRails4からRails5に上げたときの知見をまとめました。よろしければこちらもご参照ください。

tech.gunosy.io

最後に

全てをここでは書ききれませんがざっと弊社のRails管理画面の開発の中身を紹介してみました。

私の所属する広告技術部ではRails管理画面に限らず広く一緒にサーバーサイド開発してくれる仲間を募集中です。ご興味あるエンジニアの方は下記から応募してみてください!

https://hrmos.co/pages/1009778707507720193/jobs/0000003hrmos.co