Релиз гема TheSortableTree 2.0

    Приветствую!

    Рад сообщить, что в прошедшие выходные, после долгого затишья, состоялся релиз моей небольшой, но смею надеяться, полезной поделки — гема TheSortableTree (rails 3, rails 4).

    TheSortableTree — это гем, который помогает организовать отрисовку Nested Set деревьев. Но самое главное то, что он позволяет легко и просто управлять вашим Nested Set деревом с помощью удобного перетаскивания элементов в нужное место.

    image

    В текущей версии гема решена самая главная проблема — скорость отрисовки. Раньше она была чудовищно медленной. Сейчас (в среднем) можно получить скорость отрисовки 1500-2000 узлов в секунду. Я считаю эту скорость приемлемой и достаточной для большинства прикладных нужд.

    Ниже (если вам интересно) немного истории создания гема, благодарности, планы, и рассказ о том, как на open source проекты влияет распитие крепкого черного чая вечером после работы.

    P.S:

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



    Немного истории


    Интерес к nested set и его отрисовке у меня появился тогда же, когда я познакомился с ruby и ruby on rails. Это был год 2008.

    Если вы помните, в то время реализация nested set алгоритма на ruby была в начальном состоянии. Мы использовали nested set для формирования дерева комментариев. Главной проблемой работы с вложенными множествами стало то, что приличного и достаточно распространенного решения для отрисовки деревьев фактически не было. Мы велосипедировали как могли.

    В тот момент я захотел рисовать деревья простой рекурсией. Почему? Потому что этот подход, на мой взгляд, довольно прост в реализации, понятен для понимания и практически не содержит магии.

    В 2009-2010 годах в моих проектах уже работала первая версия кода для отрисовки деревьев. Тогда код был совсем плох — классическая каша из вида и логики. Мне не удавалось найти время для расчистки авгиевых конюшен. Но! Код работал.

    В конце 2011 я вычислил код, отделил логику от представления и оформил первую версию гема. Проблемы были, но я надеялся на коллективный разум github'a. В любом случае могу сказать, что в некотором плане код стал красивым. Но все еще ужасно медленным. Я даже не хочу вспоминать эти страшные цифры.

    В конце 2012 случайная беседа с хабрапользователем Anonym натолкнула меня на мысль, что мой код работает безбожно медленно и так быть не должно. И если до этого я ждал доброго дядю с github'a, который мне подскажет что нужно изменить в моем коде, то в тот момент меня разобрал дикий интерес: что же не так?

    Странно, но почему-то именно после виртуальной беседы с Anonym в одной из веток Q&A хабра, сидя дома за чашкой вечернего чая я прокрутил в голове основные фрагменты своего кода и нашел узкое место.

    Решение было таким ужасно простым, что даже ввело меня в ступор на некоторое время. В тот же вечер гем был пропатчен и скорость отрисовки катастрофически возросла. Код стал быстрым.

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

    Благодарности


    Я очень признателен всем тем, кто помогал мне советами, патчами, консультациями и конструктивной критикой и скепсисом: прежде всего это хабражители: vorbiz, UseRifle и Anonym.

    Спасибо некому mjsarfatti за его скрипт nestedSortable на базе которого работает перетаскивание в моем геме.

    Спасибо Иконзе за пару-тройку иконок.

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

    Планы


    Сейчас я вижу несколько основных направлений над которыми стоит поработать:

    1. Я вырезал из гема хелпер, создающий простой шаблон для древовидных комментариев. На мой взгляд такой функционал сразу стоит вынести в отдельный гем, основанный на моем геме. Хотя таких решений уже наверняка полно. И тут стоит серьезно подумать.

    2. Есть много других решений для древовидных структур данных — acts_as_ordered_tree, ancestry. Было бы хорошо сделать версию гема и под них.

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

    Немного о граничных условиях


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

    Итого


    В целом, я доволен тем, что получилось. Надеюсь моя небольшая поделка облегчит кому-то жизнь.

    Конечно я надеюсь на конструктивную критику, отзывы и issues на странице проекта.

    Успехов и удачи!

    Похожие публикации

    Средняя зарплата в IT

    110 500 ₽/мес.
    Средняя зарплата по всем IT-специализациям на основании 7 087 анкет, за 2-ое пол. 2020 года Узнать свою зарплату
    AdBlock похитил этот баннер, но баннеры не зубы — отрастут

    Подробнее
    Реклама

    Комментарии 13

      +1
      Решение было таким ужасно простым, что даже ввело меня в ступор на некоторое время.

      Так написали бы что за решение :)
        0
          +1
          дык и коммит у вас не один что бы понять где вы смогли прозреть :)
            0
            попробуйте отрисовать дерево рекурсией. главная проблема — выбрать на текущем уровне все дочерние узлы для данного parent_id. это операция ресурсоемкая. я просто построил индексный массив, где индекс массива — parent_id. Так для текущей ноды с id=100 я из индексного массива могу выбрать всех дочек просто обратившись children_nodes[100]. выбираю детей пачками и очень быстро. очень простое решение доступное школьнику 9 класса. Просто надо было правильно поставить вопрос, который я себе почему то очень поздно задал.
          0
          Решение только для подписчиков :)
            0
            ссылка выше ведет на строку с конкретным кодом. пояснение написал в комментах. сразу не написал — лишний повод для придирок. На хабре редко дают конструктивные предложения. На мой взгляд, особенности реализации лучше обсуждать в другом месте.
          +1
          Реквестирую поддержки ancestry!
          И спасибо за гем, конечно.
          Вообще, конечно, удивляет, что в весьма интегрированном мире RoR нет единого решения для такой базовой вещи, как универсальное дерево.
            0
            Присоединяюсь к риквесту. Очень люблю ancestry за возможность легко оперировать его полем на клиенте.
              0
              ancestry не входит в круг моих интересов, обещать не буду. Хотя как знать. Возможно кто то решится сам сделать форк и доработать.
              0
              Для отрисовки Nested Set дерева достаточно цикла и стека текущих parent-вершин.
                0
                полностью согласен. Но ведь за то, что пошел другим путем — не расстреляют?
                0
                Дело не в расстреле :-) Дело в том что выгода от использования вложенных множеств — это то что можно выбирать произвольное поддерево одним SQL-запросом. И получив его отсортированным по LEFT несложно его отобразить. Собственно цикл и стек — это просто оптимизации рекурсии, более императивно.
                  0
                  да, все как вы говорите. Но вот что получается — я видел код «плоской» пробежки по дереву. Без рекурсий как у меня. И я не могу вам сказать, что тот код мне было легко понять и кастомизировать. Возможно вы знаете решение лучше, и это конечно же прекрасно, если вы покажете другой удобный путь. Мне тяжело давать оценки без конкретного кода. Если вам не трудно — напишите мне в скайп (он есть на гитхабе). как я понимаю вы сами занимались этим вопросом и у вас есть примеры наработанного кода. Было бы интересно пообщаться на эту тему.

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

                Самое читаемое