NotionRubyMapping のアップデート(3) : hkob の雑記録 (158)

はじめに

hkob の雑記録の第158回目は、Faraday の取得時にハッシュのキーを Symbol にする作業を解説します。

symbolize_names: true

昨日の「おわりに」に記載したように Faraday の response 変換時に symbolize_names を true にすることで JSON の parse した後のハッシュキーをシンボルにすることができるようです。早速、この部分を下の parser_options に変更しました。

        conn.response :json
        # conn.response :json, parser_options: {symbolize_names: true}

この変更により、さまざまなテストが失敗するようになりました。当然ですね。これを一つずつ修正していきます。

WebMock のエラー表示

NotionRubyMapping のテストでは、実際に Notion API をアクセスすることはなく、WebMock を利用しています。一度、API アクセスした時の response の JSON を fixtures として取得しておき、WebMock でアクセスを偽装しています。この時、API の payload が異なると WebMock に登録されたものと一致しないため、エラーとなります。この際、テストログに登録済の stubs が registered request stubs: として出力され、ログが肥大化する問題がありました。テストのために大量の無駄なログが表示されるのは厳しいので、NetConnectNotAllowedError をオーバライドすることにしました。

具体的には spec/spec_helper.rb に以下の記述を追加しました。

module WebMock
  class NetConnectNotAllowedError < Exception
    def initialize(request_signature)
      super("Real HTTP connections are disabled. Please stub: #{request_signature}")
    end
  end
end

この結果、失敗した時のエラーは以下のような形で出力されました。失敗した URL と body だけが表示されるので、だいぶスッキリしました。

     WebMock::NetConnectNotAllowedError:
        Real HTTP connections are disabled. Please stub: PATCH https://api.notion.com/v1/pages/206ffaa277744a99baf593e28730240c with body '{"properties":{"CheckboxTitle":{"checkbox":true,"type":"checkbox"},"DateTitle":{"type":"date","date":{"start":"2022-03-14","end":null,"time_zone":null}},... (以下省略)

テストの修正

テストはこんな感じの修正になりました。 set_icon のテストだとこんな感じになります。シンボルになることでだいぶスッキリ書けるようになります。

     describe "set_icon" do
       before { payload.set_icon(**params) }
+
       context "for emoji icon" do
         let(:params) { {emoji: "😀"} }
+
         it "update icon (emoji)" do
-          is_expected.to eq({"icon" => {"type" => "emoji", "emoji" => "😀"}})
+          expect(subject).to eq({icon: {type: :emoji, emoji: "😀"}})
         end
       end

実装の修正

実装も同様に修正していきます。payload は symbol のままでも、JSON にする際には文字列になるので、問題ありません。また、各種ハッシュキーも全て symbol で設定するようにします。

     def set_icon(emoji: nil, url: nil)
       payload = if emoji
-                  {"type" => "emoji", "emoji" => emoji}
+                  {type: :emoji, emoji: emoji}
                 elsif url
-                  {"type" => "external", "external" => {"url" => url}}
+                  {type: :external, external: {url: url}}
                 else
                   {}
                 end
-      @json["icon"] = payload
+      @json[:icon] = payload
       self
     end

おわりに

記述は簡単になったのですが、流石にページの修正量が多いので、まだ全て完了しているわけではありません。まずは現状のテストが全て通過するところまで持っていきます。ただ、明日までに終わるか不明です。もし、終わらなかった場合は現在考えている FileObject の構想をまとめてみたいと思います。

hkob.notion.site