前回までのあらすじ
前回の記事では、RubyのWebAssemblyポートを使いSPA(single-page application)を構築するためのパッケージを開発し、TodoMVCを移植しました。
はじめに
TodoMVCは通信を伴わずブラウザ上のみで完結するアプリケーションだったため、構築用パッケージ"Bormaŝino"は特に通信系の機能は持っておらず、jsモジュールを用いてFetch API(もしくはXmlHttpRequest等)を扱う必要が有りました。
今回はこの欠けていた部分であるFetch APIラッパー他の実装が完了し、jsモジュール等を生で扱わずとも通信を伴うアプリケーションが実現できるようになりました。また、既存のJavaScript資産を組み合わせての開発も更に容易になっています。
新たに実装した機能を扱うデモとして地理院地図を扱うアプリケーションを実装しましたので、本記事ではそのコードの要点を解説します。
デモ
コード解説
ファイル構成
.
├── js
│ ├── app.js # ブートストラップコード
│ ├── index.html # アプリケーションの外枠
│ ├── map.js # 地図表示コード
├── src
│ ├── app.rb # アプリケーションの中核 Sinatra::Baseを継承したクラス
│ ├── bootstrap.rb # Ruby側のブートストラップコード
│ ├── gsi_api.rb # 国土地理院の地名検索APIのクライアント
画面の上半分はmap.js
、下半分はapp.rb
が主な処理を担っています。
通信処理
地名検索を国土地理院のAPIで行う通信をFetch API
のラッパーであるBormashino::Fetch
で行っています。
Bormashino::Fetch.new(
resource: "https://msearch.gsi.go.jp/address-search/AddressSearch?q=#{CGI.escape(query)}",
resolved_to: callback_to,
options:,
).run
Bormashino::Fetch.new
は以下のキーワード引数を取ります。
キーワード | 対応するFetch APIの引数 | 備考 |
---|---|---|
resource | 第1引数(resource) | 必須, String |
init | 第2引数(init) | 省略可, Hash |
resolved_to | - | 必須, 応答を渡すエンドポイントのパス, String |
options | - | 省略可, エンドポイントへ渡されるHash |
Bormashino::Fetch#run
を叩くと内部ではFetch APIが呼び出されリクエストが実行されます。応答が得られるとresolved_to
で指定されたエンドポイントパスへPOSTリクエストが行われ応答内容が渡されます。
# 地名検索APIの結果が返ってきたら呼び出されるエンドポイント
post '/address_callback' do
options = JSON.parse(params[:options])
@cache.set_item(options['q'], params[:payload])
redirect to("/?q=#{CGI.escape(options['q'])}")
end
エンドポイントへは次のようなパラメータが渡されます。
名称 | 内容 | 備考 |
---|---|---|
status | 返ってきたステータスコード | 数値(をto_sしたもの) |
payload | 得られた応答内容 | 文字列 |
options |
Bormashino::Fetch.new に渡した内容をto_json したもの |
文字列 |
ページタイトル
検索した地名がページタイトルに入るようにしました。
<template class="bormashino-head">
<title><%if params['q'] %><%= params['q'] %> - <% end %>Bormaŝino GSI maps demo</title>
</template>
<template class="bormashino-head">
で囲まれた内容が<head>
へ挿入されます。react-helmetに似た機能です。
画面更新イベント
Sinatraが何らかの値を返し画面が更新された際にイベントを発生させるようにしました。このイベントを捕捉するイベントリスナーを定義すると画面更新時にJavaScriptで任意の処理を実行できます。
今回のデモでは上半分にLeafletで地図を表示しており、下半分の地点一覧が更新される度に地図上のマーカーを更新しています。
app.addEventListener('bormashino:updated', (e) => {
// 画面が更新される度に実行される
})
おわりに
既存のJavaScript資産を活用しつつRubyで大半が実装されたSPAが構築できるようになりました。
開発用のテンプレートも今回の変更を含んだgem/NPMパッケージを使用するように更新されておりますので、どうぞお試し下さい。