読んだ「カスタマーサクセスの実現のためCustomer Reliability Engineering(CRE)チームを立ち上げました | FiNC Tech Blog」

カスタマーサクセスの実現のためCustomer Reliability Engineering(CRE)チームを立ち上げました | by 小林毅志 | FiNC Tech Blog | Jul, 2020 | Mediumを読んだ。

読みながらマインドマップを作った。

f:id:tanaken0515:20200803084808p:plain

https://www.mindmeister.com/ja/1579107296/finc-cre

感想

ブログ記事の「課題」の部分、自分にとってはあまり読みやすくなかった(並列ではない事柄が並んでいるように見えた)

「新規機能の開発で手一杯」と「本質的な改善に動く余裕がなかった」は結局どうやって解決したのか分からなかった

  • CREチームが誕生した時点ですでに解決していた?
  • 人員を増やす、新規機能の開発を止める(優先度を下げる)、あたりのアクションが必要そうだと感じる
    • 「今ではPM1名、バックエンドエンジニア4名、iOSエンジニア1名とチームのメンバーも増えてきました」
    • すごい。このメンバーたちがいるから解決した、ということかな?

問い合わせ件数が半分になったのすごい

  • DAUを伸ばしつつお問合わせ件数半分とのこと
  • ここでの「お問い合わせ」はユーザからCSへのお問い合わせかな
    • 「当然、エンジニアにくる問い合わせ自体も減っています。」という記載があるから、そうっぽい
    • ユーザ -> CS -> エンジニア のどの矢印のことを指しているのか分かりやすく書けるともっとよさそう
  • ユーザに困りごとを発生させない、あるいは、お問い合わせをしなくても困りごとを解決できる、という状態を目指していきたい
    • これは結果的にユーザからCSへのお問い合わせの件数に反映されるはず
    • 一方で、お問い合わせの件数が減ったからといって、本当に困りごとが解決していると言い切れるのか?という話もある
    • 本当に困りごとが解決しているのかどうかを、把握できるようにする必要がありそう

「信頼」について考える

心理的安全ジャーニー Slackで安全を実装する5つの手法 - Speaker Deck を読んだ。 「心理的安全性」という言葉について、Googleによる定義に基づいて図解を織り交ぜながら分かりやすく説明してくれている。

今回は、この資料の後半に出てくる「信頼」という言葉について考えたい。

なぜ「信頼」について考えるか

いま自分が取り組んでいるCustomer Reliability Engineering(CRE : 顧客信頼性エンジニアリング)の活動においても「信頼」という言葉が出てくる。

➡︎CREについての記事はこちら: CREとはなんなのかを考えている - tanaken’s blog

けど「信頼」という言葉自体について考えたことなかった。

今回の資料での「信頼」は「チーム内の対人関係における信頼」なので、これをそのまま「CREにおける信頼」として解釈するのは適切ではないかもしれない。

とはいえ同じ「信頼」という言葉なので、ヒントとなる考え方はありそうな気がしている。

信頼とは何か

f:id:tanaken0515:20200729083042j:plain 引用: 心理的安全ジャーニー Slackで安全を実装する5つの手法 - Speaker Deck

  • 自分に何か困ったことが発生した時、何かに悩んでいる時、誰かに頼りたい時、相手が相談に乗ってくれる、一緒に解決策を考えてくれる、そういう行動をしてくれると信じること = 信頼 なのだなぁ
    • その問題の解決に至るかはここでは議論されていない(もちろん解決できた方が良いと思うけど)
  • CREの観点で考えてみると、登場人物は「顧客」と「サービス運営者」がいる。「サービス運営者」としては「顧客」に次のように感じてもらう(=信じてもらう)ことを目指したいなと思った。
    • 問い合わせをしたらすぐに相談に乗ってくれそう
    • 一緒に解決策を考えてくれそう
    • 実現したいことを手助けしてくれそう
  • 「顧客」のことを信じるという観点も忘れずにいたいなと思った
    • 相互に「信頼」を築きたい

