Permalink
Browse files

refactored cycle detection into seperate class

  • Loading branch information...
1 parent 142688c commit 5a0a58caff8436fe4e3c5062ebace6a1c469dede @moonmaster9000 committed Aug 25, 2012
Showing with 63 additions and 65 deletions.
  1. +56 −59 lib/frill/frill.rb
  2. +7 −6 spec/frill_spec.rb
View
@@ -42,7 +42,7 @@ def initialize
end
def add label
- @nodes[label] ||= Node.new label
+ nodes[label] ||= Node.new label
end
def move_before label1, label2
@@ -51,57 +51,85 @@ def move_before label1, label2
node1.move_before node2
- detect_cycles
+ CycleDetecter.detect! nodes
end
def [](label)
- @nodes[label]
+ nodes[label]
end
def empty?
- @nodes.empty?
+ nodes.empty?
end
def include? label
- @nodes.keys.include? label
+ nodes[label]
end
def index label
to_a.index label
end
def to_a
- lists = []
+ array = []
- @nodes.values.each do |node|
- unless lists.include? node.label
- first = node.first
- lists += first.to_a
- end
+ nodes.values.each do |node|
+ array += construct_array(node) unless array.include? node.label
end
- lists
+ array
end
private
+ attr_reader :nodes
- def detect_cycles
- @nodes.values.each do |node|
- visited = {}
- visited[node.label] = true
+ def construct_array node
+ array = []
+ current_node = node.first
- current_node = node.next
- while current_node
- raise Frill::CyclicDependency if visited[current_node.label]
- visited[current_node.label] = true
- current_node = current_node.next
+ while current_node
+ array << current_node.label
+ current_node = current_node.next
+ end
+
+ array
+ end
+
+ class CycleDetecter
+ def self.detect! nodes
+ new(nodes).detect!
+ end
+
+ def initialize(nodes)
+ @nodes = nodes
+ @visited = {}
+ end
+
+ def detect!
+ nodes.values.each do |node|
+ fan_out node unless visited[node.label]
end
+ end
+
+
+ private
+
+ attr_reader :nodes, :visited
+
+ def fan_out(node)
+ visited[node.label] = true
+
+ fan :next, node
+ fan :previous, node
+ end
+
+ def fan(direction, start_node)
+ current_node = start_node.send direction
- current_node = node.previous
while current_node
raise Frill::CyclicDependency if visited[current_node.label]
visited[current_node.label] = true
- current_node = current_node.previous
+ current_node = current_node.send direction
end
end
end
@@ -125,47 +153,16 @@ def move_before node
end
def first
- node = nil
- current_node = self
-
- until node
- if current_node.previous
- current_node = current_node.previous
- else
- node = current_node
- end
- end
-
- node
+ first_node = self
+ first_node = first_node.previous while first_node.previous
+ first_node
end
def last
- current_node = self
- last_node = nil
-
- until last_node
- if current_node.next
- current_node = current_node.next
- else
- last_node = current_node
- end
- end
-
+ last_node = self
+ last_node = last_node.next while last_node.next
last_node
end
-
- def to_a
- current_node = self
-
- list = []
-
- until current_node == nil
- list << current_node.label
- current_node = current_node.next
- end
-
- list
- end
end
end
end
View
@@ -71,10 +71,10 @@ module Module3; include Frill; end
describe ".before" do
it "inserts the current module before the requested module in Frill's list of decorators" do
+ Module4.before Module3
Module2.before Module1
Module5.after Module4
Module3.before Module2
- Module4.before Module3
Frill.decorators.index(Module5).should be > Frill.decorators.index(Module4)
Frill.decorators.index(Module3).should be < Frill.decorators.index(Module2)
@@ -93,19 +93,19 @@ module Module3; include Frill; end
describe ".before" do
it "inserts the current module before the requested module in Frill's list of decorators" do
- Frill.decorators.should == [Module1, Module2, Module3]
+ Frill.list.to_a.should == [Module1, Module2, Module3]
Module1.before Module2
- Frill.decorators.should == [Module1, Module2, Module3]
+ Frill.list.to_a.should == [Module1, Module2, Module3]
Module3.before Module2
- Frill.decorators.should == [Module3, Module1, Module2]
+ Frill.list.to_a.should == [Module3, Module1, Module2]
end
end
describe ".after" do
it "inserts the current module after the requested module in Frill's list of decorators" do
- Frill.decorators.should == [Module1, Module2, Module3]
+ Frill.list.to_a.should == [Module1, Module2, Module3]
Module1.after Module2
Module3.after Module2
@@ -136,10 +136,11 @@ module Module3; include Frill; end
it "should throw exceptions when cycles are detected" do
g = Frill::List.new
+ g.move_before "c", "b"
g.move_before "b", "a"
expect {
- g.move_before "a", "b"
+ g.move_before "a", "c"
}.to raise_exception(Frill::CyclicDependency)
end
end

0 comments on commit 5a0a58c

Please sign in to comment.