Как реализовать в Ruby on Rails навигацию по разделам?

У меня есть приложение Ruby / Rails, в котором есть два или три основных «раздела». Когда пользователь посещает этот раздел, я хочу отобразить некоторую под-навигацию. Все три раздела используют один и тот же макет, поэтому я не могу «жестко закодировать» навигацию в макете.

Я могу придумать несколько разных способов сделать это. Думаю, чтобы помочь людям проголосовать, я помещу их в качестве ответов.

Есть другие идеи? Или за что голосуете?

Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
12
0
5 082
9
Перейти к ответу Данный вопрос помечен как решенный

Ответы 9

  1. Частичная визуализация. Это очень похоже на вспомогательный метод, за исключением того, что, возможно, в макете будут некоторые операторы if или передать их помощнику ...

да, что-то вроде render: partial => 'section1_subnav'

Matt Rogish 30.09.2008 04:11

Вы можете использовать что-то вроде плагина навигации по адресу http://rpheath.com/posts/309-rails-plugin-navigation-helper

Он не выполняет навигацию по подразделам из коробки, но после небольшой настройки вы, вероятно, сможете настроить его на что-то подобное.

Я предлагаю вам использовать частичные. Есть несколько способов сделать это. Когда я создаю партиалы, которые немного разборчивы в том, что им нужны определенные переменные, я также создаю для них вспомогательный метод.

module RenderHelper
  #options: a nested array of menu names and their corresponding url
  def render_submenu(menu_items=[[]])
    render :partial => 'shared/submenu', :locals => {:menu_items => menu_items}
  end
end

Теперь партиал имеет локальную переменную с именем menu_items, по которой вы можете перебирать, чтобы создать свое подменю. Обратите внимание, что я предлагаю вложенный массив вместо хеша, потому что порядок хеширования непредсказуем.

Обратите внимание, что логика, определяющая, какие элементы должны отображаться в меню, также может быть внутри render_submenu, если это имеет для вас больше смысла.

Что касается содержания ваших подменю, вы можете декларативно работать с ним в каждом контроллере.

class PostsController < ApplicationController
#...
protected
  helper_method :menu_items
  def menu_items
    [
      ['Submenu 1', url_for(me)],
      ['Submenu 2', url_for(you)]
    ]
  end
end

Теперь всякий раз, когда вы вызываете menu_items из представления, у вас будет правильный список для перебора конкретного контроллера.

Это кажется мне более чистым решением, чем размещение этой логики внутри шаблонов представлений.

Обратите внимание, что вы также можете объявить элементы меню по умолчанию (пустые?) Внутри ApplicationController.

Не лучше ли иметь текст для параметров подменю в представлении, а не в контроллере?

Olly 02.10.2008 23:07

Это худший из возможных подходов. Как указывалось выше, он полностью нарушает MVC.

maurycy 26.12.2008 23:04

Предупреждение: впереди продвинутые трюки!

Сделайте их все. Скройте те, которые вам не нужны, с помощью CSS / Javascript, которые можно тривиально инициализировать любым количеством способов. (Javascript может читать используемый URL-адрес, параметры запроса, что-то в файле cookie и т. д. И т. Д.) Это имеет то преимущество, что потенциально может намного лучше работать с вашим кешем (зачем кешировать три представления, а затем истекать их все одновременно, если вы можете кэшировать один ?), и может использоваться для улучшения взаимодействия с пользователем.

Например, давайте представим, что у вас есть общий интерфейс панели вкладок с суб-навигацией. Если вы визуализируете содержимое всех трех вкладок (т.е. оно написано в HTML) и скрываете две из них, переключение между двумя вкладками выполняется тривиально: Javascript и даже не попадает в ваш сервер. Большая победа! Нет задержки для пользователя. Никакой нагрузки на сервер для вас.

Хотите еще одна большая победа? Вы можете использовать вариант этого метода для обмана страниц, которые могут быть не более чем на 99% общими для пользователей, но все же содержать пользовательское состояние. Например, у вас может быть первая страница сайта, которая является относительно общей для всех пользователей, но при входе в систему произносится «Привет, Боб». Поместите необщую часть («Привет, Боб») в файл cookie. Прочтите эту часть страницы через Javascript, читающий файл cookie. Кэшировать всю страницу для все пользователи независимо от статуса входа при кэшировании страницы. Это буквально способно отрезать 70% доступа от всего стека Rails на некоторых сайтах.