信頼に至るまで

f:id:tanaken0515:20200802094142j:plain 引用: 心理的安全ジャーニー Slackで安全を実装する5つの手法 - Speaker Deck

  • 信頼への道のりには「親和」と「尊重」がある
  • のりを早く進むには「感謝」も大事っぽい

親和について

f:id:tanaken0515:20200729090816j:plain 引用: 心理的安全ジャーニー Slackで安全を実装する5つの手法 - Speaker Deck

f:id:tanaken0515:20200729091514j:plain 引用: 心理的安全ジャーニー Slackで安全を実装する5つの手法 - Speaker Deck

  • 「親和」を築くには「コストを払ってまで友好関係を築きたい」という意思を相手に伝えることが大事らしい
    • ちょっと恩着せがましいような印象もある...
    • でもまあわからなくもない
      • ちょっとしたことで「こんなことしてくれるんだ〜」と嬉しくなる瞬間はある
      • 例えば、スタバでカップにお絵描きしてくれるやつとか
        • 自体自分にとっては特に利益にはならない
        • けど、なんとなく「悪い気はしないな〜」みたいな
          • 相手がちょっとしたコスト(時間)を払ってくれているからなのかな?(わからない)
  • CREの観点で考えてみると、「サービス運営者」は「顧客」との親和を築くためにコストを払って何かやってみよう、ということかな。
    • 例えばいま自分が携わっているSUZURIだと、このメールとかはまさにそれかもしれない

尊重について

f:id:tanaken0515:20200802094136j:plain 引用: 心理的安全ジャーニー Slackで安全を実装する5つの手法 - Speaker Deck

f:id:tanaken0515:20200802094131j:plain 引用: 心理的安全ジャーニー Slackで安全を実装する5つの手法 - Speaker Deck

  • 「静かな人に声を与える」の大事そう&むずそう
    • その場では考えを言わないけど別の場では言うとか、頭の中だけに留めてしまうとか、そういうケースあると思う
    • なぜそうなるのか?
      • たぶん「自分の考えを伝えても意味ないや」とか、「自分が意見を言うような話ではなさそう」とか、考えてしまう
    • どうすれば?
      • 「意見の尊重」をするのが大事
    • どうなる?
      • 「自分の考えを汲み取ってくれる」とか、「自分の意見がヒントになるかも」とか、考えるようになる
  • CREの観点では、「サービス運営者」は「顧客」に対して「意見の尊重」をしている姿勢を示す必要がありそう
    • 例えば「こんなご意見をいただきました!」のリストを開示するとか?
      • まずは意見がちゃんと届いていることを伝える
    • 意見に対する対応方針も示せるとよさそう(対応しない場合も含めて)

感謝について

f:id:tanaken0515:20200802094155j:plain 引用: 心理的安全ジャーニー Slackで安全を実装する5つの手法 - Speaker Deck

f:id:tanaken0515:20200802094149j:plain 引用: 心理的安全ジャーニー Slackで安全を実装する5つの手法 - Speaker Deck

  • 「感謝」に「同様の行為を返報として約束する」という解釈もあるのか。知らなかった。
  • 協力してもらった時その相手に感謝を伝えると、相手は「自分が同じような状況になったときに協力してもらえそう」と感じる(=信じる)ということだな。
    • これはつまり「信頼」だ
  • 感謝を伝えることで「信頼」が増える
  • CREの観点だと、「サービス運営者」と「顧客」の間で感謝を伝え合う仕組みがあるとよさそう

まとめ

「チーム内の対人関係における信頼」について語られた資料をみながら「CREにおける信頼」について考えてみた。

ヒントになることがいくつかあったのでよかった。実践していきたい。

プロジェクト化とプロジェクトマネジメントは人生に活かせそう

日々人生をやっていると「自分、なにも前に進んでいないな...」と感じることがある。

