Создание маршрутов в Discourse и отображение данных

Со временем 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 перекусов, похоже, работает :candy:

Конечно, по мере развития вашей функции и добавления сложности, вы, вероятно, не будете просто возвращать захардкоженный JSON из контроллера, как здесь; вы будете выполнять запрос к базе данных и возвращать данные таким образом.

Клиентская часть (Ember.js)

Если вы откроете браузер и перейдёте по адресу /admin/snack (без .json), вы увидите, что Discourse сообщает: «Упс! Эта страница не существует.», — это потому, что в нашем фронтенд-приложении на Ember нет ничего, что могло бы отреагировать на этот маршрут. Давайте добавим шаблон .gjs, чтобы отобразить наш перекус:

frontend/discourse/admin/templates/snack.gjs

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

  <hr />

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

И, как и на стороне API Rails, нам нужно подключить маршрут. Откройте файл frontend/discourse/admin/routes/admin-route-map.js и найдите метод export default function(). Добавьте следующую строку:

this.route("snack");

В мире Ember осталось сделать одну последнюю вещь: заставить приложение Ember выполнить AJAX-запрос для получения нашего JSON с сервера. Давайте создадим последний файл. Это будет 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 должен быть маршрутом

  • Маршрут Ember для snack делает AJAX-запрос к /admin/snack.json

  • Роутер приложения Rails говорит, что это должен быть admin_snack controller

  • admin_snack_controller возвращает JSON

  • Приложение Ember получает JSON и рендерит шаблон .gjs

Куда двигаться дальше

Я написал дополнительное руководство о том, как добавить Ember Component в Discourse.


Этот документ находится под контролем версий — предложите изменения на github.

46 лайков