Рекурсивное создание индексной панели (на основе UL, LI) - PullRequest
0 голосов
/ 25 августа 2009

Я использую 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. Смотрите последний комментарий на странице.

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

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

1 Ответ

1 голос
/ 27 августа 2009

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

  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 возвращает массив, который мы и хотим. Если прекратить добавление или вложение в исходном массиве, все разрушится:)

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

...