お仕事は楽しくやっていて充実しているし成長も感じているのだけど、お仕事ではやらないような自分の興味分野や趣味でやってみたいことはあって、そっちがなかなか進まないよなぁという話。

モヤモヤ〜としながらも毎晩YouTubeをみたり漫画を読んだりしてだらだら過ごしてお風呂に入って寝る、という日々を繰り返していて大変よくない。*1

プロジェクト化、人生にも活かせそう

先日たまたま、関わっているお仕事現場の方(@library_fitさん)が「プロジェクトマネジメントの基礎講座」を開催してくれて、その内容が人生にも活かせそう、と感じたのでこの記事を書き始めた。

講座のスライドはこちら

この記事ではスライドを抜粋しながら、思ったことを書いていく。

「プロジェクト」とは?

f:id:tanaken0515:20200716093035p:plain プロジェクトには「目的」と「明確な始まりと終わり」がある、とのこと。

人生において「なんとなく興味がある!」とか「やりたい!」とかを割りと気軽に発言するのだけど、実際にそれを学んだり実行したり、その活動を継続するためには「目的」があった方がよさそうだなぁと思った。

まあ毎回「目的を決めなきゃ〜〜〜」と考えすぎてしまうとしんどくなってしまうとは思うけれど。目的を決めずにふわふわと何かをやることで得られる何かがあることもすごく分かるし。

ただ、ふわふわせずにしっかりと着実に前進させたい、というケースでは「目的」を決めるのは結構大事そう、と思った。

そして「明確な始まりと終わり」。これが決まっていないと、それはプロジェクトではない、という話。

  • いつになったら始まりで、いつになったら終わりなのか
  • なにをやったら始まりで、なにをやったら終わりなのか
  • どういう状態になったら始まりで、どういう状態になったら終わりなのか

この辺、人生の中であんまり考えていない or 考えていても結構ゆるい、かもなぁと。

「プロジェクト化する」とは?

f:id:tanaken0515:20200716095144p:plain

やろうとしていることに「目的」を決めて「期限」をつけること。 ふんわりとではなく、意識的に明確にこれをやることで、その物事への向き合い方が大きく変わりそう、と思った。

f:id:tanaken0515:20200716092153p:plain 人生の何かを前進させたい場合も、プロジェクト化するとよさそう。

プロジェクトの種類

プロジェクトはメンバー構成と納品の有無で大きく四つに分類される

f:id:tanaken0515:20200717071033p:plain

この分類なるほどな〜、と思った。

人生において自分個人の何かをやりたい場合は「メンバー構成 = 自分ひとり、納品 = なし」なので、左下っぽい。

自分と同じ目的を持った仲間を集めて何かやる場合は、左上かな。(メンバーがフレキシブルかどうかは状況によりそうだから左下にもなりそう)

「プロジェクトマネジメント」とは

f:id:tanaken0515:20200717072817p:plain

つまりは、プロジェクトの目的と期限を満たすためのなんらかの活動を指すらしい。

なるほど、プロジェクトマネジメントは「目的を満たし、かつ、期限を守る」ための活動なのか。

逆に(?)、特に意識せずとも「目的を満たし、かつ、期限を守る」ことができるプロジェクトであれば、プロジェクトマネジメントは必要ない、ということになるな。

それってどんなプロジェクトだろう。満たすべき目的の水準がめっちゃ低いとか?期限が極端にゆるくて、ゆっくりやっていれば終わるプロジェクトとか?

お仕事において、そういうプロジェクトってあんまりなさそうだなぁ。だからお仕事ではプロジェクトマネジメントが必要だし、プロジェクトマネージャーという職種(職位?)が存在しているのだろうな。

プロジェクトマネジメントがなくとも、プロジェクトは前に進む。しかし、スピードがあげられない。

f:id:tanaken0515:20200717084703p:plain f:id:tanaken0515:20200717084700p:plain

なるほど、プロジェクトマネジメントは「プロジェクトの迷いを減らすための活動」と捉えることができるのか。

人生に「プロジェクトマネジメント」は必要か?

