Рекурсивное создание индексной панели (на основе UL, LI)

Я использую awesome_nested_set для своей центральной структуры веб-сайта. Я хочу иметь возможность построить индексную панель на основе UL/LI из вложенного набора, но также хочу, чтобы она использовала преимущества низкой интенсивности базы данных вложенного набора. Когда я использовал act_as_tree, у меня была рекурсивная функция, которая строила индексную панель. Он просто вызывал себя, если встречал дочерние элементы и т. д. Мне интересно, есть ли лучший способ сделать это с помощью nested_set. Я придумал следующее до сих пор (непроверенный):

  def recursive_indexbar(parent, parameters)
    return unless parameters.length == 1 && parameters.first.to_i > 0

    maximum_level = parent.level + parameters.first

    content_tag :ul do
      parent.descendants.current.visible.front_end.recurse do |component_instance, block|
        content_tag :li, :class => (@item.component_instance == component_instance) ? 'uber' : false do
          component_instance.name
          unless component_instance.leaf?
            content_tag :ul, block.call
          end
        end
      end
    end
  end

Теперь это на самом деле не работает, потому что в nested_set нет рекурсивной функции, я просто взял это по этой ссылке: http://dev.rubyonrails.org/ticket/9678. Смотрите последний комментарий на странице.

Также будет возможность пройти несколько уровней вглубь, но это легко реализовать.

Может ли кто-нибудь дать мне какие-либо указатели?


person Brendon Muir    schedule 25.08.2009    source источник


Ответы (1)


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

  def new_recursive(parent, parameters)
    return unless parameters.length == 1 && parameters.first.to_i > 0

    maximum_level = parent.level + parameters.first

    recurse = lambda do |component_instance|
      component_instance.children.current.visible.front_end.collect do |child|
        content_tag :li, :class => (@item.component_instance == child ? 'uber' : nil) do
          returning [] do |content|
            content << link_to(child.name, [child.parent, child.instance])
            unless child.leaf? || child.level == maximum_level
              content << content_tag(:ul, recurse.call(child))
            end
          end
        end
      end
    end

    content_tag :ul, recurse.call(parent)
  end

Обратите также внимание на использование collect, а не each (что кажется более логичным). Collect возвращает массив, который нам и нужен. Если перестать добавлять или вкладывать в исходный массив, все ломается :)

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

person Brendon Muir    schedule 27.08.2009