(no subject)

Jun 01, 2010 18:38


Мой первый плагин для Ruby on Rails

Плагин sviperll_navigation предназначен для описания структуры Веб-приложения с точки зрения пользовательского интерфейса. sviperll_navigation позволяет декларативно описать связи между страницами приложения в виде дерева и использовать это описание для генерации меню и других навигационных элементов на страницах сайта. Плагин стоит использовать, когда система навигации сильно параметризована, например когда сущетвует несколько ролей пользователей, для каждой из которых доступно различное множество страниц и следует отображать различные пункты меню. Структура меню в таком случае должна быть максимально адаптирована под конкретную роль, показывая первыми наиболее часто используемые страницы этой роли. Установка: Просто поместить плагин в директорию "vendor/plugins" приложения. Настройка: В директории "config" приложения создать файл navigation.rb следующего вида: Navigator.draw(request) do |nav| if !logged_in? nav.node :top, 'Вход', login_path else nav.node :top, 'Счета', paid_orders_path do |orders| unless @order.nil? || @order.new_record? || !@order.confirmable? all_orders.node :hidden, @order.external_id, user_order_path(:user_id => @user.id, :id => @order.id) do |order| order.node :left, 'Получить PDF', user_order_path(:user_id => @user.id, :id => @order.id, :format => :pdf), :class => 'pdf' end end end nav.vnode :top, 'Расходы' do |expenses| expenses.node :tab, 'Расходы пользователей', expenses_path expenses.node :tab, 'Неучтённые рассылки', accountable_lists_path do |lists| if !@list.nil? && !@list.new_record? && @list.accountable? lists.node :hidden, @list.name, user_list_path(:user_id => @user.id, :id => @list.id) do |list| list.node :hidden, 'Редактировать', edit_user_list_path(:user_id => @user.id, :id => @list.id) end end end end end end Файл обязан заканчиваться блоком Navigator.draw(request) do ... end До этого блока могут быть объявления дополнительных функций, в случае, если это потребуется. В этом файле доступны все переменные и методы, которые доступны в тексте любого шаблона Ruby on Rails. Например выше используются переменные @order и @list, а так же helper logged_in? Внутри блока описывается дерево страниц приложения. Для этого используется два метода: - node - vnode Метод node описывает конкретную страницу приложения. Метод node принимает следующие аргументы: node(, ,
, = {}) - --- это абсолютно произвольная метка, которой помечается переход от родительской страницы к данной - --- заголовок данной страницы -
--- url данной страницы, в качестве параметра лучше использовать helper'ы которые предоставляет Ruby on Rails, типа users_path, user_lists_path и т. п. - --- произвольный словарь, по-умолчанию пустой. Метод vnode описывает виртуальную страницу приложения. В приложении нет контроллера или представления, которые описывали бы эту страницу, но было бы не плохо иметь эту страницу, чтобы навигация по приложению была более удобной и логичной. Метод vnode принимает два аргумента: vnode(, , = {}) Смысл аргументов такой же как и у метода node, единственное отличие --- отсутствие аргумента
Использование: При подключении плагина во всех представлениях приложения становится доступным helper с именем navigator этот хелпер можно использовать для генерации меню преложения. <% navigator.children(:left).each do |node| %>
  • <%= link_to "#{h(node.title)}", node.path, node.options %>
  • <% end %> В этом фрагменте выбираются все страницы на которые можно попасть с текущей страницы, но только те, которые помечены меткой :left. Результатом метода является массив описаний страниц. Для каждого элемента доступны следующие методы. - title --- заголовок страницы из файла navigation.rb - path --- url страницы из файла navigation.rb - options --- словарь значений из файла navigation.rb - current? --- метод возвращает true если это и есть текущая страница - active? --- метод возвращает true, если путь от корня дерева к текущей страницы проходит через данную страницу. Кроме метода children предоставляется ещё несколько методов, каждый из которых возвращает массив описаний страниц: - children() --- метод из примера, возвращает страницы, помеченные тегом , на которые можно попась из данной страницы. - siblings() --- возвращает страницы-братья, помеченные тегом . Братьями считаются страницы, на которые можно попасть с родительской страницы для текущей. - root() --- возвращает корневые для приложения страницы, помеченные тегом - path --- возвращает последовательность страниц, начиная от корня и заканчивая текущей страницей. Метод path в отличие от остальных методов не принимает параметра с меткой страниц. Методы children, siblings и root можно вызывать без параметра , в таком случае будут выбираться все страницы, а не только помеченные каким-то тегом. Метод children инкапсулирует паттерн "Куда я могу попасть отсюда?". Его можно использовать для генерации меню внизу страницы. Метод siblings можно использовать для навигации в стиле закладок, когда в верху страницы отображется панель закладок, с помощью которых можно переходить между соседними страницами. Метод root можно использовать для отображения главного меню приложения, которое отображается всегда. Метод path можно использовать для реализации "хлебных крошек", элемента навигации, который отображает путь к текущей страницы, когда можно перепрыгнуть на любую из родительских страниц. Теги позволяют группировать страницы по какому-то признаку, отображая несколько меню в разных частях страницы с разным оформлением. Все методы всегда возвращают либо массив страниц, либо пустой массив. Несколько текущих страниц Возможен случай, когда в дереве страниц приложения присутствует несколько страниц с одинаковым параметром path метода node. В таком случае текущей считается только одна страница, та, которая встречается в дереве первой. Первыми в дереве страниц следует размещать наиболее часто посещаемые/используемые страницы. Система навигации поддерживает эту идею, пытаясь сделать текущими именно первые страницы. Виртуальные страницы У виртуальных страниц отсутвтвует параметр path в файле navigation.rb. Если ссылка на виртуальную страницу отображается в меню, то куда будет осуществлён переход, при клике на эту ссылку? Переход будет осуществлён на первую невиртуальную страницу вложенную в данную виртуальную страницу. Таким образом система навигации реализует, что-то вроде редиректа. Если виртуальную страницу показать нельзя, то попробуем показать вложенную страницу и так до тех пор, пока мы не дойдём до невиртуальной страницы. Это свойство так же поддерживает правило что самые часто посещаемые/используемые страницы нужно размещать первыми в дереве страниц. Так как при переходе на виртуальную страницу будет реально показываться первыая из вложенных невиртуальных страниц. Если есть несколько страниц, вложенных в виртуальную страницу и для одной из них свойство current? равно true, то для родительской виртуальной страницы свойство current? так же будет true. Отсутствие текущей страницы В случае, если текущая отображаемая страница не описана в файле navigation.rb, то у система навигации не будет занать, какая страница текущая. В этом случае все методы объекта navigator, которые должны возвращать массив описаний страниц, будут возвращать пустой массив. Исключением является метод root, который не зависит от текущей страницы. Определение текущей страницы Для определения текущей страницы используется путь, переданный в качестве параметра
    методу node в файле navigation.rb. На определение того, является ли страница текущей влияют только те параметры, которые отвечают за формирование элемента PATH в HTTP запросе. В запросе http://my.site.com/this/is/the/path?param1=value1¶m2=value2 элементом PATH является строка '/this/is/the/path' именно она сравнивается с параметром path страницы в файле navigation.rb и в случае совпадения страница считается текущей. Второстепенные параметры отбрасываются. Для реализации сравнения используется свойство path_parameters объекта request, которое сравнивается с параметрами, получаемыми при разброре свойства path страницы из файла navigation.rb page_params = ActionController::Routing::Routes.recognize_path(path, :method => :get) current_page_params = request.path_parameters Если page_params и current_page_params совпадают, то страница считается текущей. Страницы, которые отображают действия new и create контроллеров считаются одинаковыми, так же как и страницы, которые отображают действия edit и update. Для этого при сравнении словарей параметров, для элементов 'action' не различаются пары 'create' и 'new', а так же 'update' и 'edit'.

    ruby, web, rails

    Previous post Next post
    Up