これまでの自分の人生経験でいうと、多くはそもそもプロジェクト化されていない(=目的と期限が決まっていない)ケースがだった気がする。

挙げるとすれば、大学受験はプロジェクト化されていたかもなぁ。目的=志望大学の合格*2、期限=OO年3月、みたいな。
この「目的を満たし、かつ、期限を守る」ための活動ってなんだろう?と考えてみると、学校授業を受ける、とか、大学受験塾に通う、とか、それらの宿題を定期的にやる、とか、模擬試験を受ける、とか、そういうことかな。様々な不安や迷いが常にあったけど、いろんな人に相談しながらその不安や迷いを小さくしようと心がけていた気がする。特に、当時通っていた塾の塾長さんにはよく相談していて、いま思えば、塾長さんは「大学受験プロジェクト」のプロジェクトマネジメントをしてくれていたのかもしれないなぁと思った。

これからの人生はどうだろう。

人生には限りがあるし、その中でも健康に過ごせる期間は限られていると思う。その前提で、たくさんのやりたいことをやっていくためには、プロジェクトマネジメントが必要そうだなぁと思った。

まとめ

この記事を書きながら思ったことをまとめると

  • やりたいことが進まないなぁと思ったら、プロジェクト化してみる(=目的と期日を定めてみる)と確認するとよさそう
  • プロジェクト化したら、プロジェクトマネジメント(=プロジェクトの迷いを減らすための活動)をするとよさそう
  • 人生には限りがあるので、プロジェクトマネジメントは必要そう

この3つかな。

忙しさにかまけて人生を蔑ろにしてしまいがちなので、まずはプロジェクト化してみるところから、やってみようかなと思う。

*1:週40時間のフルタイムで働きつつ週10~15時間で別のお仕事もやっているので「単純に忙しくない?」という気持ちもあるんだけど、それにしても日々無駄に溶かしている時間も多くて「もっと良い感じにできそう」という課題感がある

*2:「大学に入るのは手段であって目的ではないぞ!!」みたいなことを言う人がいそう

思い出した順

最近のこととか思っていることとか。思い出した順。

もっと音楽はあっていいんじゃないか

家にずっといる。音楽あったほうが生活が彩ると思う。

作業BGMとかもそうだけど、なんか折に触れて音楽が流れたらいいなって。

電気つけたら、窓を開けたら、トイレから出たら、冷蔵庫を覗いたら、コーヒーを飲んだら

目覚ましの音も好きな音楽が流れるようにしたらよさそう

まあ最近は目覚まし使ってないのだけれど

SpotifyAPIとかを使ったらなんか良い感じにできるのかな https://developer.spotify.com/

ミステリと言う勿れ

漫画

flowers.shogakukan.co.jp

奥さんが急に買って来た、何かのアプリで数話読んだらしい

主人公の視点や物事の考え方が面白い、素敵な作品

奥さんは最近ずっと毎日「あつまれどうぶつの森」をやっていたのだけど、今週月曜から今日(木曜)までは一度もやっていない

何か思うところがあって控えているようす

あつもりを控えている反動で、漫画を買ってきたっぽい

ジャンププラスで「ヒカルの碁」も読み始めている。ヒカルの碁は自分も好きなマンガなので共通の話題が増えるのは嬉しい。

Qiita

3つ書いた

こういうのを書いてみるといかに自分が今まで適当にやっていたのかが分かって便利

まあこの記事たちも適当なところはいっぱいあるのだけど

適当にやっているのだ、ということを認識することが大事だったりすると思う

スプラ2実は引退したけど実は復帰してる

先月30歳になったので、記念にスプラをやったのだけど

見事に13連敗もして、「30にもなって何やってんだ俺は...」と完全に思ってしまったので実は引退した。

だけど奥さんがあつもりをやってるなどで、

あ、これまでニンテンドーアカウント?のファミリープランに入っていなくて、

自分と奥さんは別々でニンテンドーアカウントの支払いをしていたのだけれど、

