frill 0.1.4 → 0.1.5

Sign up to get free protection for your applications and to get access to all the features.
Files changed (4) hide show
  1. data/VERSION +1 -1
  2. data/lib/frill/frill.rb +66 -31
  3. data/spec/frill_spec.rb +28 -17
  4. metadata +12 -12
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.1.4
1
+ 0.1.5
data/lib/frill/frill.rb CHANGED
@@ -1,36 +1,42 @@
1
1
  module Frill
2
+ class CyclicDependency < RuntimeError; end
3
+
2
4
  def self.included(base)
3
- self.decorators.add base
5
+ self.list.add base
4
6
  base.extend ClassMethods
5
7
  end
6
8
 
7
9
  def self.decorators
8
- @decorators ||= Graph.new
10
+ list.to_a
9
11
  end
10
12
 
11
13
  def self.reset!
12
- @decorators = nil
14
+ @list = nil
13
15
  end
14
16
 
15
17
  def self.decorate object, context
16
- decorators.sorted_nodes.each do |d|
18
+ decorators.each do |d|
17
19
  object.extend d if d.frill? object, context
18
20
  end
19
21
 
20
22
  object
21
23
  end
22
24
 
25
+ def self.list
26
+ @list ||= List.new
27
+ end
28
+
23
29
  module ClassMethods
24
30
  def before decorator
25
- Frill.decorators.move_before self, decorator
31
+ Frill.list.move_before self, decorator
26
32
  end
27
33
 
28
34
  def after decorator
29
- Frill.decorators.move_after self, decorator
35
+ Frill.list.move_after self, decorator
30
36
  end
31
37
  end
32
38
 
33
- class Graph
39
+ class List
34
40
  def initialize
35
41
  @nodes = {}
36
42
  end
@@ -44,6 +50,8 @@ module Frill
44
50
  node2 = add label2
45
51
 
46
52
  node1.move_before node2
53
+
54
+ detect_cycles
47
55
  end
48
56
 
49
57
  def move_after label1, label2
@@ -51,6 +59,8 @@ module Frill
51
59
  node2 = add label2
52
60
 
53
61
  node1.move_after node2
62
+
63
+ detect_cycles
54
64
  end
55
65
 
56
66
  def [](label)
@@ -66,53 +76,78 @@ module Frill
66
76
  end
67
77
 
68
78
  def index label
69
- sorted_nodes.index label
79
+ to_a.index label
70
80
  end
71
81
 
72
- def sorted_nodes
82
+ def to_a
73
83
  lists = []
74
84
 
75
85
  @nodes.values.each do |node|
76
86
  unless lists.include? node.label
77
- leaf = node.leaf
78
- lists += leaf.to_a
87
+ first = node.first
88
+ lists += first.to_a
79
89
  end
80
90
  end
81
91
 
82
92
  lists
83
93
  end
84
94
 
95
+ private
96
+
97
+ def detect_cycles
98
+ @nodes.values.each do |node|
99
+ visited = {}
100
+ visited[node.label] = true
101
+
102
+ current_node = node.next
103
+ while current_node
104
+ raise Frill::CyclicDependency if visited[current_node.label]
105
+ visited[current_node.label] = true
106
+ current_node = current_node.next
107
+ end
108
+
109
+ current_node = node.previous
110
+ while current_node
111
+ raise Frill::CyclicDependency if visited[current_node.label]
112
+ visited[current_node.label] = true
113
+ current_node = current_node.previous
114
+ end
115
+ end
116
+ end
117
+
85
118
  class Node
86
- attr_accessor :parent, :child
119
+ attr_accessor :next, :previous
87
120
  attr_reader :label
88
121
 
89
122
  def initialize(label)
90
123
  @label = label
91
- @parent = nil
92
- @child = nil
124
+ @next = nil
125
+ @previous = nil
93
126
  end
94
127
 
95
128
  def move_before node
96
- parent_node = node.leaf
129
+ next_node = node.first
130
+ previous_node = self.last
97
131
 
98
- parent_node.child = self
99
- self.parent = parent_node
132
+ previous_node.next = next_node
133
+ next_node.previous = previous_node
100
134
  end
101
135
 
102
136
  def move_after node
