よもやま話β版

よもやま話を書きます。内容はぺらぺら。自由に書く。

BFSの勉強メモ

これの続き: DFSの勉強メモ - よもやま話β版

BFSとは

幅優先探索( Breadth-First Search )のこと。

BFSの例

BFSは A → B → C → D → E → F → G → H → I → J → K → L の順で探索する。 BFSは キューを利用し、最短経路を解くケースで使う。

BFSを使って問題を解く

まずはこれをやるといいよ、とオススメしていただいた問題を解いてみる。 https://atcoder.jp/contests/abc007/tasks/abc007_3

ものすごく丁寧に問題内に解き方が載っているので、ありがたく参考にしつつ書いたらACになった。 https://atcoder.jp/contests/abc007/submissions/49629732

今回の学び

  • キューの中身全部吐くまで回さないと意味がない
  • 先に埋まった手数より短い手数が後から探索されることがあるので、その時は上書きする

おまけ

abc007_3 をやる前と後に、abc317_e にトライしてみていたが、修正したことでACの数が増えた。

もっとカンタンなやつをたくさん解かないとどうしようもなさそうなのでこれくらいで…。

DFSの勉強メモ

競技プログラミングの勉強会にて、DFS について教えていただいたのでメモ。( Thanks for あのぶるさん( @thatblue_plus! お世話になっております🙏 )

グラフとは

そも、DFS というのは「グラフ」についての用語である。グラフというのは、ノード(点)とエッジ(線)で構成されている、よく見るこういうやつである。時々「木」のことを考えることがあるが、「木」とは「"連結"で"閉路"を持たないグラフ」のことを指す。

グラフの例

DFSとは

深さ優先探索( Depth-First Search )のこと。自分は木のほうがわかりやすいので、まず木で把握する。

DFSの例

DFSは A → B → E → F → J → K → G → C → D → H → L → I の順で探索する。 DFSは「大回りをしてどうなるか」等を見たい時に使い、再帰を利用するのが特徴。

DFSを使って問題を解く

改めて、以前参加して自力ではまったく歯が立たなかった https://atcoder.jp/contests/abc317/tasks/abc317_c がDFSで解けるとのことで、実装をやってみる。

好きな街からスタートして同じ街を二度以上通らずに別の街へ移動するときの、通る道路の長さの和としてありえる最大値を求めてください。

上記の説明より、まさに「大回りをしてどうなるか」を調べるということに該当するので、DFSが適当だと判断できる。再帰利用と「探索済み(seen)」を保持しておくのが肝要な様子、というのを念頭においてコードを書いたが、結果として全然ダメだった。

ACを出したものも、結局のところ過去にあのぶるさんにペアプロしてもらって書いたコード( https://atcoder.jp/contests/abc317/submissions/46458009 )をほぼ参考にしながら、なんとか書けたという状況となった。結果としてDFSを知っただけではダメだなということを痛感した…。DFSの再帰の中で何をするかというのが肝要。それはそう。

今回の学び

失敗した場合、どのように失敗しているのか、結果をちゃんとみた方がいい。 TLE が出てるということは仕組みはあってて速度の問題かなと思いこんでいたケースがあったが、改めて詳細をみたら「回答が出ない」というバグを抱えていた状態になっていたようだということに後から気づいた。AC7割、TLE3割という感じで、TLEは遅かったのではなく変なループにハマって答えに辿り着かなかったと考えたほうがよさそうだった。仕組みは合ってると思い込んでしまうと永久にTLEから逃れられないので、ちゃんと実行結果の一覧を見にいくようにする。

続き: BFSの勉強メモ - よもやま話β版

Sudoのアイコンは何故サンドイッチなのか

これは「フィヨルドブートキャンプ Part 2 Advent Calendar 2023」の2日目の記事です。 https://adventar.org/calendars/9309

Sudoのアイコンはサンドイッチのキャラクターである。やや某スポンジのキャラ を彷彿とさせるが、食物・非食物という点で明確に別物と言えるだろう。

https://www.sudo.ws/images/sudo-sandwich-logo.png

The current sudo logo, © 2019 by Mark Stillman and licensed under CCBY 4.0.

https://www.sudo.ws/about/logo/

ある日、フィヨルドブートキャンプの日報*1で「何故Sudoのアイコンはサンドイッチなのか」という疑問を見かけた。Sudoのロゴは、昔は青色の盾をイメージしたものだったが、2019/05/08 からサンドイッチのものに変更されているようだ。

ref: https://news.ycombinator.com/item?id=27569648

From 2019-05-08, the logo is some kind of sandwich

パッと調べた限り由来がよく分からず、Wayback Machine とかも漁ったが、よくよく見ると公式の /about/logo のページにハッキリと書いてあった。灯台下暗し。すべては公式にある。

ref: https://www.sudo.ws/about/logo/

It was inspired by xkcd 149.

xkcdというのは人気のあるウェブコミック(※参考:wikipedia)であり、これの149というのは以下である。

https://imgs.xkcd.com/comics/sandwich.png

ref: https://xkcd.com/149/

「サンドイッチを作って」と友人に要求したところ、拒否されるが、Sudoをつけて再要求したところ受諾された、というストーリーである。コマンドを叩いて通らなかったので、権限問題に気付いて改めてSudoをつける…というのは普段でもありがちな1コマ。xkcdの作者さん自身がエンジニアのため、こういうネタがあるらしい。

webサイト側には制作年月日の表記はなかったが、解説wikiによると2006/08/28に公開された作品のようだ。

ref: https://www.explainxkcd.com/wiki/index.php/149:_Sandwich

そも、 "make me a sandwich" というフレーズについては、1995/12/16に放映されたサタデー・ナイト・ライブというアメリカのコメディ番組が元でインターネットミームになったものとのこと。下記リンク先が詳しいので、具体内容はそちらに委ねる。

ref: https://amp.knowyourmeme.com/memes/make-me-a-sandwich

1995年のコントが、2006年にwebコミックのネタになり、2019年にロゴと化し、それを見た2023年の学習者のふとした疑問に紐づくというのは、まさしくバタフライ・エフェクトといえるのではないか。なかなかに感慨深かった。

とりあえず、改めて「なんでSudoのアイコンはサンドイッチなんですか?」と聞かれたら、これで問題なく回答できそうだ。

*1:フィヨルドブートキャンプでは、受講生のみなさんが学習したこと・考えたこと・困っていることなどを日報として書くことができる機能があります。日報はメンターがチェックしています。

Kaigi on Rails 2023 感想メモ

kaigionrails.org

Kaigi on Rails 2023 参加してきました! ありがとうございました! 2020年の開始以降、ご時世柄ずっとオンライン開催だった会ですが、満を持してのオフラインでしたね。大変楽しくセッションを拝聴させていただきました。

RoomAの様子

今回はRoomA・Bがあり、人間は分裂できないのでどちらか片方しか聴講できないという問題が発生していたのですが、聞けなかった分は後日オンライン配信のアーカイブが公開されるようなので、ぜひ拝見したいな〜と思っております。

CFP通過の倍率が今回約3倍だったとのことで「来場者の4人に1人はCFP出してるかもね」という会話があったりもしました。自分は今年出せていなかったのですが、スピーカーの皆さんの熱量を浴びて「発表っていいな〜」という状態になっているので、来年は採択の有無はさておき「CFP出したぞ!」と言えるようにしたいです。

通知アプリ

今回は以下のような機能のあるブラウザアプリが配布されており、とても便利に活用させてもらいました。

  • 運営からのアナウンス(Wi-Fi情報書いてあるの大変助かる〜)
  • 気になっているセッションのブックマーク、からのリマインドPush通知
  • QRコード読み取りで「知り合った人」を増やす

これ自体もRailsで作成されているところがドッグフーディングな感じがして最高ですね。特に「知り合った人」は話をするキッカケになったりしてとても助かりました。タグもつけられたりして面白かったです 👍

以下、つらつらと自分用のセッションメモです。

セッションメモ(Day1)

  • スポンサーLT1(mybestさん): レビュー記事をよく拝見するけどバックエンドはRailsなの実は知らなかった…!
  • スポンサーLT2(Techouseさん): かなりガッツリ、スポンサーLTとは思えないレベルのSidekiq & AWS Fargate のお話を聞けて面白かった。
  • スポンサーLT3(gifteeさん): giftee Port リリースおめでとうございます!企画からリリースまでの流れがすごく丁寧で素敵。
  • 基調講演「準備中」: @zzak さんがこれまでどのようにRubyRailsと関わってきたのかを、CI関係のTIPSを濃いめに語ってくださった。物事を開始されるときに凄まじい量・質の情報収集をされているご様子が印象的だった。「知らなければ改善できない」という言葉は金言だなと感じた。
  • Rails アプリの 5,000 件の N+1 問題と戦っている話」: 1件のN+1を解決するために、人間は予想以上に色んなところを無意識に見てるんだなということに改めて気づいた。向き合いにくい時にも、目の前のものをサッと気軽に拾えるようにしてくれるというのが素敵。『目の前にごみが落ちたら拾うじゃないですか』確かに。
  • Async Gem で始める ruby 非同期プログラミング」: Async、Fiber、FiberScheduler のあたりの基礎知識があまりなかったので、検索しつつ拝見。大事そうな説明が時間の都合でスキップされていたご様子だったので、改めて資料をじっくり読みたい。
  • Exceptional Rails」: 正常系/準正常系/異常系のエラーの取り扱い方法についての丁寧な解説。Rails wayに沿ってうまく乗りこなしたい。初学者の方でもこのあたり悩まれるケース多いと思うので、説明の時の参考として紹介したい。
  • 初めてのパフォーマンス改善〜君たちはどう計測す(はか)るか〜」: 徹底して計測に基づいて一歩一歩改善していく過程が素晴らしい。また、PullRequestに "コードにしなかったこと" も合わせて全てまとめるという点もかなり重要。自分はちょっと徹底できていないところがあるので見習っていかねば。
  • Simplicity on Rails - RDB, REST and Ruby」: RESTful と DB の違いについて初学者の方に質問された時にうまく言語化できなくて詰まる場合があるが今後はこの発表見てね、とお伝えするのが良いかも。ログイン/ログアウトを sessions#new, #create, #destroy とするのがcoolというのは言われて気付いたが確かに素晴らしい。
  • Turbolinksアレルギー患者に捧げるTurbo & Stimulusでの時短実装術」: 自分もTurbolinksに振り落とされてやや苦手意識はあったが、怖くないよ〜〜〜とのことで上手くHotwireと付き合っていきたいなという気持ちになった。ココだけ使いたい、というレベル感でVueやReactを入れるのはやっぱりちょっとツラいので…。
  • 定数参照のトラップとそれを回避するために行う2つのこと」: 定数が心配なときは先頭 :: で回避しがちだったので、改めてどういう仕組みかのおさらいとさせてもらった。自分で定義するときは役割明確にと思い重複を避けるが、gemで利用されている定数をうっかり参照してしまう、はありそうなのでもし似たような問題を踏んだらこの発表を思い出して回避!
  • Active Record クエリクイズ」: Rubyコミッターでもあるpockeさんからのクイズということで、自分もかなり身構えて裏読みを試みましたが、シンプルに負荷高そうな方が正解な4問だった。ActiveRecordがデザインしてくれているカタチに素直に乗っかって使っていきたい。to_sql はいいぞ。

セッションメモ(Day2)

  • 事業の試行錯誤を支える、コードを捨てやすくしてシステムをシンプルに保つ設計と工夫」: ほぼ似てるからいいか、でテーブルを共通化して機能を捨てづらくすると後々ツラい。やはり機能を持ったままにするとメンテコストもあるので、素早く捨てられる状態を維持するのは大切。閲覧側にifを書きたくなったらテーブルごと分ける機運の兆し、というのは覚えておきたい。
  • Fat Modelを解消するためのCQRSアーキテクチャ」: CQRSアーキテクチャは未体験なので大変勉強になった。具体の実装としてUseCase/Query/Commandをうまく責務を分けて使うのはややコツが必要そうに感じた。でもうまくやればテストも分かれるしスッキリするな。Userモデル周りとかFatになりがちなのでそこだけ適用するとかアリかな?
  • E2E testing on Rails 2023」: ずっとCapybaraさんにお世話になってぬくぬくしていたので、Playwrightがそんなにシェアを伸ばしていたのは知らなかった。グラフで具体的に見ると衝撃。かなり速くなる様子なので、どこかのタイミングで触る機会を模索したい…。さっと入れたら動くかな?
  • 自分の道具を自作してつくる喜びを体感しよう、Railsで。〜 4年続いたPodcastを実例に〜」ゆるふわPodcastのいちリスナーとして興味深かったし、聴講者へ「自作サービスって良いなぁ」という気持ちを植えつける、侵蝕性の高いエモ発表だった。趣味と実益を兼ねたサーバを自由に運用…いいなぁ…なんか自分もやりたいなぁ。なんかすっごく眩しかったです。
  • ペアプロしようぜ 〜 3人で登壇!? 楽しくて速いペアプロ/モブプロ開発 〜」お揃いTシャツの3人、アクの強いAI挿絵、気合の入ったマイクパフォーマンスと見所が特盛。インパクトだけでなく、ペアプロの重要性をちゃんとデータで示してデモをきっちりやり遂げるのが流石。デモ中の何気ないやりとりの中に沢山のペアプロのコツが溶け込んでいて、百聞は一見に如かずの通り、大変参考になった。
  • Railsアプリにパスワードレス認証を導入した知見」: パスワードレス認証は、自分がいちインターネット民として生活しているなかで時々出会いますが、そういえば調べたことなかったのでwebauthn(gem)があると言うこと自体を知れたのが収穫。mac+firefoxで問題があるなどは自分で試して後で泣くより事前に知っておくと大変助かるので、有益情報だった。
  • コードカバレッジ計測ツールを導入したらテストを書くのが楽しくなった話」: テストコードを書く、という行動の促しのために、可視化(SimpleCov導入)だけではダメで、「ついでに書こう」という啓蒙でカバレッジ率が上がったとのこと。物事を進捗させるには導入するだけではなくアプローチの工夫もセットで必要なんだな〜ということがよくわかるエピソード。あと恥ずかしながら C0 などの概念を知らなかったので今後使っていきたい。
  • スポンサーLT4(pixivさん): Railsでお持ちの関連サービスについて、igaigaさん主治医のプロダクト健康診断を受けているとのこと。最新で偉い!!!
  • スポンサーLT5(スタメンさん): mainブランチに追従しているとのこと。こまめにやればそれは確かに日常ではあるが、言うは易し行うは難し…すごい。
  • スポンサーLT6(スマートバンクさん): B/43 は自分も活用していて大変お世話になってます! 規制準拠に応じてRails・Goの環境で切り分けられているとのこと。
  • 基調講演「A Decade of Rails Bug Fixes」: @byroot さんによるRailsのバグ解決に関するエピソード。なぜバグが発生したのかを徹底的に深掘り調査されていく過程にとても感銘を受けた。また、最終的にmergeを目指すにあたって、他者への丁寧な説明の大切だという点も盛り込まれていた。「コミュニケーションは大事。ナイスで愛想がいい。正しいよりも重要。」

Kaigi Effect

良い発表を浴びると色々やってみたいことが増えますね! 自分の元気度と相談しながらですが、色々とトライしていきたいです。

  • 来年スタッフ業やってみたい旨をお伝えする(済)
  • conference-app の機能で気になってる点があるのでPullRequest出してみようかな(考え中)
  • ブログ再始動 ※隔週くらい?
  • 来年のCFP提出を目指す

大江戸Ruby会議10で「生活発表」聴いてきた

「大江戸Ruby会議10」に参加しました。良き体験の記録。 https://regional.rubykaigi.org/oedo10/

予備知識

上記の通り、「大江戸Ruby会議」とは Asakusa.rb による "生活発表会" である。"技術"という制約が外れた(?) Rubyist たちの"生活"が覗けるユニークな会となっている。会場は浅草にある「雷5656会館」。確かコロナ禍前(第9回)に1度参加したことがあって、うろ覚えだったがスムーズに到着できた。ちなみに、会場名にかけて「3000円」の参加チケットとは別に「5656円」が準備されていたりする。

全体の感想

生活発表会なので、Rubyの話題は薄めに出たり出なかったりというレベルの存在感なのだが、全体的にテーマ選びや言葉尻の端々に「プログラマーっぽさ」が滲み出ているのがユニークだ。

みなさんが、発表が成立するくらい打ち込んできたものを持っている、ということ自体が眩しかった。個人的なここ数年の悩みのタネが「趣味の類を継続できない」ことなので、会から新しい刺激をもらって帰ってきた今、何かちょっとずつでもいいから取り組んでみたいと思っている。この気持ちの可用性を保っていきたい。

発表聞いたメモ

  • Days of struggle as a Cop : copをやったことがある、という言葉の解釈に一瞬戸惑う会場はおそらくふーがさんの狙い通りだったのだろう。オフラインのみだからこそのお話ありがとうございました!
  • 造って学んだ発酵食の世界 : パンと酒の共通点、確かに「発酵」ですね…。将来はエンジニアになるんですけど、という前置きに快諾をくれる世界に素敵な空気を感じました。酒造りの時期にRuby造りというのは浪漫がありますね〜。
  • 観る将、指す将、TyP 〜時を越えた将棋指しの魅力〜 : TyPって何だろう🤔 と思っていたら豊島将之(とよぴー)さんのことでした。自分は将棋の指し方は全然分からんのですが、棋士の方のエピソードは惹かれるものが多いですね。チラッとwikipediaをたぐったら幻の△4二角の話*1とか載っていてうっかり読み込んでしまいました。ドラマだなぁ…。
  • 朝会 : 「おはようございます」「テンション低いですね」から始まり「今日も一日がんばりましょう」で〆、まさしく朝会フォーマットを覗き込んでいるようで大変面白かったです。podcastの公開収録かな…?
  • YouTubeチャンネルを支える技術 : 日付だけで笑える回路、自分にも入ってました。後から10/15の回*2を拝見したら、まだ会の受付開始を10時だと思っているやんちゃさんが残っていて、vlogってすごいなと思いました。そしてやっぱり毎日これを続けられているということがすごい。可用性(1)。
  • 継続的 #RubyMuscleMixin 実践入門 : トレーニングに MTBFMTTR を適用するの納得感がすごかったです。自分もいま1年くらいランニング*3をしていますが、週1・やむを得ない用事とかの日は無理にしない・連続で出来なくても気にしない、出来る時は必ずやる…で続いているように思います。「"連続"ログインを考えない」のは実感として超大事。可用性(2)。
  • Hanamiを支える技術 2023 : 火気厳禁な "川" でいかに 🍶(熱燗) を楽しみ続けるか、という話。背負われていたデカい登山用?カバンから、電源 と 🍶 と あっためるマシン が出てきて、本気度と🍶にかける情熱を感じました。さすがです。可用性(3)。
  • IRB Committers and The World : 仕事のデバッグからプライベートのカンタンな四則演算まで、あらゆるシーンでIRBにはお世話になっております。さらにサジェスト機能が強力になっていくとのことで大変ありがたいです。引き続き何卒よろしくお願いします…!!!
  • その昔島根で起きたこと : Rubyの聖地・島根県松江市 のNaClさんの立場から観測されたRuby昔話、面白かったです。Ruby Association 発祥の図など、これまでにつながるRubyの歴史を垣間見れました。Rubyの試験ちょっと興味あるんだよな…受けてみようかな…。
  • 『Rubyメソッドかるた』王者への道 〜万葉チームのガチな取り組みを大公開〜 : 万葉さんがかるたに縁深いということは初めて知りました。Rubyメソッドかるた、手元にありますが、決まり字の観点から整理すると「ひきすう〜」で始まるのが多いのですね。「挑戦者はいますか? :)」から王者の風格 👑 を感じました…絶対勝てない…w
  • Yet Another Red Gem : 猫廼舎オーナーogijunさんによる「赤い宝石」= コーヒーの実 のお話。コーヒーの実が赤いということをそもそも知らず、液面のリングのお話など、コーヒーの世界の浪漫を垣間見ました。いつも作業用にインスタントばかりなので、たまには良い珈琲をお店で飲みたいなぁ。猫廼舎さん、現在は不定期営業とのことで、配信情報*4を要チェックですね。
  • WEB+DB PRESSと私 : 2023年夏に隔月誌としては休刊となった「WEB+DB PRESS」編集長の稲尾さんによるお話。最初はApacheRubyの読み方もままならなかったとのことですが、GitHubでPullRequestやissueをフル活用してエンジニアに執筆させる方式にされていたり、イベント懇親会("著者の狩場"…)にぷらぷらされるなど、現場に常に在ることを徹底されているのがすごかったです。エンジニアのすぐそばにいてくださった稲尾さんの姿勢が「WEB+DB PRESS」にも反映されたからこそ、愛される雑誌になったのだなぁと感じました。そしてすごく気になったので「日本語の作文技術」*5文庫をポチ。

花やしき

なんと懇親会は花やしきを貸切とのことで、人生初 && 豪華なUserExperienceをさせていただいてしまいました。

花やしき貸切
うわーーーほんとに貸切ってなってる すごい

誰も利用していない花やしきアトラクション
誰もいない…! ※このあとRubyistたちとかお子さんが乗って遊ぶ

8個のアトラクションが稼働していたのですが、お子さん連れご家族とご一緒させていただき、全部制覇できました。 ステージで大人たちが真剣にけん玉に取り組む姿が印象的でした。

良きエネルギーを充電させていただきました。来週10/27-28は Kaigi on Rails 2023、楽しみです!

*1: https://ja.wikipedia.org/wiki/真部一男#幻の妙手△4二角

*2: やんちゃクラブ 2023/10/15 「もっと早く始めていたとてこうなっていた」 https://youtu.be/eNT6P6RZ068?si=aqrCVhsqzJOgqsn6

*3: 3〜4kgくらい痩せました✌ たぶん走るの止めたらまたすぐに太る

*4:猫廼舎さん https://twitter.com/cafenekonoya

*5:https://www.amazon.co.jp/dp/4022618450 【新版】日本語の作文技術 (朝日文庫) 著:本多 勝一

SwitchBotAPI を使う・再(v1.1)

よくAPIを見ていたらv1.1とあったので、v1.1でちゃんとやりたいなと思ってリトライ。 最新は公式を読んでください。 https://github.com/OpenWonderLabs/SwitchBotAPI

アプリを更新

SwitchBotのアプリがまず古すぎたので(V4.5.0だった…すみませんズボラで…)、ちゃんと更新。2023年10月時点でiOSアプリはV7.7。更新したら登録してた設定が全部消えたと思って一瞬絶望したが、ログアウトしてただけだった。ログインしたらちゃんと復活した。

リクエストに必要な値を準備する

APIがv1.1になったことにより、リクエストのために必要な値が追加で増えたので、準備していく。

tokenとsecret

アプリの 設定 > 開発者向けオプション を10回連打で出てくる「開発者向けオプション」に、「トークン」と「クライアントシークレット」の2種類の文字列が表示されるようになった。トークンはアプリ更新前後で変更がなかったが、クライアントシークレットを今回新しくゲットした。

timestamp(t)

13桁のタイムスタンプが必要とのこと。これはUNIX時間(ミリ秒)のこと。
GitHubのサンプルにある t = 1661927531000 は、UNIX時間の解釈でいうと 2022/08/31 15:32:11(JST) となる。
参考: https://ja.wikipedia.org/wiki/UNIX時間

nonce

nonceとは何かをちょっとよくわかってない状態から開始。ランダムに生成するワンタイムの暗号トークンのことを指し、自由に決めてよいものと解釈した。

signを生成

公式APIを参考にsignを生成する。自分はRubyが好きなのでRubyで試みる。以下たくさん参考。無事取れた!

require 'securerandom'
require 'base64'
require 'httpclient'

TOKEN = 'xxxxx...'
SECRET = 'xxxxx...'

t = (Time.now.to_i * 1000).to_s
nonce = SecureRandom.uuid
sign = OpenSSL::HMAC.digest('sha256', SECRET, TOKEN + t + nonce)

header = {
  'Authorization' => TOKEN,
  'sign' => Base64.strict_encode64(sign),
  't' => t,
  'nonce' => nonce,
}

client = HTTPClient.new
res = client.get('https://api.switch-bot.com/v1.1/devices', header: header)
puts res.body

#=> {"statusCode":100,"body":{"deviceList":[{"deviceId":"D7B...","deviceName":"ハブミニ AD","deviceType":"Hub Mini","hubDeviceId":"...."},...] }, "message": "success"}

余談: SwitchBotサーバ側、Headerのパラメータが先頭大文字だと受け入れてくれなかった件

当初、Rubyの標準ライブラリ net/http で実装していたが、うまく返事を得られなかった。

uri = URI.parse('https://api.switch-bot.com/v1.1/devices')
http = Net::HTTP.new(uri.host, uri.port)
http.use_ssl = true

req = Net::HTTP::Get.new(uri)
req['Authorization'] = token
req['sign'] = Base64.strict_encode64(sign)
req['t'] = t
req['nonce'] = nonce

res = http.request(req)
puts res.body
#=> {"message":"Unauthorized"}

Rubyで生成したsignを、サンプルにあるJavaScriptのコードに適用すると使える…という状況だったためかなり頭を抱えていたが、調べた結果、次のようなことがわかった。

  • net/http では、ヘッダーフィールド名の先頭を大文字に変換する。
  • SwitchBot API では、ヘッダーフィールド名を先頭大文字にしたもの ( Sign, T, Nonce ) は受け付けていない(らしい)。
    • ゆえに、net/http を使って SwitchBot API を叩いても受け付けてくれない。
  • おまけの気付き: 1度認証すると数十秒くらいは Authorization (token) しか見ずに返事をくれている気がする。
    • jsサンプルコードで 200 を得てから Rubyの動かないコードを動かすと 同じ200 をしばらく返してくれる。

今回は問題解決のために net/http の利用を諦めて、httpclient を使ったところ、無事リクエストを成功させることができた。

参考:

デバッグの様子(net/http)

# net/httpの様子をチェック

uri = URI.parse('https://api.switch-bot.com/v1.1/devices')
http = Net::HTTP.new(uri.host, uri.port)
http.use_ssl = true
http.set_debug_output $stderr # 標準出力に出す

req = Net::HTTP::Get.new(uri)
# …略…

opening connection to api.switch-bot.com:443...
opened
starting SSL for api.switch-bot.com:443...
SSL established, protocol: TLSv1.2, cipher: ECDHE-RSA-AES128-GCM-SHA256
<- "GET /v1.1/devices HTTP/1.1\r\nAccept-Encoding: gzip;q=1.0,deflate;q=0.6,identity;q=0.3\r\nAccept: */*\r\nUser-Agent: Ruby\r\nHost: api.switch-bot.com\r\nAuthorization: xxxxx...\r\nSign: xxxxx...\r\nT: 1696770306000\r\nNonce: 34523524-e0a1-406d-bb20-f2dfcc2f0155\r\nConnection: close\r\n\r\n"
-> "HTTP/1.1 401 Unauthorized\r\n"
-> "Date: Sun, 08 Oct 2023 13:05:07 GMT\r\n"
-> "Content-Type: application/json\r\n"
-> "Content-Length: 26\r\n"
-> "Connection: close\r\n"
-> "x-amzn-RequestId: ae44ece8-bd88-41fd-8842-2c12caafa200\r\n"
-> "x-amzn-ErrorType: UnauthorizedException\r\n"
-> "x-amz-apigw-id: Me9YoEy3oAMEeIg=\r\n"
-> "\r\n"
reading 26 bytes...
-> "{\"message\":\"Unauthorized\"}"
read 26 bytes
Conn close

デバッグの様子(httpclient)

# httpclientの様子をチェック
client = HTTPClient.new
client.debug_dev = STDOUT # 標準出力に出す
res = client.get('https://api.switch-bot.com/v1.1/devices', header: header)
puts res.body

= Request

! CONNECT TO api.switch-bot.com:443
! CONNECTION ESTABLISHED
GET /v1.1/devices HTTP/1.1
Authorization: xxxxx...
sign: xxxxx...
t: 1696770516000
nonce: 90c09bc6-08b1-4078-b560-241a4c428e87
User-Agent: HTTPClient/1.0 (2.8.3, ruby 3.2.1 (2023-02-08))
Accept: */*
Date: Sun, 08 Oct 2023 13:08:36 GMT
Host: api.switch-bot.com



= Response

HTTP/1.1 200 OK
Date: Sun, 08 Oct 2023 13:08:37 GMT
Content-Type: application/json
Content-Length: 543
Connection: keep-alive
x-amzn-RequestId: 32b88a02-9b34-4a76-a4d4-73916e2ca52b
x-amz-apigw-id: Me95VGk7IAMEh5Q=
X-Amzn-Trace-Id: Root=1-6522a9d5-491163743186f65919874a15;Sampled=0;lineage=c8c2b0f2:0|bf95bacf:0

旅道楽の記録・2023松本編

RubyKaigi2023で松本に行って美味しいものをたくさん食べ、素敵なものをたくさん見たので、備忘録します 😋
※技術話は何もありません! RubyKaigi2023のまとめはこちら→ RubyKaigi2023備忘録 - よもやま話β版

BEER TAP HONMACHI (day0)

tabelog.com

到着した時刻がすでに前夜祭系には参加できない感じのタイミングだったので、夜時間を持て余していたところ、エモリハウスメンバーのぷぽさん、Ossan2goさんに拾っていただいて「BEER TAP HONMACHI」へ。すでにRubyistがたむろして談義が発生しており「あっ RubyKaigi はじまってる〜!」と思いました。

メニュー画像
長野みなみ風ビール MUTYUU(霧宙)をいただきました

MUTYUU

自分はアルコールを量飲めないので一杯だけじっくりいただきましたが、フルーティーな味ですごく飲みやすかったです。

信州ゴールデン新館 (day0)

new-concept-resort.jp

お酒屋さんは早めに閉店とのことで、本格的にお腹を満たすため「信州ゴールデン新館」へ。やはりRubyistの集いが見受けられるなかで、ご当地グルメとして「馬刺し」と「山賊焼き」をいただきました。

馬刺しの画像
馬刺しが有名とのこと。不思議な食感…これがいわゆる「たてがみ」?

山賊焼き
山賊焼き、衣がザクザクしていてとても美味しかった。手前に写っていた馬刺し皿は食べ尽くしちゃってたのでカット

栞日 (day1)

sioribi.jp

会場にほど近い場所にある、雰囲気がとても良い本屋さん・兼・喫茶店とのことで、朝食をいただきました。個人的には本も好きなので何の予定もなければゆっくり過ごしたいと思える空間でしたが、重要なイベントデーだったので、朝ご飯のひとときを過ごすのみで慌ただしく出てきてしまったのが少々心残りです。 美味しいコーヒーとトーストをいただいていると、続々Rubyistがやってきたので、この好機を逃してなるものかと思い開場前フライングでしたが、サイン本をゲットさせていただきました!

RubyKaigiのこと考えていたらコーヒーとトーストの写真を確保し忘れておりました。悔やまれる。

そば処 たかぎ (day1)

e-takagi.net

前日夜に「あっ、半袖で3日間過ごしたら風邪をひく」ということに気付き、昼飯時は上着を購入するために単騎でユニクロなどに行っておりました。この際、せっかく長野に来たからには蕎麦をたぐらねばならぬと思い、会場から距離があればハラペコRubyistたちの波を避けられるかもという狙いの位置どりのお蕎麦屋さんに入りました。

「そば処 たかぎ」入口
一階はお土産屋さん、二階がお蕎麦屋さん

蕎麦と天ぷら 良いですね すごく良い

ああ、良い蕎麦がきた…。気持ちはすっかり井之頭五郎です。人と食べるご飯ももちろん好きですが、土地の名物とひとりで向き合う時間もなかなかオツなものです。いやぁ、美味しかったなぁ…。

配布されたバウチャーが利用できたので、ありがたく会計時に使わせていただきました。入店直後はそこまで混雑の波が来てないと思っていましたが、時間が経つごとにゾロゾロとRubyKaigi組がやってきたので、わぁ、街が1000人を一気に受け入れるって大変だ…! という感想を抱きました。松本市の皆さん、本当にありがとうございました…!

菊の湯 (day1)

visitmatsumoto.com

朝食をいただいた「栞日」と同じオーナーさんが経営されているお風呂屋さん「菊の湯」。昔ながらの黄色桶のある湯屋の風景がありつつも、ステッカーが売ってたり、ハーブ水のサービス(母の日関連)をいただいたりなど新しい感性で運営されている空気を感じました。地元の方ももちろん通われています。カランからお湯を出すやりかたが分からなくて困っていたら、優しい雰囲気の地元のおばあさまに助けていただきました。その節はお世話になりました!ステキなお湯屋さんでした〜♨️

「菊の湯」外観・夜
良いお湯でした〜

珈琲茶房かめのや (day2)

tabelog.com

入れるモーニングのお店を求めて、会場からやや遠ざかる方向に足を伸ばし「珈琲茶房かめのや」へ。店名にあるように珈琲の種類が豊富で迷いましたが、自分は浅煎りの「信州林檎コーヒー」とトーストをいただきました。

「珈琲茶房かめのや」外観
レトロ純喫茶の佇まい

コーヒーとトースト
季節のジャムはあんずでした。美味しかった!

ガラス戸の向こうに坪庭が見える
雰囲気が最高なんですよ

ガラス戸越しに坪庭を見ながら、純喫茶の空気感のなかで味わうモーニング…話題はもちろんRubyKaigiのセッションについて。思い出深い時間になりました。

DOON食堂 印度山 (day2)

www.shokudoindoyama.com

偶然にも高専時代の部活の先輩と10年ぶりくらいにエンカウントしたので、お昼をご一緒させていただきました。 カレーがサーブされると、店主さんご自身が席まで来てくれて、食べ方を教えてくれました。日本の良くあるカレーや、でかいナンがついてくるインドカレーはもちろん食べたことあるのですが、まだ食べたことない「カレー」ってあるんだなという気付きがありました。 店主さんが北インドのほうのご出身だそうで、これはお母さんのカレーなんだ、それをみんなに食べて欲しいんだ。とおっしゃっていたのがとても印象的でした。

「松本はしご横丁」入口
ちょっと入り組んだところにあって、一人では来れなかったと思う…。

銀の仕切り付きプレートに盛られたカレーセット
初めて食べた北インドのカレー。めちゃめちゃ美味しかった…!

白くて丸いのはナンではなく、薄いパリパリしたおせんべい。ちょっとずつ割ってふりかけのように混ぜるとのことで、食感がすごく面白くなりました。ヨーグルトもデザートではなく混ぜ食べ用のソースのひとつで、合わせるとカレーに酸味が加わってエスニックな美味しさを感じました。このヨーグルトかけるのが一番好きかも…。左上の丸っこいものが本当のデザートで、後から調べたところによると「グラブジャムン」と呼ばれるものらしく、シロップ漬けドーナツらしいです。めちゃくちゃ甘くて食べきれず、半分だけ齧る結果となりました(えーんすみません!)。

先輩とは猫とゲームの話ができたしお元気そうで何より〜またどこかのRuby会場でお会いしましょう! 追伸: 自分もティアキン始めましたが、はじまりの島をまだ出ていません。クリアできるのはいつになるやら。

城町ろばた 縁 (day2)

blog.nagano-ken.jp

RubyKaigiまとめにも書きましたが、WNB.rb の方々とのご飯会でした! 英語力の無さを痛感した諸々の出来事の印象がすごすぎて、せっかくすごいウニを注文したのに写真を撮るのも忘れてしまいました。ウニ、凄かったです。ウニが何たるかを伝えるために検索で画像を出して見せたり、「アレルギー」という単語の実際の発音は「アレジー」に近い(Allergie)ということを知りました。なるほどな…! RubyKaigi後、ラジオ英会話 と Duolingo を進めています。とりあえず成果より先に習慣付けから…と思い、本当にちょっとずつですが。これが My Ruby Kaigi Effect …。

cucinetta にし村 (day3)

cucinishi.exblog.jp

今回のRubyKaigiで出会ったミシェルとお昼を求めてフラフラしたところ、素敵な洋食屋さんに辿り着きました。バウチャーを使えるよという掲示を(この3日間のために!)してくださっており、助かりました。

「クチネッタ にし村」外観
バウチャーの貼り紙をしてくださっていた

たけのこのリゾット

たけのこのリゾット、とても美味しかったです。ミシェルとちょっとずつシェアしてパスタも味わえました。複数人でランチに行くとシェアできるのがいいですね!Thanks, Mish! ❤️

CAFE SWEET 縄手本店 (day3,4)

www.sweet-bakery.co.jp

松本滞在の中で唯一リピートしたお店 CAFE SWEET。創業100年越えの歴史のあるカフェとのことですが、雰囲気が洗練されていてむしろ新しさを感じました。

CAFE SWEET の看板
店名表記・メニュー表記から大正浪漫を感じる…!

朝早くからオープン(土日の営業は朝8:00〜)していて助かりました。また、朝からボリュームのあるメニューが注文できました。朝食べる派なのでペロッと完食しました。

ワンプレートにサンドイッチとチップス、ラテ
サンドイッチにチップスがついてくるスタイル。美味! (day3)

ピザトーストも豪華〜分厚い〜〜 (day4)

なわて通り

www.nawate.net

松本をうろうろする中で特に目をひいたのは、カエルがシンボルになっている「なわて通り」でした。あまりゆっくり見ている時間はなく、ご飯屋さんへの行き帰りに通りすがるのが精一杯でしたが、風情ある軒並みの通りを歩いているだけで気分は最高でした。

なわて通りの街並み
風情ある軒並み

川沿いに位置している。爽やかな画だ…

街灯にあしらわれたカエル
カエルがシンボルらしい

カエルの石像(1)
ここにもカエル

カエルの石像(2)
ここにも

めちゃデカなカエルオブジェ

どうやら昔はこのあたりにたくさんカエルがいたのでシンボルになったようでした。愛されてるね〜。

松本城 (day4)

www.matsumoto-castle.jp

せめて帰る前に松本城を見たいと思い、たまたま帰路が同じになったこたつさんに同行してもらい松本城を観光! 黒い城、迫力がありました。また、場内の急な階段が印象的でした。古いお城がそのまま残っていて、その中を拝見できるというのはすごいことですね。400年前はこのお城の中を当時の人たちが実際に使っていて、この急な階段の上り下りをしていて、また戦いに備えた設備のなかで当然実戦を想定して暮らしていたのだなぁと遥か昔のことを考えるとなんだかしみじみしました。ロマンだなぁ。

松本城 with 白鳥

おきな堂(day4)

okinado1933.com

こたつさんと最後の松本グルメにと、川沿いを歩きつつ「おきな堂」へ。店内は創業昭和初期の風情が残っていて、すごくグッときました。デミグラスオムライスもすごく美味しかったです。

卵がしっかり焼いてあるオムライス。最高。

こたつさんとはエモリハウスメイトでしたが、開催中はスタッフ業でお忙しそうであまりお話しできておらず…。最終日ではありましたが松本城と昼ごはんをご一緒できて凄く楽しかったです! 帰りの電車でオススメしてもらった漫画の1巻をうっかり読んだら止まらなくて案の定睡眠不足をやらかしました。どうしてくれるんですか!!(※自業自得) またぜひオススメしてください!!

ありがとう松本

記事を書いてる間に1ヶ月くらい経っちゃいましたが、松本で出会った素敵なものについて書き留めておかなければと思っていたので、なんとか完遂出来て良かったです。行く前は蕎麦をめちゃくちゃ食べるぞと思っていたのですが、振り返ったら実は1回しか食べてなかったです。観光的な意味では若干不完全燃焼なところがあるので、機会を見つけてまた蕎麦をたぐりに行きたいです。ありがとう松本!