acts_as_graph 0.0.1 → 0.0.3

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: 85713371daed2a84ea58c068c10a373165ad9b3b
4
- data.tar.gz: 448fd7508d466a053e8568e3958326f0115bd68f
2
+ SHA256:
3
+ metadata.gz: 1e2c2c5547d606eb07ee5f497397e85b61e05937a5b4eac9f1641f5a8c5c51ea
4
+ data.tar.gz: f405e59e5356dcf1099f27a7f4b139c7fb1a776ab87109e611caa2b0ba7f152d
5
5
  SHA512:
6
- metadata.gz: da1fe3794e4b6d89fe824908f1d1767e3a45dad7206dcf1cb3b4dee9926ff253c6085e7e3067608f2a795dbee6362463a65fc8dc4cbf8346d33573fb43ff6cc5
7
- data.tar.gz: 6f2f24d36ca3530c70f9d2a3f700e93fcb6b216b6305ee4a4d8e634445273b91427da69745eaa3f12ba0d0117845ad31438ac6367576f7a133649c342fc6a021
6
+ metadata.gz: d9e53a8bbcd9da65eb69e40ad61a0a59f97aca36daf9e94aaf0141bd5aac1bf980495f9f8c5b14f336ac3968e0704d5ffe23cc57166b809ab2b6f68a7a3a4920
7
+ data.tar.gz: 8593e2dd8c8ec45c4942eac7f437a8fa6fdcd5182f4cf5c9d482990aad94872644b93aaebf92f163f31ef41fa8664dceac3a65f4bbc9cb08482da357c93e1afa
@@ -1,12 +1,12 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- acts_as_graph (0.0.1)
5
- rspec
4
+ acts_as_graph (0.0.2)
6
5
 
7
6
  GEM
8
7
  remote: https://rubygems.org/
9
8
  specs:
9
+ byebug (10.0.2)
10
10
  diff-lcs (1.3)
11
11
  rspec (3.7.0)
12
12
  rspec-core (~> 3.7.0)
@@ -27,6 +27,8 @@ PLATFORMS
27
27
 
28
28
  DEPENDENCIES
29
29
  acts_as_graph!
30
+ byebug
31
+ rspec
30
32
 
31
33
  BUNDLED WITH
32
- 1.16.1
34
+ 1.17.2
@@ -9,18 +9,20 @@ Gem::Specification.new do |s|
9
9
  s.platform = Gem::Platform::RUBY
10
10
  s.authors = ['Zhichao Feng']
11
11
  s.email = ['flankerfc@gmail.com']
12
- s.homepage = 'https://github.com/flanker'
12
+ s.homepage = 'https://github.com/flanker/acts_as_graph'
13
13
  s.summary = 'A very simple acts as graph for your model'
14
14
  s.description = 'A very simple acts as graph for your model'
15
15
  s.license = 'MIT'
16
+ s.metadata = {'source_code_uri' => 'https://github.com/flanker/acts_as_graph'}
16
17
 
17
- s.required_ruby_version = '>= 2.3'
18
+ s.required_ruby_version = '>= 2.5'
18
19
  s.required_rubygems_version = '>= 1.3.6'
19
20
 
20
21
  s.files = `git ls-files`.split("\n")
21
22
  s.test_files = `git ls-files -- test/*`.split("\n")
22
23
  s.require_path = ['lib']
23
24
 
24
- s.add_runtime_dependency 'rspec'
25
+ s.add_development_dependency 'rspec'
26
+ s.add_development_dependency 'byebug'
25
27
 
26
28
  end
@@ -1,3 +1,5 @@
1
+ require 'acts_as_graph/dag'
2
+
1
3
  module ActsAsGraph
2
4
 
3
5
  def self.included base
@@ -30,31 +32,33 @@ module ActsAsGraph
30
32
  child_vertices.each do |child_vertice|
31
33
  next if vertices_found.include?(child_vertice) || child_vertice == starting_vertice
32
34
  vertices_found << child_vertice
33
- child_vertice.collect_child_vertices vertices_found, starting_vertice: starting_vertice
35
+ child_vertice.collect_child_vertices vertices_found, starting_vertice: starting_vertice if child_vertice.respond_to?(:collect_child_vertices)
34
36
  end
35
37
  end
36
38
 
37
39
  def has_circular_reference?
38
- vertices_found = []
39
- has_circular_reference_in_child_vertices? vertices_found, starting_vertice: self
40
+ child_vertices.any? do |child_vertice|
41
+ path = [self, child_vertice]
42
+ child_vertice.has_circular_reference_in_path?(path) if child_vertice.respond_to?(:has_circular_reference_in_path?)
43
+ end
40
44
  end
41
45
 
42
- def has_circular_reference_in_child_vertices? vertices_found, starting_vertice: nil
46
+ def has_circular_reference_in_path? path
43
47
  child_vertices.any? do |child_vertice|