Кого волнует, может ли Rails масштабироваться или нет, когда ваш сайт на самом деле является Nginx, обслуживающим статические ресурсы, с новыми HTML-страницами, которые иногда доставляются каким-то Ruby, работающим при каждом тысячном доступе или около того;)

Обратите внимание, что этот ответ воля не удастся для некоторых пользователей, если вы сначала не протестируете (или не предположите) JavaScript или файлы cookie, соответственно. Лучшим ответом было бы использовать вместо этого JavaScript с частичным HTML или Varnish + ESI.

Louis St-Amour 26.05.2012 19:37

Я сам задал примерно тот же вопрос: Нужен совет: структура представлений Rails для подменю? Вероятно, лучшим решением было использование частичных файлов.

Есть еще один способ сделать это: вложенные макеты.

Я не помню, где я нашел этот код, поэтому приношу свои извинения первоначальному автору.

создайте файл с именем nested_layouts.rb в папке lib и включите следующий код:

module NestedLayouts
  def render(options = nil, &block)
    if options
      if options[:layout].is_a?(Array)
        layouts = options.delete(:layout)
        options[:layout] = layouts.pop
        inner_layout = layouts.shift
        options[:text] = layouts.inject(render_to_string(options.merge({:layout=>inner_layout}))) do |output,layout|
          render_to_string(options.merge({:text => output, :layout => layout}))
        end
      end
    end
    super
  end
end

затем создайте различные макеты в папке макетов (например, admin.rhtml и application.rhtml).

Теперь в ваших контроллерах добавьте это внутри класса:

include NestedLayouts

И, наконец, в конце ваших действий сделайте следующее:

def show
  ...
  render :layout => ['admin','application']
end

порядок макетов в массиве важен. Макет администратора будет отображаться внутри макета приложения, где бы ни находился «результат».

этот метод может очень хорошо работать в зависимости от дизайна сайта и того, как организованы различные элементы. например, один из включенных макетов может просто содержать серию блоков div, содержащих контент, который необходимо отобразить для определенного действия, а CSS в макете более высокого уровня может контролировать их расположение.

Ответ принят как подходящий

Вы можете легко сделать это с помощью частичных файлов, если у каждого раздела есть собственный контроллер.

Допустим, у вас есть три раздела с именами Сообщения, Пользователи и Админ, каждый со своим собственным контроллером: PostsController, UsersController и AdminController.

В каждом соответствующем каталоге views вы объявляете партиал _subnav.html.erb:

/app/views/users/_subnav.html.erb
/app/views/posts/_subnav.html.erb
/app/views/admin/_subnav.html.erb

В каждой из этих частей субнава вы объявляете параметры, относящиеся к этому разделу, поэтому /users/_subnav.html.erb может содержать:

<ul id = "subnav">
  <li><%= link_to 'All Users', users_path %></li>
  <li><%= link_to 'New User', new_user_path %></li>
</ul>

Хотя /posts/_subnav.html.erb может содержать:

<ul id = "subnav">
  <li><%= link_to 'All Posts', posts_path %></li>
  <li><%= link_to 'New Post', new_post_path %></li>
</ul>

Наконец, как только вы это сделаете, вам просто нужно включить партиал subnav в макет:

<div id = "header">...</div>    
<%= render :partial => "subnav" %>
<div id = "content"><%= yield %></div>
<div id = "footer">...</div>

Есть несколько подходов к этой проблеме.

Возможно, вы захотите использовать разные макеты для каждого раздела.

Возможно, вы захотите использовать партиал, включенный всеми представлениями в данном каталоге.

Возможно, вы захотите использовать content_for, который заполняется представлением или частичным и вызывается в глобальном макете, если он у вас есть.

Лично я считаю, что в этом случае вам следует избегать большей абстракции.

Другие вопросы по теме