Discourse は時間の経過とともに複雑さを増しており、バックエンドの Ruby on Rails アプリケーションからフロントエンドの Ember.js アプリケーションまで、データがどのように流れ着くのかを理解することは、初心者にとって敷居が高い場合があります。
このチュートリアルでは、Discourse におけるリクエストの完全なライフサイクルを示し、独自の URL を持つ新しいページをアプリケーションに構築するために必要な手順を説明します。
まず URL から考える
機能を考える際は、常にアクセスするための URL について考えることを好みます。例えば、Discourse の開発中に最後に食べたお菓子を表示する管理機能を作るとしましょう。そのための適切な URL は /admin/snack になります。
この場合:
-
ブラウザで
/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 は正常に動作しているようです ![]()
もちろん、機能に複雑さを加えて構築を進めるにつれて、このようなコントローラーからハードコードされた JSON を返すのではなく、データベースをクエリしてそれを返すようになるでしょう。
クライアントサイド(Ember.js)
ブラウザを開いて /admin/snack(.json なし)にアクセスすると、Discourse が「Oops! That page doesn’t exist.」(おっと!そのページは存在しません。)と表示されるはずです。これは、フロントエンドの Ember アプリケーション内に、そのルートに対応するものが何もないためです。お菓子を表示するための .gjs テンプレートを追加しましょう:
frontend/discourse/admin/templates/snack.gjs
<template>
<h1>{{@controller.model.name}}</h1>
<hr />
<p>{{@controller.model.description}}</p>
</template>
そして、Rails API サイドと同様に、ルートを接続する必要があります。ファイル frontend/discourse/admin/routes/admin-route-map.js を開き、export default function() メソッドを探してください。以下の行を追加してください:
this.route("snack");
Ember 側で最後のやるべきことが一つ残っています。それは、Ember アプリケーションがサーバーから JSON を取得するために AJAX リクエストを実行することです。最後のファイルを作成しましょう。これは Ember Route になります。その model() 関数は、ルートがエントリーされたときに呼び出されるため、そこで ajax 呼び出しを行います:
frontend/discourse/admin/routes/admin-snack.js
import { ajax } from "discourse/lib/ajax";
import DiscourseRoute from "discourse/routes/discourse";
export default class AdminSnackRoute extends DiscourseRoute {
model() {
return ajax("/admin/snack.json");
}
}
これで、ブラウザで /admin/snack を開くと、ページにお菓子の詳細がレンダリングされているはずです!
まとめ
-
ブラウザで
/admin/snackを開くと、Ember アプリケーションが起動します -
Ember アプリケーションのルーターは、
snackがルートであるべきと判断します -
snackの Ember ルートは、/admin/snack.jsonに対して AJAX リクエストを発行します -
Rails アプリケーションのルーターは、それが
admin_snack controllerであるべきと判断します -
admin_snack_controllerは JSON を返します -
Ember アプリケーションは JSON を取得し、
.gjsテンプレートをレンダリングします
次のステップ
Discourse に Ember コンポーネントを追加する方法 についての続編チュートリアルを作成しました。
このドキュメントはバージョン管理されています - 変更提案は github でどうぞ。