Rails

Railsアプリのテスト実行時に特定の警告だけを例外に変換する

今後役立つのかわからないがRuby 2.7→3.xアップデートのときに使った方法のメモ。 Warning[:deprecated] = true すると表示される非推奨警告を発生させるコードがRailsアプリに含まれないように、テスト実行時だけこのような警告をあらかじめエラーに変換で…

できるだけコントローラではなくモデルで例外処理する

問題: コントローラで例外処理している アプリケーションが扱うドメイン特有のエラーを例外として表現する場合に、その例外をコントローラで処理するコードを書くと、ほとんどの場合でコードが読みにくくなったり、コードを変更しづらくなったりする結果とな…

AOPに基づいてconcernモジュールを作る

発端: concernモジュールの命名をどうするか ここではActiveSupport::Concernをextendしたモジュールのことをconcernモジュールやconcernと呼ぶ。 「Concernに何を実装すべきかは…非常に曖昧」1である。さらに、Railsアプリのメインであるルーティングからモ…

Railsエンジンのappディレクトリ配下のクラスを親アプリでオーバーライドする

やりたいこと Railsエンジンのappディレクトリ配下に存在するクラス(モデルやコントローラ)のメソッドをオーバーライドしたい。 結論 RailsガイドのRailsエンジンについての記事に全部書いてある。Railsエンジンのapp配下のオーバーライドは、to_prepareを…

authorization code grantに沿ったDoorkeeperのコードリーディング

さまざまな都合により、OAuth 2のプロバイダになるためのDoorkeeperというgemのコードを読むことがしばしばある生活を送っている。 似た名前のモジュールやクラスが多く、読むたびに混乱しているので、authorization code grantでアクセストークンを取得する…

意図せず関連先のカラムでwhereしつつeager loadしたらクエリのパフォーマンスが極端に悪化した事例

問題 15個ぐらいのさまざまなクエリパラメータを検索条件として受け付けることができる一覧取得API(「Item取得API」とする)があった。 そのAPIで取得するItemは複数の関連を持っていた。また、関連先の取得時にN+1問題の対策が不十分だったので、取得する…

リソースとActive Recordのモデルのあいだの差異を吸収するクラスを作る

Web APIのリソースとバックエンドで扱うモデル(特にActive Recordのモデル)に歴史的な事情で差異があり、単純にモデルからリソースへと変換できないとき、それらの差異を吸収するクラスを作って対応することがあったのでメモを残しておきます。 問題 あるW…

外部サービスのリソースをJSONシリアライザブルなActive Modelとして表現する

RailsでWeb APIを作っていて、外部のサービスからリソースを取得し、DBには保存しないもののレスポンスに含めてクライアントに返したい、ということがありました。このとき次のモジュールが役立ったので紹介します。 ActiveModel::Model ActiveModel::Attrib…

Active Recordでstring型属性を暗号化するためのRailsプラグインを作った

複数プロジェクトで、Active Recordのstring型を拡張して透過的に文字列を暗号化/復号できる型をattributes API(ActiveRecord::Attributes) を使って書く場面を目撃したり、自分でも書く機会があったので、Railsプラグインに切り出してみました。 github.c…

OpenAPI 3ドキュメントも使えるSchemaConformist 0.3.0をリリースした

rubygems.org これまでのバージョンの差分はOpenAPI 3ドキュメントが使えるようになった点です。OpenAPI 3に対応したCommittee v3の機能を使うことで、integration test/request spec実行中にOpenAPI 3ドキュメント中のスキーマに基づいたJSONレスポンスのバ…

"The Modular Monolith: Rails Architecture"を読んだ

Modular MonolithというアーキテクチャをRailsアプリケーションへ適用する記事を読みました。 medium.com モノリスアーキテクチャとマイクロサービスアーキテクチャの中間に位置する、一つのモノリシックなアプリケーション内でドメインごとにモジュールに分…

アソシエーションのscopeを使いつつLIMITっぽいことをやる

細かすぎて伝わらないかもしれませんが、ハマったので共有します。 問題 ユーザーが免許を持つ次のようなモデルを考えます。has_one :licenseは免許更新を重ねてきたなかで最新の免許を取得したくて書いたと思ってください。 class User < ApplicationRecord…

GraphQL Subscriptionsをgraphql-rubyとAction Cableで作る

graphql-rubyでは、RailsのAction Cableに乗ることでGraphQL Subscriptionsを実装できます。 GraphQL Subscriptionsとは GraphQL Subscriptionsは、あらかじめ特定のGraphQLクエリを購読しておき、サーバ側でイベントが起きるたびにその形式のデータを受信で…

wscatでAction Cableと通信する

Railsで/cableなどのエンドポイントにAction CableをマウントするとWebSocketサーバとして利用できます。wscatを使ってAction CableによるWebSocket APIと対話的に通信するために、送信するデータの形式などを調べました。 準備 wscat github.com npmでイン…

GraphQL APIを作るときにテストをどう書いていくか

こういうのはどうかという最近の考えを書いておきます。とはいっても、だいたいはgraphql-rubyのドキュメントに書いてあります。Rails + graphql-ruby + RSpecが前提です。 各フィールドのテスト フィールドから正しく値を取得できるか、つまりRailsのモデル…

GraphQL APIをスキーマファースト開発するためのモックサーバをRailsとApolloで作る

