LoginSignup
2
1

More than 1 year has passed since last update.

Rubyで通信を伴うSPAを構築してみました

Last updated at Posted at 2022-05-15

前回までのあらすじ

前回の記事では、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パッケージを使用するように更新されておりますので、どうぞお試し下さい。

2
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
1