44
- return true if vertices_found.include?(child_vertice) || child_vertice == starting_vertice
45
- vertices_found << child_vertice
46
- child_vertice.has_circular_reference_in_child_vertices? vertices_found, starting_vertice: starting_vertice
48
+ return true if path.include?(child_vertice)
49
+ next_path = path + [child_vertice]
50
+ child_vertice.has_circular_reference_in_path?(next_path) if child_vertice.respond_to?(:has_circular_reference_in_path?)
47
51
  end
48
52
  end
49
53
 
54
+ def child_vertices
55
+ self.send children_method_name
56
+ end
57
+
50
58
  private
51
59
 
52
60
  def children_method_name
53
61
  self.class.children_method_name
54
62
  end
55
63
 
56
- def child_vertices
57
- self.send children_method_name
58
- end
59
-
60
64
  end
@@ -0,0 +1,30 @@
1
+ module ActsAsGraph
2
+ class Dag
3
+
4
+ attr_reader :vertices
5
+
6
+ def initialize vertices
7
+ @vertices = vertices
8
+ end
9
+
10
+ def topological_sort
11
+ visited = []
12
+ post_order = []
13
+ vertices.each do |vertice|
14
+ dfs(vertice, visited, post_order) unless visited.include?(vertice)
15
+ end
16
+ post_order
17
+ end
18
+
19
+ private
20
+
21
+ def dfs vertice, visited, post_order
22
+ visited << vertice
23
+ vertice.child_vertices.each do |child_vertice|
24
+ dfs(child_vertice, visited, post_order) unless visited.include?(child_vertice)
25
+ end if vertice.respond_to?(:child_vertices)
26
+ post_order << vertice
27
+ end
28
+
29
+ end
30
+ end
@@ -1,3 +1,3 @@
1
1
  module ActsAsGraph
2
- VERSION = '0.0.1'
2
+ VERSION = '0.0.3'
3
3
  end
@@ -0,0 +1,47 @@
1
+ require 'spec_helper'
2
+
3
+ module ActsAsGraph
4
+ RSpec.describe Dag do
5
+
6
+ class Task
7
+
8
+ include ActsAsGraph
9
+
10
+ acts_as_graph children: :depended_tasks
11
+
12
+ attr_reader :title
13
+ attr_accessor :depended_tasks
14
+
15
+ def initialize title, depended_tasks = []
16
+ @title = title
17
+ @depended_tasks = depended_tasks
18
+ end
19
+
20
+ end
21
+
22
+ it 'sorts as topological order' do
23
+ task_1 = Task.new 'task_1'
24
+ task_2 = Task.new 'task_2'
25
+ task_3 = Task.new 'task_3'
26
+ task_4 = Task.new 'task_4'
27
+ task_5 = Task.new 'task_5'
28
+ task_6 = Task.new 'task_6'
29
+ task_7 = Task.new 'task_7'
30
+ task_8 = Task.new 'task_8'
31
+
32
+ task_2.depended_tasks = [task_1]
33
+ task_3.depended_tasks = [task_2]
34
+ task_4.depended_tasks = [task_2]
35
+ task_6.depended_tasks = [task_5]
36
+ task_7.depended_tasks = [task_3, task_4]
37
+ task_8.depended_tasks = [task_2, task_3]
38
+
39
+ dag = Dag.new [task_8, task_7, task_6, task_5, task_4, task_3, task_2, task_1]
40
+
41
+ result = dag.topological_sort
42
+ expect(result.length).to eq(8)
43
+ expect(result).to match_array([task_1, task_2, task_3, task_8, task_4, task_7, task_5, task_6])
44
+ end
45
+
46
+ end
47
+ end
@@ -18,6 +18,15 @@ RSpec.describe ActsAsGraph do
18
18
 
19
19
  end
20
20
 
21
+ class Job
22
+
23
+ attr_reader :title
24
+
25
+ def initialize title
26
+ @title = title
27
+ end
28
+ end
29
+
21
30
  context '#descendant_depended_tasks' do
22
31
 
23
32
  it 'should get all descendant tasks' do
@@ -57,13 +66,24 @@ RSpec.describe ActsAsGraph do
57
66
  expect(descendant_depended_tasks.length).to eq(5)
58
67
  expect(descendant_depended_tasks).to match_array([task_2, task_3, task_4, task_5, task_6])
59
68
  end
69
+
70
+ it 'supports other type of object as a child' do
71
+ task_1 = Task.new 'task_1'
72
+ task_2 = Task.new 'task_2'
73
+ job_1 = Job.new 'job_1'
74
+ task_1.depended_tasks = [task_2, job_1]
75
+
76
+ descendant_depended_tasks = task_1.descendant_depended_tasks
77
+ expect(descendant_depended_tasks.length).to eq(2)
78
+ expect(descendant_depended_tasks).to match_array([task_2, job_1])
79
+ end
60
80
  end
61
81
 
62
82
  context '#has_circular_reference?' do
63
83
 
64
84
  it 'works if there is no circular reference' do
65
85
  task_1 = Task.new 'task_1'
