Discourseでルートを作成し、データを表示する

Discourse は時間の経過とともに複雑さを増しており、バックエンドの Ruby on Rails アプリケーションからフロントエンドの Ember.js アプリケーションまで、データがどのように処理されるのかを理解することは、初心者にとってハードルが高い場合があります。

このチュートリアルでは、Discourse におけるリクエストの全ライフサイクルを示し、独自の URL を持つ新しいページをアプリケーションに構築したい場合に必要な手順を説明します。

まず URL から考える

機能の設計を考える際、私はまずその機能にアクセスするための URL を考えることを好みます。例えば、Discourse の開発中に最後に食べたおやつを表示する管理者向けの機能を構築したいとしましょう。それには /admin/snack という URL が適切です。

この場合:

  • ブラウザで /admin/snack にアクセスすると、「フルスタック」を使ってスナックが表示されるはずです。つまり、Ember アプリケーションが読み込まれ、スナックを表示するために必要なデータをリクエストします。

  • /admin/snack.json にアクセスすると、スナック自体の JSON データが返されるはずです。

サーバーサイド (Ruby on Rails)

まず、スナック用の新しい コントローラー を作成しましょう。

app/controllers/admin/snack_controller.rb

class Admin::SnackController < Admin::AdminController
  def index
    render json: { name: "donut", description: "delicious!" }
  end
end

ここでは、Admin::AdminController を継承することで、コントローラーを表示しているユーザーが管理者であることを確認するためのすべてのセキュリティチェックを利用できます。コントローラーにアクセスできるようにするには、もう一つだけやるべきことがあります。それは config/routes.rb に一行追加することです:

次のようなブロックを探します:

namespace :admin, constraints: StaffConstraint.new do
  # lots of stuff
end

その中に次の行を追加します:

get 'snack' => 'snack#index'

これで、ブラウザで /admin/snack.json にアクセスできるようになり、スナックの JSON が表示されるはずです。スナック API はうまく動作しているようです :candy:

もちろん、機能に複雑さを加えて構築を進めるにつれて、このようなコントローラーからハードコードされた JSON を返すことはせず、データベースをクエリしてその結果を返すようになるでしょう。

クライアントサイド (Ember.js)

ブラウザを開いて /admin/snack (.json なし) にアクセスすると、Discourse が「Oops! That page doesn’t exist.」(おっと!そのページは存在しません。)と表示されます。これは、フロントエンドの Ember アプリケーションに、そのルートに対応するものが何もないためです。スナックを表示するための .gjs テンプレートを追加しましょう:

app/assets/javascripts/admin/templates/snack.gjs

<template>
  <h1>{{@controller.model.name}}</h1>

  <hr />

  <p>{{@controller.model.description}}</p>
</template>

そして、Rails API サイドと同様に、ルートを接続する必要があります。ファイル app/assets/javascripts/admin/routes/admin-route-map.js を開き、export default function() メソッドを探します。以下の行を追加します:

this.route("snack");

Ember 側で最後にやるべきことがもう一つあります。それは、Ember アプリケーションがサーバーから JSON を取得するために AJAX リクエストを実行することです。最後のファイルを一つ作成しましょう。これは Ember Route です。その model() 関数はルートにエントリしたときに呼び出されるため、そこで ajax コールを行います:

app/assets/javascripts/admin/routes/admin-snack.js

import { ajax } from "discourse/lib/ajax";

export default Ember.Route.extend({
  model() {
    return ajax("/admin/snack.json");
  },
});

これで、ブラウザで /admin/snack を開くと、スナックの詳細がページにレンダリングされているはずです!

まとめ

  • ブラウザで /admin/snack を開くと、Ember アプリケーションが起動します

  • Ember アプリケーションのルーターは、snack がルートであるべきだと判断します

  • snack の Ember.Route は /admin/snack.json へ AJAX リクエストを行います

  • Rails アプリケーションのルーターは、それが admin_snack controller であるべきだと判断します

  • admin_snack_controller は JSON を返します

  • Ember アプリケーションは JSON を取得し、.gjs テンプレートをレンダリングします

次のステップ

Discourse に Ember コンポーネントを追加する方法 についてのフォローアップチュートリアルも執筆しています。


このドキュメントはバージョン管理されています。変更提案は GitHub でお願いします。

「いいね!」 46