最近RubyとReact.jsをよく利用していて、Rubyで扱っている値をJSONとして表現したいケースが増えてきた。いうのどうやっていますかと人に聞きたいので、自分はこうやっていますよというのを説明のためにまとめておくことにする。自分の場合、次のような方法で実装することが多い。(ActiveSupportがやってくれる)コード具体的には、以下のようなクラスをつくっている。コメントのJSON表現のためのクラスである。コメントのJSON表現におけるViewがこのクラスということになる。endend上記のものは共通部分を集めた基底クラスで、実際にはこれを継承した具象クラスを定義して利用する。雑多な部分は取り除いてあるが、例えばRailsでコメントのJSONを返すactionを定義したい場合はこういう風にして使う。いうライブラリが提供しているmodule。いうインスタンスメソッドが定義される。実装を支援するためだけに利用しているライブラリなので、無くても構わないが、見通しがよくなるので使っている。Schemaが生成できるようになるが、型情報の指定はやはり手間が掛かるので公開APIを提供する場合以外はこの機能は使っていない。current_userWebアプリケーションでの用途だと「誰がアクセスしているか」によってレスポンスを変えたい場合が多く、これはJSONの場合も例外ではない。Likeを付けたコメントにはアイコンを付けておきたいとか、削除しても良いコメントの場合は削除ボタンを出したいとか。いった情報がクライアントサイドで逐一計算されるのではなく、JSON表現自体に含まれていると、重要なロジックも一元管理できて便利な場合が多い。いう要求から、上述したJSON表現用のクラスのコンストラクタでは、current_userというコンテキストに依存した値も受け付けられるようにしている。昔は「JSONを返すようなエンドポイントでは、キャッシュしやすくするために常にコンテキストに依存しない値を返すべきではないか」と考えることもあった。実際にこの手の処理を利用したアプリケーションを何度も実装してみると、文脈に依存してデータを返せる利便性を優先したほうが現実的に感じるようになった。JSONに変換するというのは、一種の関数のようなもので、current_userを渡す場合も関数で受け取る値が複数個になっただけという気持ちで見ている。ちなみに上記のコード例だと「いちいちLikeしてるかどうか見てたら、N+1クエリ発生してまずくない?」という疑問が発生するかもしれない。実装がeager-loadingに対応していて問題が無かったり、そもそもコンテキストに依存した値が必要ない場合はcurrent_userを指定しないなどの方法で上手く回避している。GraphQLなどを利用すれば、求められているデータだけ計算すれば良いということになり、この手の問題は解消されるはず。GraphQL同様に取得したいプロパティを指定するための簡易言語があり、同じ問題を解決できる。おしまい要点だけ説明したので伝わりにくかったと思うけれど、とりあえず説明は以上です。この方法は、直近で携わったものだと、掲示板、amakan、WikiHub、Qiitaなどで利用されている。皆さんどうやってますか。良かったらTwitterやブログ記事などに書いて教えてください。.to_react_propsみたいな方法より、目的ごとにクラスを用意して表現した方がいいと思う。2016あるオブジェクトをJSONとして表現するときにどう表現したいかというのは、例に挙げたcurrent_userの他に、用途によってもかなり変わってくる。APIでは恐らく表現方法が異なってくる。みたいなものが生やされてしまう例も稀によく見る。他にも、1つのJSONのObjectを生成するのに複数のモデルが必要な場合もあって、モデル自体に定義しようとすると厄介なケースが多い。いう機能が実装されたが、これには「ユーザのポップアップの表示に必要なデータ」をJSONで表現するクラスが利用されている。このユーザをフォローしているかどうか、記事投稿数、Contributionの値などを計算して含める必要があるので、この用途専用の表現が必要になっている。いう風に用途によってJSONの表現方法が変わってくることを考えると、用途と表現用クラスを1対1にして管理するというのは、悪くない考えだと思う。(仮にactive_model_serializersを自分で書けと言われると少し面倒な規模感)。このくらいの用途であればもっと軽量な実装の方が良いだろうというのが、これを使っていない理由です。Schemaの実装を抜いた、さらに軽量なGemも用意していて、用途に応じてこれと使い分けている。