奥さんがあつもりをやりまくっている関係で、ファミリープランにしたほうが良くない?となり、

ファミリープランだと8アカウントまで同じ金額で通信が使えるので

サブ垢つくって色々遊べるじゃ〜んという考えに至ってしまい、

結局サブ垢でスプラ2に復帰してしまった。

サブ垢ではチャージャーをマスターするぞ〜、と楽しくやっている。

実力的には、ガチマッチを始めてC-からB-飛び級できてめちゃ喜んでいる程度です

からしいことだけやってる感覚

最近のお仕事では、お金周りのことやユーザとの関係性を良い感じにエンジニアリングして行こうぜ的なこと主にやっている。

必要であることだと感じているし、割りと自分が得意とするお仕事をさせてもらっているので幸せに感じている。

一方で、なんというか「お金をちゃんと管理するのは大事」だし「最高のサービスにするためにユーザに寄り添っていくのは大事」なのだけど、

正しいことすぎる、というか、正義?みたいな物を盾?にしているような感覚もある。

この命題は真だよね、みたいな、自明だよね、みたいな、何かそういうものを淡々とやっているというか。

ほぼほぼ誰の目から見ても、第三者からみても「やったほうがいいこと」をやっているとき、

自分の価値観で自分の意志でやっているのか、単に第三者からみて自明に「やったほうがいいこと」だからやっているのか、

わからなくなるなぁ、と感じる瞬間もある。

「やったほうがいい」という結論が概ね確からしい、というものごとだけをやっているような感覚になることがある。

周りに否定されながらも自分の信じる道を行く!みたいなことをしてみたいと感じているのかも、と思ったりもする。

他にも

書こうと思っていたことがあった気がするのだけどこの辺りにしておく。

メモを書き留めているTrelloがあるのでそこからまたぽつぽつと記事を書いていこう。

読んだ: エンジニアはどのようにして技術を学べば良いのか

@genkiroid さんのブログ記事「エンジニアはどのようにして技術を学べば良いのか | /etc/motg」を読んだ。

とても参考になる記事で、忘れたくないなぁと思った。

ので、マインドマップを作った(記事に書かれていたことの実践にもなるので二鳥)。

はじめに

f:id:tanaken0515:20200512095849j:plain

この節があることで読みやすかったなぁと思う。参考にしたい。

何を学べば良いのか分からない

f:id:tanaken0515:20200512095931j:plain

目的(提供したい価値)が分かれば手段(学ぶべきこと)は自ずと見えてくる、という仮定のもと、価値とはなんなのか、学ぶ際の注意点、の話をしていた。

個人的には提供したい価値が分かっていても学ぶべきことが分からないケースはあったなぁと思うので、若干自分の考えとのギャップがあるなと感じた。

その時は周囲の人が「tanakenくんがやりたいことを実現するにはこれを学んだら良いのでは?」という話をしてくれて「あ、それだわ」となって解決した。

ただもしかしたら、提供したい価値を分かったつもりになっていた(解像度が低かった)ために手段が見えなかっただけかも、という気もするので、提供したい価値を確認してみる、というアプローチはとても良さそう。

技術書を読んでもすぐ忘れる

f:id:tanaken0515:20200512095942j:plain

マインドマップを実践してみた。「文章ではなく単語で記述」という原則をバッチリ無視したマインドマップが出来上がってしまったので、記事で紹介されているこの本を読んでみようと思った。

マインドマップ読書術 (トニー・ブザン天才養成講座) (トニー・ブザンのマインドマップ) | トニー・ブザン, 近田 美季子, 近田 美季子 |本 | 通販 | Amazon

学習する時間がない

f:id:tanaken0515:20200512095955j:plain

すきま時間を復習の時間に充てるやつ、やってみようかなと思った。

昔はテストや受験の勉強の時に、トイレの壁にノートを貼ったりしてたのを思い出した。あれもすきま時間の活用だったのだなぁ。

