вторник, 8 ноября 2011 г.

Mojlicious: Использование роутов в javascript

Мне нравится, как реализованы роуты в Mojolicious и особенно мне нравится то, что их можно именовать. Именую я роуты всегда в соответствии с именем контроллера и метода.
Например,
$r->get('/messages/:id')->to('messages#show')->name('messages_show');
$r->post('/messages/:id/delete')->to('messages#delete')->name('messages_delete');
И затем в контроллере:
$self->redirect_to('messages_show', id =>123);
Такой подход позволяет изменять роуты с меньшим влиянием на остальной код. И все бы хорошо, но часто приходится использовать роуты не только на стороне сервера, но и на стороне клиента. Например,
var some_id = 123;
$.getJSON('/messages/' + some_id, function(data){ ... });
$.post('/messages/' + some_id + '/delete', function(data){ ... });
Хотелось бы иметь возможность использовать имена роутов и на клиентской стороне. Для этой задачи и был написан плагин "Mojolicious::Plugin::JSUrlFor". Достаточно добавить в основной ваш лейаут:
<%= js_url_for %>
и в клиентском javascript-е будет доступна функция "url_for"( аналогична хелперу "url_for" с "Mojolicious::Plugin::DefaultHelpers"):
var some_id = 123;
$.getJSON( url_for('messages_show', {id:some_id}), function(data){  } );
$.post( url_for('messages_delete', {id:some_id}), function(data){  } );
Модуль "Mojolicious::Plugin::JSUrlFor" пока еще только на Github, но заброшу на CPAN сразу, как покрою тестами.

10 коммент.:

fuksito комментирует...

А почему бы не вставлять в шаблонах перловый url_for ?
Типа:

$.getJSON( <%= url_for('messages_show', {id:some_id}) %>, function(data){ } );

yko комментирует...

Хорошая идея. Генерация url в js часто бывает головной болью.

Из предложений:
1. вынести шаблон js в __DATA__ будет удобне и не будет html в коде
2. чтобы генерировать $json_routes один раз, но лениво - при первом обращении. Таким образом не нужно будет бегать по всему дереву роутов при каждом запросе.
3. сохранить js в отдельный файл в статике. при запуске приложения убивать его, при первом обращении - создавать и дальше раздавать как статику.
3.1 т.к. роуты вообще-то динамичные, то сделать п.3 - опциональным :)

Это все позволит решить проблему с модульностью - почти весь js код всеже приятнее хранить в отдельных файлах, чем писать прямо в html.

koorchik комментирует...

2fuksito:
Допустим у тебя есть список сообщений и функции:
function show_message(message_id) {}
function delete_message(message_id) {}
Каким образом ты будешь использовать перловый url_for ?

И более того прогонять статический javascript через шаблонизатор - это не есть гуд.

koorchik комментирует...

2yko:
>Из предложений:
1. вынести шаблон js в __DATA__ будет удобне и не будет html в коде

Подумаю над этим.

>2. чтобы генерировать $json_routes один раз, но лениво - при первом обращении. Таким образом не нужно будет бегать по всему дереву роутов при каждом запросе.
В приципе, генерация и происходит только во время вызова хелпера "js_url_for", если шаблон не использует этот хелпер, тогда генерация не происходит. Но, согласен, нужно добавить кеширование, чтобы повторно ходить по дереву роутов.

>3. сохранить js в отдельный файл в статике. при запуске приложения убивать его, при первом обращении - создавать и дальше раздавать как статику.
3.1 т.к. роуты вообще-то динамичные, то сделать п.3 - опциональным :)

Тоже неплохой вариант, но это уже попадет в "TODO" :)

fuksito комментирует...

2koorchik предпроцесинг яваскрипта вполне нормальное дело, как по мне, особенно если он так компилируеться один раз.
Не знаю как в моджо, но в рельсах для url_for можно задать объект как параметр пути, вроде url_for(user), и в объекте уже решается что будет использовано в пути, айдишник или юзернейм или комбинация.
Например url_for(artist) выводит /3444-Metallica. Получаеться что поведение в яваскрипте и на серверсайде разное.

koorchik комментирует...

2fuskito:
> предпроцесинг яваскрипта вполне нормальное дело, как по мне, особенно если он так компилируеться один раз
Тогда твой вариант:
$.getJSON( <%= url_for('messages_show', {id:some_id}) %>, function(data){ } );
Не будет работать.

> Не знаю как в моджо, но в рельсах для url_for можно задать объект как параметр пути, вроде url_for(user), и в объекте уже решается что будет использовано в пути, айдишник или юзернейм или комбинация.
Все равно не понял, как можно реализовать "function show_message(message_id) {}" если у тебя "url_for(user)" может вызываться только в шаблонах и нет JS варианта?

koorchik комментирует...

Добавил кеширование сгенерированного кода джаваскриптовой функции "url_for" для "production" режима.

Анонимный комментирует...

>Допустим у тебя есть список сообщений и функции:
>function show_message(message_id) {}
>function delete_message(message_id) {}
>Каким образом ты будешь использовать перловый url_for ?
>И более того прогонять статический javascript через шаблонизатор - это не есть гуд.

Нафик, лучше js прогонять через статический валидатор.

koorchik комментирует...

>Нафик, лучше js прогонять через статический >валидатор.
Кто здесь? Это вообще к чему?

koorchik комментирует...

2yko:
>сохранить js в отдельный файл в статике. при запуске приложения убивать его, при первом обращении - создавать и дальше раздавать как статику.

Добавил генератор статического javascript-файла. Генерировать нужно вручную.
./your_app.pl generate js_url_for $filename

Отправить комментарий

Не забудьте добавить себя в постоянные читатели и включить уведомления о новых комментариях, либо воспользуйтесь RSS каналом ;)