2012-11-09 1 views
1

Imagine У меня есть объектная модель:шаблона для рекурсивного обновления два взаимосвязанных графов объектов

в блоге есть много статей, и статья имеет много комментариев

Представьте также, что у меня есть два блог, блог и Блог B.

Blog A - Article id 1 - Comment id 1 "fun stuff" 
     - Article id 2 - Comment id 2 "cool" 

и

Blog B - Article id 3 - Comment id 3 "no fun" 

мне нужно сравнить граф объектов для блога A и B, Дневник и обновление Дневник B на основе значения объектов в дневнике А.

В в этом случае блог B должен изменить комментарий 3 как «забавный материал» и создать новые объекты со значениями, идентичными статьям 2 и 2.

Рекурсивно ходить по графику - это очевидное решение, но логика запутана. Я бы предпочел не изобретать колесо ... есть ли образец или процесс для этого?

Я использую Ruby/Rails

+0

Пожалуйста, определите «обновить по мере необходимости». Как «Article 1» имеет два разных «комментария 1» изначально? Они относятся к тем же объектам, принадлежащим обоим блогам? –

+0

Обновлено @ZachKemp, смысл? –

+0

кажется, что вы просто пытаетесь воспроизвести содержимое блога A в блоге B; разве это не проблема дизайна? почему бы не иметь отношения 'has_and_belongs_to_many' между блогами и статьями вместо этого, так что вам не нужно реплицировать ваши записи? –

ответ

0

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

Шаблон посетителя позволяет отделить алгоритм ходьбы от иерархии, начиная с кода, выполняемого на каждом узле иерархии. Более функциональный подход к этому с использованием карты или инъекции/складки возможен ... но, поскольку я хочу повторно использовать операторов, было проще разбить их на отдельные классы.

Иерархия реализована в каждой модели, которая должна определять метод «детей», который возвращает детей.

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

module Visitable 
    def accept visitor 
    child_vals = [] 
    if respond_to?(:children) 
     children.each do |child| 
     child_vals << child.accept(visitor) 
     end 
    end 
    val = visitor.visit(self) 
    child_vals.any? ? val + child_vals : val 
    end 
end 

class Survey 
    attr_accessor :name, :children 

    include Visitable 

end 

class Category 
    attr_accessor :name, :children 

    include Visitable 

end 

class Question 
    attr_accessor :name 
    include Visitable 
end 

s = Survey.new 
s.name = 's1' 
c = Category.new 
c.name = 'c1' 
c2 = Category.new 
c2.name = 'c2' 
q = Question.new 
q.name = 'q1' 
q2 = Question.new 
q2.name = 'q2' 

c.children = [q] 
c2.children = [q2] 
s.children = [c,c2] 

class ReturnVisitor 
    def visit obj 
    obj.name 
    end 
end 

s.accept(ReturnVistor.new) 
-> ['s1', ['c1', ['q1'], ['c2', ['q2']]]] 

# "poorly implemented lisp"?