103
- child_node = node.root
137
+ previous_node = node.last
138
+ first_node = first
104
139
 
105
- self.child = child_node
106
- child.parent = self
140
+ previous_node.next = first_node
141
+ first_node.previous = previous_node
107
142
  end
108
143
 
109
- def leaf
144
+ def first
110
145
  node = nil
111
146
  current_node = self
112
147
 
113
148
  until node
114
- if current_node.child
115
- current_node = current_node.child
149
+ if current_node.previous
150
+ current_node = current_node.previous
116
151
  else
117
152
  node = current_node
118
153
  end
@@ -121,19 +156,19 @@ module Frill
121
156
  node
122
157
  end
123
158
 
124
- def root
159
+ def last
125
160
  current_node = self
126
- root_node = nil
161
+ last_node = nil
127
162
 
128
- until root_node
129
- if current_node.parent
130
- current_node = current_node.parent
163
+ until last_node
164
+ if current_node.next
165
+ current_node = current_node.next
131
166
  else
132
- root_node = current_node
167
+ last_node = current_node
133
168
  end
134
169
  end
135
170
 
136
- root_node
171
+ last_node
137
172
  end
138
173
 
139
174
  def to_a
@@ -143,7 +178,7 @@ module Frill
143
178
 
144
179
  until current_node == nil
145
180
  list << current_node.label
146
- current_node = current_node.parent
181
+ current_node = current_node.next
147
182
  end
148
183
 
149
184
  list
data/spec/frill_spec.rb CHANGED
@@ -71,12 +71,12 @@ describe Frill do
71
71
 
72
72
  describe ".before" do
73
73
  it "inserts the current module before the requested module in Frill's list of decorators" do
74
- Module5.before Module4
75
- Module4.before Module3
76
- Module3.before Module2
77
74
  Module2.before Module1
75
+ Module5.after Module4
76
+ Module3.before Module2
77
+ Module4.before Module3
78
78
 
79
- Frill.decorators.index(Module5).should be < Frill.decorators.index(Module4)
79
+ Frill.decorators.index(Module5).should be > Frill.decorators.index(Module4)
80
80
  Frill.decorators.index(Module3).should be < Frill.decorators.index(Module2)
81
81
  Frill.decorators.index(Module2).should be < Frill.decorators.index(Module1)
82
82
  Frill.decorators.index(Module4).should be < Frill.decorators.index(Module3)
@@ -93,33 +93,33 @@ describe Frill do
93
93
 
94
94
  describe ".before" do
95
95
  it "inserts the current module before the requested module in Frill's list of decorators" do
96
- Frill.decorators.sorted_nodes.should == [Module1, Module2, Module3]
96
+ Frill.decorators.should == [Module1, Module2, Module3]
97
97
 
98
98
  Module1.before Module2
99
- Frill.decorators.sorted_nodes.should == [Module1, Module2, Module3]
99
+ Frill.decorators.should == [Module1, Module2, Module3]
100
100
 
101
101
  Module3.before Module2
102
- Frill.decorators.sorted_nodes.should == [Module3, Module1, Module2]
102
+ Frill.decorators.should == [Module3, Module1, Module2]
103
103
  end
104
104
  end
105
105
 
106
106
  describe ".after" do
107
107
  it "inserts the current module after the requested module in Frill's list of decorators" do
108
- Frill.decorators.sorted_nodes.should == [Module1, Module2, Module3]
108
+ Frill.decorators.should == [Module1, Module2, Module3]
109
109
 
110
110
  Module1.after Module2
111
111
  Module3.after Module2
112
112
 
113
- Frill.decorators.sorted_nodes.first.should == Module2
114
- Frill.decorators.sorted_nodes.last(2).should =~ [Module1, Module3]
113
+ Frill.decorators.first.should == Module2
114
+ Frill.decorators.last(2).should =~ [Module1, Module3]
115
115
  end
116
116
  end
117
117
  end
118
118
 
119
- describe Frill::Graph do
119
+ describe Frill::List do
120
120
  describe "#add" do
121
- it "should add an element to the graph" do
122
- g = Frill::Graph.new
121
+ it "should add an element to the list" do
122
+ g = Frill::List.new
123
123
  g.add "hi"