GMOペパボ Advent Calendar 2017の23日目の記事です。 今回はJavaScriptでGraphQLのサーバ/クライアントや関連ツールを提供しているApolloのツールセットでRailsプロジェクトでGraphQLのモックサーバを立ち上げるところまでを試してみます。 業務でRails製…

Railsの内部やPluginによる拡張方法について学べる本 "Crafting Rails 4 Applications" を読んだ

読みました、というよりは夏の終わりぐらいから何度か読んでいました。 Crafting Rails 4 Applications: Expert Practices for Everyday Rails Development (The Facets of Ruby)作者: Jose Valim,Brian P. Hogan出版社/メーカー: Pragmatic Bookshelf発売日…

テスト時にAPIドキュメントのスキーマ定義からレスポンスのJSONを自動でバリデーションするgemを作った

あらかじめ書いたJSON Hyper Schema/OpenAPI 2.0のAPIドキュメントにおけるレスポンスのスキーマ定義をもとに、APIモードのRailsでHTTPリクエストを発行するテストを実行すると、自動でレスポンスのJSONをバリデーションしてくれるSchemaConformistというgem…

RSpecのrequest specでCommitteeを使ってレスポンスJSONを自動的にバリデーションする

この記事の続きのようなものです。 blog.kymmt.com やりたいこと Rails + RSpecでWeb APIのrequest specを書くときに、Committee(とCommittee::Rails)の assert_schema_conform を使って、レスポンスのJSONがOpenAPIドキュメントで定義したレスポンスのJSO…

Web APIのレスポンスJSONをCommittee + OpenAPIでバリデーションして仕様と実装の乖離を防ぐ

APIドキュメントに書いたJSON Schemaと実際に実装したWeb APIのレスポンスJSONが一致するかバリデーションするためのCommitteeというgemがあります。また、このCommitteeをRailsプロジェクト中のテストから使うためのCommittee::Railsというgemがあります。 …

Rails 5.1でRails pluginをセットアップする手順

最近読んでいる “Crafting Rails 4 Applications” の中でRails pluginを開発する場面が多々あるので、手元でもRails 5を使ってRails pluginを書いてみています。 Rails 5だと、プラグインのセットアップ手順が本の記述やRails Guidesの記述と少し違っていた…

GraphQL::Batchのサンプルコードを読む & 使ってみる

単純にGraphQLクエリを投げると、サーバサイドでの関連を含むレコード取得時にN+1問題が発生することがあります。こういうケースでは、複数のデータ取得リクエストをひとまとめにして、単一のリクエストとしてDBからデータを取得するbatchingが推奨されてい…

graphql-ruby + Railsで簡易なクエリとミューテーションが使えるGraphQL APIを実装する

会社でGraphQLのハンズオンがあったのをきっかけに、最近はGraphQLのサーバ側実装をちょっと触っています。 graphql-rubyを使うと、RubyでGraphQL APIを実装することができます。今回はRailsでGraphQLのクエリとミューテーションを実装してみました。 graphq…

Yokohama.rb Monthly Meetup #82に参加した

2017-07-08(土)のYokohama.rb Monthly Meetup #82参加メモです。 yokohamarb.doorkeeper.jp Rubyレシピブック レシピ257から260まででした*1。259, 260についてメモ。 259: リモートホストが稼働していることを確認する リモートホストが動いているかを確…

Springが動くRails+MySQLなAPIサーバの開発環境をDocker Composeで作る

このあいだ、Rails+MySQLという構成のアプリケーション開発環境をDocker Composeで構築できるようにしました。 blog.kymmt.com いろいろと理解が深まるにつれて、何点かクリアしたい問題が見えてきました。 Dockerfile で使うイメージ ruby:2.4.1-onbuild は…

Rails+MySQLなAPIサーバの開発環境をDocker Composeで作る

先日、"Quickstart: Compose and Rails"の手順にしたがいながら、Docker ComposeでRails+MySQLがとりあえず動くような環境を作りました。 blog.kymmt.com 今回は、RailsのAPIサーバの開発環境をもうちょっといい感じにDocker Composeで作ってみます。DBにはM…

"Quickstart: Compose and Rails"を読みながらDocker ComposeでRails+MySQLの環境を作る

次の記事などでDockerを使ってRailsの開発環境を構築しているのを見て、自分でもやっておこうと思ったので、やってみました。 dev.classmethod.jp 公式ドキュメントの"Quickstart: Compose and Rails"を読みながらやります。 docs.docker.com 前提 まったく…

Rails を使った EC アプリケーション開発について学べる本 "Take My Money" を読んだ

読みました。 Take My Money: Accepting Payments on the Web作者:Rappin, NoelPragmatic BookshelfAmazon どんな本か 副題が "Accepting Payments on the Web" となっているように、決済 (payment) システムをもつ Web アプリケーションを作る方法について…

Rails 5.0.1 で rails new するとできる Gemfile の git_source ブロックの意味

Rails 5.0.1 で rails new したときに作成される Gemfile の先頭に次のブロックが挿入されるようになっていました。 git_source(:github) do |repo_name| repo_name = "#{repo_name}/#{repo_name}" unless repo_name.include?("/") "https://github.com/#{re…

Ruby (on Rails) で使える enumeration 実装を比較してみた

こんにちは、GMO ペパボの人間です。これは pepabo Advent Calendar 2016 の 9 日目の記事です。 昨日は我らが CTL けんちゃんくんさんの 「gemビルドしようとして The validation error was 'yourgem-x.y.z contains itself (yourgem-x.y.z.gem), check you…