Использование полиморфизма Rails для вложенных комментариев - PullRequest
2 голосов
/ 30 ноября 2010

Мне нужно создать систему вложенных комментариев в приложении на Rails 3, которая позволяет комментировать многие модели (статьи, публикации и т. Д.), И я обсуждаю вопрос о развертывании своего собственного решения в духе этого поста .Доступны драгоценные камни, такие как acts_as_commentable_with_threading с awesome_nested_set , но они чувствуют себя раздутыми для моих нужд.

  1. Мне нужно иметь возможность добавлять комментарии к нескольким моделям
  2. Мне нужно иметь возможность добавлять комментарии к комментариям, бесконечно глубоко
  3. Мне нужно иметь возможность эффективно извлекать всех потомков для поста, статьи и т. Д.
  4. Мне нужнобыть в состоянии эффективно представить комментарии в их соответствующей вложенности

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

Кто-нибудь высказался по этому поводу?Спасибо.

Ответы [ 3 ]

6 голосов
/ 30 ноября 2010

Существует два вида вложений: дерево и вложенный набор.

acts_as_tree хранит только parent_id, поэтому писать новые записи очень быстро, но вы должны рекурсивно пройтись по цепочке идентификаторов, чтобы получить список всех дочерних элементов. Это не хороший выбор, когда вам нужно много читать.

awesome_nested_set записывает три бита информации: parent_id, lft и rgt. Левые и правые значения рассчитываются так, чтобы они содержали все дочерние идентификаторы для этой записи. Это очень быстро для операций чтения, но медленнее для записи.

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

Вам нужно использовать только два метода для рендеринга всего дерева комментариев: итерировать по Comment.roots и для каждого комментария визуализировать comment.children.

class ModelController < ApplicationController
  def show
    @model = Model.find_by_id(params[:id])
    @comments = @model.comments.roots
  end
end

<ul id="comments">
<% @comments.each do |comment| %>
  <%= render :partial => 'comment', :object => comment %>
<% end %>
</ul>

<!-- _comment partial -->
<li class="comment">
  <!-- comment markup -->
  <% if comment.children.present? %>
  <ul>
    <%= render :partial => 'comment', :collection => comment.children %>
  </ul>
  <% end %>
</li>

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

Обновление : Похоже, awesome_nested_set не обновлялось некоторое время. Проверьте родословную вместо этого. В основном делает то же самое.

1 голос
/ 30 ноября 2010

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

Я бы проверил Рекурсивные CTE - хотя он не зависит от базы данных, он дает вам хорошую структуру данных для работы без необходимости иметь дополнительные атрибуты для отслеживания.

0 голосов
/ 04 октября 2011

Раньше я делал что-то подобное, добавляя следующие поля в таблицу комментариев:

attach_to_controller (string)

attach_to_id (int)

Тогда при показе я бы сделал AJAX-вызов индекса комментариев и отфильтровал их по этим двум полям.

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

...