Rails の to_json には便利なオプションを渡せるよ

3行まとめ

Rails でDBのデータを取得して json 形式に変換したい、というシーンにおいて

  • to_jsonActiveSupport::ToJsonWithActiveSupportEncoder のメソッド
  • to_json には as_json (ActiveModel::Serializers::JSON) のオプションが渡せる
  • as_json のオプションはとても便利

単に json 形式に変換したい

Rails でのアプリケーション開発において、取得してきたデータを json 形式に変換したいシーンはままあると思う。 そういう時は to_json が便利。

例えば name に tanaken を含むユーザを取得して json 形式に変換したい時はこんな感じ。

> users = User.where('users.name like "%tanaken%"')
=> [#<User:0x00007faead5daf08
  id: 1,
  name: "tanaken0515",
  email: "tanaken0515@example.com",
  created_at: Wed, 05 Feb 2020 21:25:55 JST +09:00,
  updated_at: Wed, 05 Feb 2020 21:28:07 JST +09:00>]
> users.to_json
=> "[{\"id\":1,\"name\":\"tanaken0515\",\"email\":\"tanaken0515@example.com\",\"created_at\":\"2020-02-05T21:25:55.000+09:00\",\"updated_at\":\"2020-02-05T21:28:07.000+09:00\"}]"

便利。

モデルの特定のカラムだけ欲しい

でもこれだと User モデルのカラムを全部出しちゃって不便なことがある。例えば「この json をフロントに渡したいんだけど email は個人情報だから渡したくない。id と name だけあれば良い。」みたいな時。

実際のお仕事(主に土日にやってるほう)で似たようなシーンがあったのだけど、先日まで to_json を雰囲気で使っていた( json 形式に変換してくれるだけでしょ?と思っていた)自分は、「 select で絞ってから to_json すっか〜」というアプローチをとった。

