-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
First version of acts_as_graph_vertex!
- Loading branch information
1 parent
2db6004
commit c3ed1ea
Showing
10 changed files
with
403 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
.DS_Store | ||
*.gem | ||
coverage |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
require: rubocop-rspec | ||
|
||
LineLength: | ||
Max: 120 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
language: ruby | ||
rvm: | ||
- 2.2.0 | ||
script: bundle exec rspec && bundle exec rubocop |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
source 'https://rubygems.org' | ||
|
||
gemspec |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,89 @@ | ||
PATH | ||
remote: . | ||
specs: | ||
acts_as_graph_vertex (1.0.0) | ||
|
||
GEM | ||
remote: https://rubygems.org/ | ||
specs: | ||
ast (2.0.0) | ||
astrolabe (1.3.0) | ||
parser (>= 2.2.0.pre.3, < 3.0) | ||
byebug (3.5.1) | ||
columnize (~> 0.8) | ||
debugger-linecache (~> 1.2) | ||
slop (~> 3.6) | ||
coderay (1.1.0) | ||
columnize (0.9.0) | ||
coveralls (0.7.8) | ||
multi_json (~> 1.10) | ||
rest-client (~> 1.7) | ||
simplecov (~> 0.9.1) | ||
term-ansicolor (~> 1.3) | ||
thor (~> 0.19.1) | ||
debugger-linecache (1.2.0) | ||
diff-lcs (1.2.5) | ||
docile (1.1.5) | ||
filewatcher (0.3.6) | ||
trollop (~> 2.0) | ||
method_source (0.8.2) | ||
mime-types (2.4.3) | ||
multi_json (1.10.1) | ||
netrc (0.10.2) | ||
parser (2.2.0.2) | ||
ast (>= 1.1, < 3.0) | ||
powerpack (0.0.9) | ||
pry (0.10.1) | ||
coderay (~> 1.1.0) | ||
method_source (~> 0.8.1) | ||
slop (~> 3.4) | ||
pry-byebug (2.0.0) | ||
byebug (~> 3.4) | ||
pry (~> 0.10) | ||
rainbow (2.0.0) | ||
rest-client (1.7.2) | ||
mime-types (>= 1.16, < 3.0) | ||
netrc (~> 0.7) | ||
rspec (3.1.0) | ||
rspec-core (~> 3.1.0) | ||
rspec-expectations (~> 3.1.0) | ||
rspec-mocks (~> 3.1.0) | ||
rspec-core (3.1.7) | ||
rspec-support (~> 3.1.0) | ||
rspec-expectations (3.1.2) | ||
diff-lcs (>= 1.2.0, < 2.0) | ||
rspec-support (~> 3.1.0) | ||
rspec-mocks (3.1.3) | ||
rspec-support (~> 3.1.0) | ||
rspec-support (3.1.2) | ||
rubocop (0.28.0) | ||
astrolabe (~> 1.3) | ||
parser (>= 2.2.0.pre.7, < 3.0) | ||
powerpack (~> 0.0.6) | ||
rainbow (>= 1.99.1, < 3.0) | ||
ruby-progressbar (~> 1.4) | ||
rubocop-rspec (1.2.1) | ||
ruby-progressbar (1.7.1) | ||
simplecov (0.9.1) | ||
docile (~> 1.1.0) | ||
multi_json (~> 1.0) | ||
simplecov-html (~> 0.8.0) | ||
simplecov-html (0.8.0) | ||
slop (3.6.0) | ||
term-ansicolor (1.3.0) | ||
tins (~> 1.0) | ||
thor (0.19.1) | ||
tins (1.3.3) | ||
trollop (2.1.1) | ||
|
||
PLATFORMS | ||
ruby | ||
|
||
DEPENDENCIES | ||
acts_as_graph_vertex! | ||
coveralls (~> 0.7) | ||
filewatcher (~> 0.3) | ||
pry-byebug (~> 2.0) | ||
rspec (~> 3.1) | ||
rubocop (~> 0.28) | ||
rubocop-rspec (~> 1.2) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,80 @@ | ||
# acts_as_graph_vertex [![Build Status](https://travis-ci.org/nathankleyn/acts_as_graph_vertex.svg?branch=master)](https://travis-ci.org/nathankleyn/acts_as_graph_vertex) [![Coverage Status](https://coveralls.io/repos/nathankleyn/acts_as_graph_vertex/badge.png?branch=master)](https://coveralls.io/r/nathankleyn/acts_as_graph_vertex?branch=master) | ||
|
||
Simple mixin for adding graph like functions (parents, children, traversal, etc) to any class. | ||
|
||
## Installing | ||
|
||
You can install this gem via RubyGems: | ||
|
||
```sh | ||
gem install acts_as_graph_vertex | ||
``` | ||
|
||
## Using | ||
|
||
Sometimes it's useful to be able to add graph like functionality to existing classes you have. This is where acts_as_graph_vertex comes in! Simply mixin this module, and you'll get basic directed acyclic graph (DAG) functionality for free: | ||
|
||
```ruby | ||
require 'acts_as_graph_vertex' | ||
|
||
class MyAmazingClass | ||
include ActsAsGraphVertex | ||
end | ||
``` | ||
|
||
And now you can use the functions: | ||
|
||
```ruby | ||
parent = MyAmazingClass.new | ||
child1 = MyAmazingClass.new | ||
child2 = MyAmazingClass.new | ||
child3 = MyAmazingClass.new | ||
|
||
# The following calls will create a DAG like the following: | ||
# | ||
# --> child1 -- | ||
# / \ | ||
# parent-- --> child3 | ||
# \ / | ||
# --> child2 -- | ||
|
||
parent.add_child(child1) | ||
child2.add_parent(child1) | ||
child3.add_parent(child1) | ||
child3.add_parent(child2) | ||
``` | ||
|
||
You can now traverse the graph from any of these vertices: | ||
|
||
```ruby | ||
parent.children # => [child1, child2] | ||
parent.all_children # => [child1, child2, child3] | ||
child3.parents # => [child1, child2] | ||
child3.all_parents # => [child1, child2, parent] | ||
``` | ||
|
||
Note that this mixin does not currently prevent or handle cyclic dependencies; it's intended to be simple rather than exhaustive. If cycle detection is required, using something as a layer over this mixin such as Tarjan's algorithm for finding strongly connected components of a graph is recommended. Tarjan's algorithm is bundled with the Ruby standard library as `TSort` (despite the naming, this class does not provide topographic sorting). | ||
|
||
## License | ||
|
||
The MIT License (MIT) | ||
|
||
Copyright (c) 2015 Nathan Kleyn | ||
|
||
Permission is hereby granted, free of charge, to any person obtaining a copy | ||
of this software and associated documentation files (the "Software"), to deal | ||
in the Software without restriction, including without limitation the rights | ||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||
copies of the Software, and to permit persons to whom the Software is | ||
furnished to do so, subject to the following conditions: | ||
|
||
The above copyright notice and this permission notice shall be included in | ||
all copies or substantial portions of the Software. | ||
|
||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN | ||
THE SOFTWARE. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
$LOAD_PATH.unshift(File.join(__dir__, 'lib')) | ||
|
||
Gem::Specification.new do |gem| | ||
gem.name = 'acts_as_graph_vertex' | ||
gem.version = '1.0.0' | ||
gem.homepage = 'https://github.com/nathankleyn/acts_as_graph_vertex' | ||
gem.license = 'MIT' | ||
|
||
gem.authors = [ | ||
'Nathan Kleyn' | ||
] | ||
gem.email = [ | ||
'nathan@nathankleyn.com' | ||
] | ||
gem.summary = 'Simple mixin for adding graph like functions (parents, children, traversal, etc) to any class.' | ||
gem.description = "See #{gem.homepage} for more information!" | ||
|
||
gem.files = Dir['**/*'].select { |d| d =~ /^(README.md|lib\/)/ } | ||
|
||
gem.add_development_dependency 'coveralls', '~> 0.7' | ||
gem.add_development_dependency 'filewatcher', '~> 0.3' | ||
gem.add_development_dependency 'pry-byebug', '~> 2.0' | ||
gem.add_development_dependency 'rspec', '~> 3.1' | ||
gem.add_development_dependency 'rubocop', '~> 0.28' | ||
gem.add_development_dependency 'rubocop-rspec', '~> 1.2' | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,75 @@ | ||
# A mixin module enabling classes to have parents and children. It provides | ||
# convenience methods for determining dependencies, and depdenants. | ||
# | ||
# Note that in contrast to a tree, this graph module allows multiple parents. | ||
module ActsAsGraphVertex | ||
# The self.included idiom. This is described in great detail in a | ||
# fantastic blog post here: | ||
# | ||
# http://www.railstips.org/blog/archives/2009/05/15/include-vs-extend-in-ruby/ | ||
# | ||
# Basically, this idiom allows us to add both instance *and* class methods | ||
# to the class that is mixing this module into itself without forcing them | ||
# to call extend and include for this mixin. You'll see this idiom everywhere | ||
# in the Ruby/Rails world, so we use it too. | ||
def self.included(cls) | ||
cls.extend(ClassMethods) | ||
end | ||
|
||
# Common methods inherited by all classes | ||
module ClassMethods | ||
attr_writer :parents, :children | ||
end | ||
|
||
# Public: The parents linked to this instance. | ||
# | ||
# Returns an Array of Objects. | ||
def parents | ||
@parents ||= [] | ||
end | ||
|
||
# Public: The children linked to this instance. | ||
# | ||
# Returns an Array of Objects. | ||
def children | ||
@children ||= [] | ||
end | ||
|
||
# Public: Add a vertex to the parents linked to this instance. Will automatically add as a child of the given parent | ||
# if the given parent also mixes in the graph functionality. | ||
# | ||
# vertex - The Object to add as a parent. | ||
# add_child - Whether to add this item as a child of the given parent. | ||
def add_parent(vertex, add_child = true) | ||
return if parents.include?(vertex) | ||
vertex.add_child(self, false) if add_child && vertex.respond_to?(:add_child) | ||
parents << vertex | ||
end | ||
|
||
# Public: Add a vertex to the children linked to this instance. Will automatically add as a parent of the given child | ||
# if the given child also mixes in the graph functionality. | ||
# | ||
# vertex - The Object to add as a child. | ||
# add_parent - Whether to add this item as a parent of the given child. | ||
def add_child(vertex, add_parent = true) | ||
return if children.include?(vertex) | ||
vertex.add_parent(self, false) if add_parent && vertex.respond_to?(:add_parent) | ||
children << vertex | ||
end | ||
|
||
# Public: Convenience method to return all of the parents from this vertex in | ||
# the tree upwards to the root of the tree. | ||
# | ||
# Returns an Array of parent Objects. | ||
def all_parents | ||
((parents + parents.map(&:all_parents)).flatten).uniq | ||
end | ||
|
||
# Public: Convenience method to return all of the children from this vertex in | ||
# the tree downwards to the leaves of the tree. | ||
# | ||
# Returns an Array of child Objects. | ||
def all_children | ||
(children + children.map(&:all_children).flatten).uniq | ||
end | ||
end |
Oops, something went wrong.