С течением времени 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 сообщает «Ой! Эта страница не существует.» — это потому, что в нашем фронтенд-приложении 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 выполнить AJAX-запрос для получения нашего JSON с сервера. Давайте создадим последний файл. Это будет 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должен быть маршрутом -
Ember.Route для
snackвыполняет AJAX-запрос к/admin/snack.json -
Роутер приложения Rails говорит, что это должен быть
admin_snack controller -
admin_snack_controllerвозвращает JSON -
Приложение Ember получает JSON и отрисовывает шаблон
.gjs
Куда двигаться дальше
Я написал дополнительное руководство о том, как добавить Ember Component в Discourse.
Этот документ находится под управлением версий — предложите изменения на github.