> users = User.select(:id, :name).where('users.name like "%tanaken%"')
=> [#<User:0x00007faead64f5b0 id: 1, name: "tanaken0515">]
> users.to_json
=> "[{\"id\":1,\"name\":\"tanaken0515\"}]"

そしたらレッビューで「それ to_jsononly: オプションを指定したらできますよ〜」というコメントをいただいた。

> users = User.where('users.name like "%tanaken%"')
=> [#<User:0x00007faead5daf08
  id: 1,
  name: "tanaken0515",
  email: "tanaken0515@example.com",
  created_at: Wed, 05 Feb 2020 21:25:55 JST +09:00,
  updated_at: Wed, 05 Feb 2020 21:28:07 JST +09:00>]
> users.to_json(only: [:id, :name])
=> "[{\"id\":1,\"name\":\"tanaken0515\"}]"

なるほど便利。ありがたレビュー、大感謝太郎。

to_json ってなんなのよ

で、この to_json ってなんなのよ、というお話。調べますわよ。

まずは rails console で定義元を探してみる。 source_location が便利。

> users.method(:to_json).source_location
=> ["/path/to/project/root/vendor/bundle/ruby/2.6.0/gems/activesupport-6.0.2.2/lib/active_support/core_ext/object/json.rb", 36]

https://github.com/rails/rails/blob/9256ae8a389fd40f9e4f152737de0fb2c6059daf/activesupport/lib/active_support/core_ext/object/json.rb#L36 ここ。

to_jsonActiveSupport::ToJsonWithActiveSupportEncoder モジュールのメソッドだったのだなぁ。(# :nodoc: となっているのでドキュメントはない)

実は rails console でメソッドの中身をみることもできて便利(これは最近知った).

> users.method(:to_json).source.display
    def to_json(options = nil)
      if options.is_a?(::JSON::State)
        # Called from JSON.{generate,dump}, forward it to JSON gem's to_json
        super(options)
      else
        # to_json is being invoked directly, use ActiveSupport's encoder
        ActiveSupport::JSON.encode(self, options)
      end
    end
=> nil

さっきの例で渡しているオプション only: [:id, :name] はただの Hash なので↑の else の方に入って、ActiveSupport::JSON.encode(self, options) が動くわけですな。


さて、続いて ActiveSupport::JSON.encode(self, options) について調べる。何も考えずに以下を打つ。

> ActiveSupport::JSON.method(:encode).source_location
=> ["/path/to/project/root/vendor/bundle/ruby/2.6.0/gems/activesupport-6.0.2.2/lib/active_support/json/encoding.rb", 21]
> ActiveSupport::JSON.method(:encode).source.display
    def self.encode(value, options = nil)
      Encoding.json_encoder.new(options).encode(value)
    end
=> nil

Encoding.json_encoder がなんらかのクラスで、そのインスタンスを new して encode メソッドを呼んでる。

https://github.com/rails/rails/blob/144df5b104d042792f3fa73576d3ca9fac74fa67/activesupport/lib/active_support/json/encoding.rb#L21 この辺読むと、Encoding はすぐ下にモジュールとして定義されていて、このモジュール内の一番下に json_encoder が書いてある。

ざっくりこんな感じ

module Encoding #:nodoc:
  class JSONGemEncoder #:nodoc:
    # 略
  end
  # 略
  
  class << self
    # 略
    attr_accessor :json_encoder
    # 略
  end
  
  self.json_encoder = JSONGemEncoder
  # 略
end

となってる。

つまり Encoding.json_encoder.new(options).encode(value)
Encoding::JSONGemEncoder.new(options).encode(value) のこと。

JSONGemEncoder クラスの中身、 encode メソッドを見てみる。

GitHubで直接コード読めば良いんだけどあえて rails console でやるならこう。

> ActiveSupport::JSON::Encoding::JSONGemEncoder.new(only: [:id, :name]).method(:encode).source.display
        def encode(value)
          stringify jsonify value.as_json(options.dup)
        end
=> nil

valueas_json(options.dup) して jsonify したものを stringify するよ、ということですね、直感的ですね。

value ってなんだっけ?というと ActiveSupport::JSON.encode(self, options)self で、これは詰まり users.to_jsonusers ですわ。

なので詰まるところ

> users.to_json(only: [:id, :name])
=> "[{\"id\":1,\"name\":\"tanaken0515\"}]"
> ActiveSupport::JSON::Encoding::JSONGemEncoder.new(only: [:id, :name]).encode(users)
=> "[{\"id\":1,\"name\":\"tanaken0515\"}]"

ってこと。

to_json がなんなのかわかってすっきり。

指定できるオプションは、どこを見ればわかるのよ

to_json の正体がわかったところで、オプションをみていこう。

valueas_json(options.dup) しているので、 as_json で使えるオプションをそのまま使えるっちゅうことですな。

value.as_json は実質 users.as_json なので、rails console でみてみると

> users.method(:as_json).source_location
=> ["/path/to/project/root/vendor/bundle/ruby/2.6.0/gems/activerecord-6.0.2.2/lib/active_record/relation/delegation.rb", 85]
[28] pry(main)> users.method(:as_json).source.display
    delegate :to_xml, :encode_with, :length, :each, :join,
             :[], :&, :|, :+, :-, :sample, :reverse, :rotate, :compact, :in_groups, :in_groups_of,
             :to_sentence, :to_formatted_s, :as_json,
             :shuffle, :split, :slice, :index, :rindex, to: :records
=> nil

ほ〜ん、なるほど、 recordsdelegate されているのね。

recordsActiveRecord::Relation#records かな。こいつの返り値は Array なので、結局のところ Array#as_json を追えば良さそう。

> users.class
=> User::ActiveRecord_Relation
> users.records.class # 一応返り値のクラスを確かめてみた
=> Array
> users.records.method(:as_json).source_location
=> ["/path/to/project/root/vendor/bundle/ruby/2.6.0/gems/activesupport-6.0.2.2/lib/active_support/core_ext/object/json.rb", 152]
> users.records.method(:as_json).source.display
  def as_json(options = nil) #:nodoc:
    map { |v| options ? v.as_json(options.dup) : v.as_json }
  end
=> nil

これは Array の各要素に対して as_json をしているだけですな。

今回の場合 users の各要素は User モデルのインスタンスなので

> users.first.method(:as_json).source_location
=> ["/path/to/project/root/vendor/bundle/ruby/2.6.0/gems/activemodel-6.0.2.2/lib/active_model/serializers/json.rb", 89]
> users.first.method(:as_json).source.display
      def as_json(options = nil)
        root = if options && options.key?(:root)
          options[:root]
        else
          include_root_in_json
        end

        hash = serializable_hash(options).as_json
        if root
          root = model_name.element if root == true
          { root => hash }
        else
          hash
        end
      end
=> nil

なるほど、ActiveModel::Serializers::JSON モジュールのメソッドだったのだなぁ! そしてこれは # nodoc ではなく、しっかりとドキュメントが書かれているのである!

api.rubyonrails.org

ここに書かれているオプションは使い放題!便便便利!

オプション紹介

ドキュメントのサンプルコードをそのまま貼って眺める

まずはオプション指定なしパターン

user = User.find(1)
user.as_json
# => { "id" => 1, "name" => "Konata Izumi", "age" => 16,
#      "created_at" => "2006-08-01T17:27:13.000Z", "awesome" => true}

次に :only , :except 。良いすね。でも個人的には多分 :except は使わないかな〜。ブラックリスト方式よりもホワイトリスト方式の方が安心できるから。センシティブな情報が入ったカラムを後から追加した時に、ブラックリストに指定し忘れるとまずいからね〜。

user.as_json(only: [:id, :name])
# => { "id" => 1, "name" => "Konata Izumi" }

user.as_json(except: [:id, :created_at, :age])
# => { "name" => "Konata Izumi", "awesome" => true }

続いて :methods これ便利すな〜。

user.as_json(methods: :permalink)
# => { "id" => 1, "name" => "Konata Izumi", "age" => 16,
#      "created_at" => "2006-08-01T17:27:13.000Z", "awesome" => true,
#      "permalink" => "1-konata-izumi" }

最後に :include 、associationを引いてこれるのも便利だなぁ。

user.as_json(include: :posts)
# => { "id" => 1, "name" => "Konata Izumi", "age" => 16,
#      "created_at" => "2006-08-01T17:27:13.000Z", "awesome" => true,
#      "posts" => [ { "id" => 1, "author_id" => 1, "title" => "Welcome to the weblog" },
#                   { "id" => 2, "author_id" => 1, "title" => "So I was thinking" } ] }

3行まとめ(再)

Rails でDBのデータを取得して json 形式に変換したい、というシーンにおいて

  • to_jsonActiveSupport::ToJsonWithActiveSupportEncoder のメソッド
  • to_json には as_json (ActiveModel::Serializers::JSON) のオプションが渡せる
  • as_json のオプションはとても便利

最初に想定した分量の5倍くらいの長さになってしまった。でも勉強になったから、よしっ!

アイコンを描いてもらった

@hamayucco さんにアイコンを描いてもらった。

写真 イラスト
photo illustration

写真のわんこは、僕の奥さんの実家で飼っていたゴールデンレトリバーで、名前は「winter」。ウィンちゃんって呼んでた。

数年前に亡くなってしまったのだけど、すごく人懐っこい子で、この笑顔の写真が大好きなのでイラストにしてもらった。

自分のためだけにイラストを描いてもらう、という体験はこれまでになくて、すごく嬉しかった。

この bosyu を出したら数名の方に応募していただいて、イラストのテイストが好きだったので今回は @hamayucco さんにお願いすることにした。

僕と奥さんの要望に丁寧に対応いただいて、お気に入りのイラストに仕上がったので大満足。

@hamayucco さんは↓で「似顔絵を描いて欲しい人」を募集しているようなので興味のある方は是非。