Структура Yesod-проекта: базовая конфигурация
Приветствую!
После первого знакомства с Yesod пришла пора заглянуть внутрь нашего проекта. Должны же мы узнать, что сделала команда yesod init
, не так ли? Давайте же заглянем в корень:
Application.hs
Foundation.hs
Model.hs
Settings.hs
devel.hs
webhs.cabal
Import.hs
Handler/
config/
messages/
templates/
Settings/
app/
deploy/
dist/
static/
test/
yesod-devel/
В этой заметке мы рассмотрим содержимое одного-единственного каталога, config
. В этом каталоге содержатся базовые конфигурационные файлы, без которых приложение категорически откажется работать.
Вот содержимое, созданное по умолчанию:
favicon.ico
robots.txt
postgresql.yml
keter.yml
models
routes
settings.yml
Полагаю, назначение файлов favicon.ico
и robots.txt
вопросов не вызывает, не правда ли? С файлом postgresql.yml
вы уже познакомились, когда настраивали параметры доступа приложения к Postgres.
Сетевая конфигурация
Вглянем на содержимое важного файла settings.yml
:
Default: &defaults
host: "*4" # any IPv4 host
port: 3000
approot: "http://localhost:3000"
copyright: Insert copyright statement here
#analytics: UA-YOURCODE
Development:
<<: *defaults
Testing:
<<: *defaults
Staging:
<<: *defaults
Production:
#approot: "http://www.example.com"
<<: *defaults
Помните, в прошлой заметке я упомянул о том, что приложение можно запустить не через yesod devel
, а непосредственно? И там упоминались четыре возможные окружения: Development
, Testing
, Staging
и Production
. Полагаю, теперь, когда вы увидели содержимое файла settings.yml
, всё встало на свои места: для каждого из окружений мы можем задать свои сетевые параметры. Например, можно переопределить значение параметра approot
, чтобы различные версии нашего приложения ассоциировали себя с разными URL-ами, и то же самое можно сделать с параметрами host
и port
. Вот возможный результат:
Default: &defaults
host: "127.0.0.1"
#analytics: UA-YOURCODE
Development:
port: 3001
approot: "http://dev.my-service.com"
<<: *defaults
Testing:
port: 3002
approot: "http://test.my-service.com"
<<: *defaults
Staging:
port: 3003
approot: "http://stage.my-service.com"
<<: *defaults
Production:
port: 3000
approot: "http://my-service.com"
<<: *defaults
Разворачивание через Keter
Содержимое файла keter.yml
мы сейчас рассматривать не будем. Это конфигурационный файл для утилиты keter
, предназначенной для автоматического разворачивания нашего приложения в виде специального бандла. Подробнее об этом рассказано здесь. Однако на данный момент я деплою приложение другим (более простым и понятным мне) способом. Кстати, об этом способе мы поговорим в следующих заметках.
Маршруты
Теперь взглянем на файл routes
. Этот файл - один из самых важных для нашего приложения. Взглянем внутрь:
/static StaticR Static getStatic
/auth AuthR Auth getAuth
/favicon.ico FaviconR GET
/robots.txt RobotsR GET
/ HomeR GET POST
Перед нами маршруты (routes). Обычный маршрут определяет три сущности (слева направо):
- Путь, то есть URL (начиная от корня), по которому мы обращаемся к той или иной странице нашего приложения.
- Ресурс, объединяющий обработчик(и) запросов, направленных по тому или иному пути.
- Типы запросов, которые мы можем направить по тому или иному пути.
Рассмотрим корневой маршрут:
/ HomeR GET POST
Путь понятен - это корень нашего приложения (домашняя страница). Ресурс HomeR
отвечает за обработку запросов, направленных к корню приложения. И, как видите, домашняя страница нашего приложения способна принимать как GET
, так и POST
-запросы.
Таким образом, по мере расширения функциональности нашего веб-приложения мы будем довольно часто обращаться к файлу routes
, чтобы дописать новые маршруты.
Вы спросите, почему же первые два маршрута выглядят необычно? Например:
/auth AuthR Auth getAuth
Об этом будет подробнее рассказано в следующих заметках. В частности, путь /auth
скрывает несколько возможных запросов, связанных, как вы уже поняли, с авторизацией.
Модели
Взглянем на содержимое файла models
:
User
ident Text
password Text Maybe
UniqueUser ident
deriving Typeable
Email
email Text
user UserId Maybe
verkey Text Maybe
UniqueEmail email
-- By default this file is used in Model.hs (which is imported by Foundation.hs)
Перед нами - модели для работы с БД. Но об этом мы поговорим особо. Поверьте, эта тема достойна отдельной заметки.
Расположение
Содержимое каталога config
уже вполне пригодно для реального использования. Осталось уточнить одну деталь, касающуюся расположения этого каталога, ведь, как уже было сказано выше, без конфигурационных файлов, расположенных в нём, наше приложение не сможет работать.
Попробуем запустить наше приложение вот так:
$ cd dist/build/webhs
$ ./webhs Development -p 3001
Ага, разбежались! Получите ошибку:
webhs: InvalidYaml (Just (YamlException "Yaml file not found: config/settings.yml"))
Файл config/settings.yml
не найден, и это вполне ожидаемо. Наше приложение рассчитывает на то, что каталог config
расположен не абы где, а в строго определённом месте. Правило очень простое: этот каталог должен располагаться в том же месте, откуда мы запускаем наше приложение.
Например, мы могли бы расположить этот каталог рядом с исполняемым файлом:
$ cd dist/build/webhs
$ cp -R ../../../config .
$ ./webhs Development -p 3001
Так заработает. Но можно просто запустить из того места, где config
уже лежит:
./dist/build/webhs/webhs Development -p 3001
Впрочем, я опять вас немного обманул, потому что исполняемый файл рассчитывает не только на каталог config
, но и ещё на кое-что. Однако об этом в отдельной заметке.