ForeignWeatherService は都市名でなく NYC のような都市コードを受け、['Sunny', 20] の配列リファレンスを返す。都市名→コード、英語→日本語を変換する ForeignWeatherAdapter を足し、3つのサービスを配列に入れて for ループで show_weather を呼びます。
OldWeatherAPI は変えず、has で内部に持つ OldWeatherAdapter を作る。get_weather の中で fetch_weather_info を呼び、'晴れ/25度' を split して { condition, temperature } のハッシュリファレンスに直す。新旧どちらも show_weather で呼べるようになります。
レガシーな OldWeatherAPI は get_weather ではなく fetch_weather_info で、戻り値も '晴れ/25度' という文字列。WeatherService と並べると、呼び出し側でサービスごとに書き分けるしかない。直す前に、何が食い違っているかを表で整理するまで。
都市名を渡すと天気を返す WeatherService クラスを Moo で作る。get_weather はハッシュリファレンスを返し、show_weather が整形して表示する。登録の無い都市は // で既定値に。Perl v5.36 の signatures を使い、この形が以降4回の基準になります。
Hello World から始め、URL を受け取るフォーム、短縮コードの生成、SQLite への保存、短縮 URL からの転送、入力のバリデーションと1回に1つずつ足し、Moo のクラスに分けて仕上げる全12回の案内板です。
EP テンプレートと stash で、発行した短縮 URL を見せる画面に整える。データベース接続と短縮・検索の処理を Moo の URLShortener クラスへ切り出す雛形を示し、app.pl をルーティングに絞る。全12回の振り返りと、次に足せる機能まで。
今のフォームは何でも受け付け、javascript: や data: の URL もそのまま転送先になる。Data::Validate::URI の is_http_uri と is_https_uri でスキームを確かめ、それ以外には 400 Bad Request を返して登録しません。
短縮 URL を開いたら、元のページへ自動で移ってほしい。$c->redirect_to で 302 Found を返して転送し、無いコードには 404 を返す。301 ではなく 302 を使う理由と、開発者ツールで Location ヘッダーを確かめる方法まで。
第7回で保存した URL を、短縮コードで探して取り出す。プレースホルダ付きの SELECT を prepare と execute で実行し、fetchrow_hashref で1行を受け取る。見つからず undef が返ったときは 404 を返します。
/abc123 や /xyz789 のように、コードごとに get を書くわけにはいかない。get '/:code' の1つのルートで全部を受け、$c->param('code') で取り出してログに出す。/:code を最後に定義する理由も確かめます。
入力を文字列でつないだ INSERT 文は、'); DELETE FROM urls; -- のような入力で SQL インジェクションを受ける。prepare と execute で値をプレースホルダ ? に渡して登録するスクリプトを書き、空の URL を弾く簡易チェックも足します。
URL 短縮に要る情報を洗い出し、id・original_url・short_code・created_at の4カラムに決める。short_code の UNIQUE など制約の意味を確かめ、CREATE TABLE IF NOT EXISTS を $dbh->do で実行して urls テーブルを作ります。
ハッシュ変数 %urls はメモリ上にしかなく、サーバーを止めると中身が消える。DBI と DBD::SQLite を入れ、DBI->connect で urls.db に接続して切断するまで。RaiseError と AutoCommit の意味も押さえます。
連番・ランダム・ハッシュのうち、同じ URL から必ず同じコードが出るハッシュを選ぶ。コアモジュール Digest::SHA の sha1_hex で40文字のハッシュ値を作り、先頭6文字を短縮コードにする。保存先はまだメモリ上のハッシュ変数です。
フォームの送信先 /shorten にルートが無く、ボタンを押すとエラーになる。post で /shorten を定義し、$c->param('url') で入力値を取り出して画面に表示する。GET と POST の違いもここで押さえます。