Internal Server Error

Previous Entry Share Next Entry
Web.pm second week
ihrd
Пока собирается крайняя версия Rakudo -- пишу очередной отчет. (Как соберется, запущу time make spectest, любопытно сколько теперь это замет времени на моей машине, результат напишу в конце поста.)

Работы по гранту движутся медленно. Forest остановился на наивном рабочем наброске, я отложил его и взялся за Routes. Главная мысль тут напрямую заимствована из RoR -- описать в одно месте с помощью достаточно гибких правил порядок разбора путей запросов. Это полезно с разных сторон: и разработчик видит все это в одном месте, и f/w знает о структуре приложения заранее.

Маршруты могут описывать как очень конкретный путь, так и общий шаблон, свои мысли о том как это может выглядеть я набросал в drafts/{routes.p6, Routes.pm}, там же есть ссылка на документацию к Routes в RoR. Сначала я думал обойтись умным сопоставлением (~~) двух массивов -- паттерна маршрута и запрошенного пути, но это оказалось слишком аскетичным, потребовалась большая гибкость в описании паттернов и я понял, что могу развить свой простенький Dispatcher.pm, который я написал ранее для November, как раз до нужного результата. Этим и занялся, сначала в репозитарии November (http://github.com/viklund/november), сейчас перенес код и продолжаю в Web (http://github.com/masak/web).

Теперь паттерн, это массив правил и сопоставляется (~~) он попарно с элементами пути. Делается это через zip оператор. Если правило совпадает -- вызывается замыкание. В самом простом случае добавление маршрут происходит так:

.add: ['foo', 'bar'], { ... }; 


Я добавил к распознаваемым правила *, как прямой способ сказать «здесь все что угодно», и даже немного больше: у zip оператора по спецификации есть специальное поведение в случае если последний элемент массива Whatever, массив растягивается до нужно длины. К сожалению это пока не реализовано, придется делать некрасивую имитацию, но так или иначе это дает дополнительную гибкость.

Еще одно нововведение -- использование :pair, чтобы запоминать параметры из пути и их передача в замыкание как именованных параметров. Здесь, к сожалению, тоже есть ограничения реализации, | %args пока не работает (в отличии от | @args), поэтому сейчас там не красивый код и работает он только для :controller и :action. Тем не менее можно использовать:

.add: [:action(/^ .+ $/), *], { self."{$:action}"(@_) } 


и это способ описать, что-то похожее на предложенное Moritz`ом поведение. По спецификации запись :pair эквивалентна pair => True и тогда первое правило выражается через просто :action.

Сейчас Rakudo неверно интерпретирует :pair как pair => 1. Jonathan помог мне c PAST, Moritz подсказал как правильно обращаться с тестами и я написал простой патч, который это исправляет. Надеюсь его примут в ближайшее время.

Чтобы упростить работу с маршрутами, я хочу сделать набор специфичных методов. Например ресурсы, как это было придумано в Forest, можно будет описывать так:

given $routes {
    .resources: 'foo', has => {
         .resource: 'account';
    }
}


И это создаст примерно такие маршруты:

.add: ['foo', * ], { %*controllers."{$:method}"(| @_) }
.add: ['foo', *, 'account'], { 
    my @args; 
    @args.push: %*controllers{$_}.Link(| $_) for @:chain; 
    %*controllers."{$:method}"(| @args);   
}


В итоге Routes, в моем понимании, должен стать основным компонентом f/w описывающим структуру приложения. А уже через него к обработке запроса можно подключить все, что угодно.


Ну вот, собрал Rakudo 79aba97, тесты Dispatcher больше не проходит, падает, пошел разбираться что же с ним не так. И переименую его в Routes уже, чтобы было поменьше путаницы.

(А, да, результаты:
Files=359, Tests=12720, 1523 wallclock secs ( 9.34 usr 1.53 sys + 2232.92 cusr 69.66 csys = 2313.45 CPU)

real 25m35.054s
user 37m29.637s
sys 1m12.839s)

Upd: переименовал, пофиксил тесты 01-06 снова проходит
Tags: ,

Рекомендую посмотреть на диспатчер фрэймворка merb, а не на рельсовый. Он элегантнее, функциональнее и быстрее рельсового :)

Хорошо, я посмотрю.

You are viewing ihrd