66
- task_2 = Task.new 'task_2'
86
+ task_2 = Task.new 'task_2', [task_1]
67
87
  task_3 = Task.new 'task_3', [task_1, task_2]
68
88
 
69
89
  expect(task_3.has_circular_reference?).to be false
@@ -83,6 +103,23 @@ RSpec.describe ActsAsGraph do
83
103
  expect(task_3.has_circular_reference?).to be true
84
104
  end
85
105
 
106
+ it 'works if the circular reference has longer path' do
107
+ task_1 = Task.new 'task_1'
108
+ task_2 = Task.new 'task_2'
109
+ task_3 = Task.new 'task_3'
110
+ task_4 = Task.new 'task_4'
111
+
112
+ task_1.depended_tasks = [task_2]
113
+ task_2.depended_tasks = [task_3]
114
+ task_3.depended_tasks = [task_4]
115
+ task_4.depended_tasks = [task_1]
116
+
117
+ expect(task_1.has_circular_reference?).to be true
118
+ expect(task_2.has_circular_reference?).to be true
119
+ expect(task_3.has_circular_reference?).to be true
120
+ expect(task_4.has_circular_reference?).to be true
121
+ end
122
+
86
123
  it 'works if there are two vertices reference with each other' do
87
124
  task_1 = Task.new 'task_1'
88
125
  task_2 = Task.new 'task_2'
@@ -96,6 +133,29 @@ RSpec.describe ActsAsGraph do
96
133
  expect(task_2.has_circular_reference?).to be true
97
134
  expect(task_3.has_circular_reference?).to be true
98
135
  end
136
+
137
+ it 'works in complex case' do
138
+ task_1 = Task.new 'task_1'
139
+ task_2 = Task.new 'task_2'
140
+ task_3 = Task.new 'task_3'
141
+ task_4 = Task.new 'task_4'
142
+
143
+ task_2.depended_tasks = [task_1]
144
+ task_3.depended_tasks = [task_1, task_2]
145
+ task_4.depended_tasks = [task_2, task_3]
146
+
147
+ # expect(task_2.has_circular_reference?).to be false
148
+ # expect(task_3.has_circular_reference?).to be false
149
+ expect(task_4.has_circular_reference?).to be false
150
+ end
151
+
152
+ it 'supports other type of object as a child' do
153
+ task_1 = Task.new 'task_1'
154
+ job_1 = Job.new 'job_1'
155
+ task_1.depended_tasks = [job_1]
156
+
157
+ expect(task_1.has_circular_reference?).to be false
158
+ end
99
159
  end
100
160
 
101
161
  end
@@ -1,5 +1,6 @@
1
1
  require 'bundler/setup'
2
2
  require 'acts_as_graph'
3
+ require 'byebug'
3
4
 
4
5
  RSpec.configure do |config|
5
6
  # Enable flags like --only-failures and --next-failure
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: acts_as_graph
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.1
4
+ version: 0.0.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Zhichao Feng
8
- autorequire:
8
+ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2018-05-10 00:00:00.000000000 Z
11
+ date: 2020-11-06 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rspec
@@ -17,7 +17,21 @@ dependencies:
17
17
  - - ">="
18
18
  - !ruby/object:Gem::Version
19
19
  version: '0'
20
- type: :runtime
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: byebug
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :development
21
35
  prerelease: false
22
36
  version_requirements: !ruby/object:Gem::Requirement
23
37
  requirements:
@@ -38,14 +52,17 @@ files:
38
52
  - Rakefile
39
53
  - acts_as_graph.gemspec
40
54
  - lib/acts_as_graph.rb
55
+ - lib/acts_as_graph/dag.rb
41
56
  - lib/acts_as_graph/version.rb
57
+ - spec/acts_as_graph/dag_spec.rb
42
58
  - spec/acts_as_graph_spec.rb
43
59
  - spec/spec_helper.rb
44
- homepage: https://github.com/flanker
60
+ homepage: https://github.com/flanker/acts_as_graph
45
61
  licenses:
46
62
  - MIT
47
- metadata: {}
48
- post_install_message:
63
+ metadata:
64
+ source_code_uri: https://github.com/flanker/acts_as_graph
65
+ post_install_message:
49
66
  rdoc_options: []
50
67
  require_paths:
51
68
  - lib
@@ -53,16 +70,15 @@ required_ruby_version: !ruby/object:Gem::Requirement
53
70
  requirements:
54
71
  - - ">="
55
72
  - !ruby/object:Gem::Version
56
- version: '2.3'
73
+ version: '2.5'
57
74
  required_rubygems_version: !ruby/object:Gem::Requirement
58
75
  requirements:
59
76
  - - ">="
60
77
  - !ruby/object:Gem::Version
61
78
  version: 1.3.6
62
79
  requirements: []
63
- rubyforge_project:
64
- rubygems_version: 2.6.14
65
- signing_key:
80
+ rubygems_version: 3.0.3
81
+ signing_key:
66
82
  specification_version: 4
67
83
  summary: A very simple acts as graph for your model
68
84
  test_files: []