124
124
  g["hi"].should_not be_nil
125
125
  end
@@ -127,17 +127,28 @@ describe Frill do
127
127
 
128
128
  describe "#move_before(label1, label2)" do
129
129
  it "should move label1 before label2" do
130
- g = Frill::Graph.new
130
+ g = Frill::List.new
131
131
  g.move_before "a", "b"
132
- g.sorted_nodes.should == ["a", "b"]
132
+ g.move_before "c", "d"
133
+ g.move_after "b", "c"
134
+ g.to_a.should == ["c", "d", "a", "b"]
133
135
  end
134
136
  end
135
137
 
136
138
  describe "#move_after(label1, label2)" do
137
139
  it "should move label1 after label2" do
138
- g = Frill::Graph.new
140
+ g = Frill::List.new
139
141
  g.move_after "a", "b"
140
- g.sorted_nodes.should == ["b", "a"]
142
+ g.to_a.should == ["b", "a"]
143
+ end
144
+
145
+ it "should throw exceptions when cycles are detected" do
146
+ g = Frill::List.new
147
+ g.move_before "b", "a"
148
+
149
+ expect {
150
+ g.move_before "a", "b"
151
+ }.to raise_exception(Frill::CyclicDependency)
141
152
  end
142
153
  end
143
154
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: frill
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.4
4
+ version: 0.1.5
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,11 +9,11 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-08-21 00:00:00.000000000 Z
12
+ date: 2012-08-22 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: rails
16
- requirement: &70132147962560 !ruby/object:Gem::Requirement
16
+ requirement: &70245083877380 !ruby/object:Gem::Requirement
17
17
  none: false
18
18
  requirements:
19
19
  - - ~>
@@ -21,10 +21,10 @@ dependencies:
21
21
  version: 3.2.2
22
22
  type: :development
23
23
  prerelease: false
24
- version_requirements: *70132147962560
24
+ version_requirements: *70245083877380
25
25
  - !ruby/object:Gem::Dependency
26
26
  name: rspec
27
- requirement: &70132147962000 !ruby/object:Gem::Requirement
27
+ requirement: &70245083876800 !ruby/object:Gem::Requirement
28
28
  none: false
29
29
  requirements:
30
30
  - - ! '>='
@@ -32,10 +32,10 @@ dependencies:
32
32
  version: '0'
33
33
  type: :development
34
34
  prerelease: false
35
- version_requirements: *70132147962000
35
+ version_requirements: *70245083876800
36
36
  - !ruby/object:Gem::Dependency
37
37
  name: rspec-rails
38
- requirement: &70132147961140 !ruby/object:Gem::Requirement
38
+ requirement: &70245083875880 !ruby/object:Gem::Requirement
39
39
  none: false
40
40
  requirements:
41
41
  - - ! '>='
@@ -43,10 +43,10 @@ dependencies:
43
43
  version: '0'
44
44
  type: :development
45
45
  prerelease: false
46
- version_requirements: *70132147961140
46
+ version_requirements: *70245083875880
47
47
  - !ruby/object:Gem::Dependency
48
48
  name: capybara
49
- requirement: &70132147960500 !ruby/object:Gem::Requirement
49
+ requirement: &70245083875240 !ruby/object:Gem::Requirement
50
50
  none: false
51
51
  requirements:
52
52
  - - ! '>='
@@ -54,10 +54,10 @@ dependencies:
54
54
  version: '0'
55
55
  type: :development
56
56
  prerelease: false
57
- version_requirements: *70132147960500
57
+ version_requirements: *70245083875240
58
58
  - !ruby/object:Gem::Dependency
59
59
  name: pry
60
- requirement: &70132147959960 !ruby/object:Gem::Requirement
60
+ requirement: &70245083874700 !ruby/object:Gem::Requirement
61
61
  none: false
62
62
  requirements:
63
63
  - - ! '>='
@@ -65,7 +65,7 @@ dependencies:
65
65
  version: '0'
66
66
  type: :development
67
67
  prerelease: false
68
- version_requirements: *70132147959960
68
+ version_requirements: *70245083874700
69
69
  description:
70
70
  email: moonmaster9000@gmail.com
71
71
  executables: []