dagnabit 2.2.1 → 2.2.2

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,9 +1,3 @@
1
- = This is the GitHub branch
2
-
3
- This branch is updated irregularly. The canonical dagnabit repository is hosted on Gitorious:
4
-
5
- http://gitorious.org/dagnabit/dagnabit
6
-
7
1
  = dagnabit
8
2
 
9
3
  dagnabit is (yet another) ActiveRecord plugin for directed acyclic graphs. It
@@ -83,6 +77,9 @@ In your node models, put
83
77
  +acts_as_dag_link+ accepts some configuration options. These configuration
84
78
  options are discussed below.
85
79
 
80
+ For a code example of a complete setup, see the <tt>dagnabit-test</tt> script
81
+ in +bin+.
82
+
86
83
  === Link table schemas
87
84
 
88
85
  Link storage is accomplished with two tables having identical schemas. One
@@ -109,6 +106,9 @@ The behavior of the plugin with a deviant schema is unspecified.
109
106
  * +transitive_closure_table_name+: The table where tuples in the transitive
110
107
  closure of the graph should be stored. Defaults to
111
108
  <tt>#{link_table_name}_transitive_closure_tuples</tt>.
109
+ * +transitive_closure_class_name+: The transitive closure is represented with
110
+ an ActiveRecord class whose name defaults to +TransitiveClosureLink+. Set this
111
+ option to change that name.
112
112
  * +descendant_id_column+: Column in the link tables for recording the ID of a
113
113
  descendant. Defaults to +descendant_id+.
114
114
  * +ancestor_id_column+: Column in the link tables for recording the ID of a
@@ -146,22 +146,20 @@ edge model was called +Link+, these would be valid expressions:
146
146
 
147
147
  +acts_as_dag_node+ adds the following instance methods to nodes:
148
148
 
149
- * +descendants+: All descendants of the node. Read-only.
149
+ * +children+: All children of the node. Read-only.
150
+ * +parents+: All parents of the node. Read-only.
150
151
  * +ancestors+: All ancestors of the node. Read-only.
152
+ * +descendants+: All descendants of the node. Read-only.
151
153
 
152
154
  === Link interface
153
155
 
154
156
  The following class methods are available on links:
155
157
 
156
158
  * +paths+: Retrieves all paths from one node to another.
157
- * +path+: Returns whether a node is reachable from another node.
158
- * +find_edge+: Finds an edge from one node to another, or nil if none exists.
159
+ * <tt>path?</tt>: Returns whether a node is reachable from another node.
159
160
  * +build_edge+: Builds an edge from one node to another node.
160
161
  * +connect+: Builds and saves an edge from one node to another. Identical to
161
162
  <tt>build_edge(nodeA, nodeB).save</tt>.
162
- * <tt>connect!</tt>: Builds and saves an edge from one node to another, raising
163
- an exception if save fails. Identical to <tt>build_edge(nodeA,
164
- nodeB).save!</tt>.
165
163
 
166
164
  == Introduction to the codebase
167
165
 
@@ -1,5 +1,5 @@
1
1
  ---
2
2
  :major: 2
3
3
  :minor: 2
4
- :patch: 1
4
+ :patch: 2
5
5
  :build:
@@ -6,7 +6,7 @@
6
6
  #
7
7
 
8
8
  require 'rubygems'
9
- require 'activerecord'
9
+ require 'active_record'
10
10
 
11
11
  src = File.dirname(__FILE__) + '/../lib/dagnabit.rb'
12
12
  if File.exists?(src)
@@ -5,11 +5,11 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = %q{dagnabit}
8
- s.version = "2.2.1"
8
+ s.version = "2.2.2"
9
9
 
10
10
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
11
  s.authors = ["David Yip"]
12
- s.date = %q{2009-12-07}
12
+ s.date = %q{2010-02-04}
13
13
  s.default_executable = %q{dagnabit-test}
14
14
  s.email = %q{yipdw@northwestern.edu}
15
15
  s.executables = ["dagnabit-test"]
@@ -75,7 +75,9 @@ Gem::Specification.new do |s|
75
75
  s.rubygems_version = %q{1.3.5}
76
76
  s.summary = %q{Directed acyclic graph plugin for ActiveRecord}
77
77
  s.test_files = [
78
- "test/connections/native_postgresql/connection.rb",
78
+ "test/benchmark/helper.rb",
79
+ "test/benchmark/linear_benchmark.rb",
80
+ "test/connections/native_postgresql/connection.rb",
79
81
  "test/connections/native_sqlite3/connection.rb",
80
82
  "test/dagnabit/link/test_associations.rb",
81
83
  "test/dagnabit/link/test_class_methods.rb",
@@ -3,7 +3,11 @@ module Dagnabit
3
3
  module TransitiveClosureRecalculation
4
4
  module OnUpdate
5
5
  def after_update
6
+ current_values = dag_link_column_names.map { |n| connection.quote(send(n)) }
6
7
  old_values = dag_link_column_names.map { |n| connection.quote(changes[n].try(:first) || send(n)) }
8
+
9
+ return unless current_values != old_values
10
+
7
11
  update_transitive_closure_for_destroy(*old_values)
8
12
  update_transitive_closure_for_create
9
13
  end
@@ -0,0 +1,43 @@
1
+ require 'rubygems'
2
+ require 'test/unit'
3
+ require 'active_record'
4
+ require 'active_support/test_case'
5
+
6
+ $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
7
+ $LOAD_PATH.unshift(File.dirname(__FILE__))
8
+ require 'dagnabit'
9
+
10
+ ActiveRecord::Base.logger = Logger.new("benchmark.log")
11
+ ActiveRecord::Base.establish_connection(:adapter => 'sqlite3', :database => ':memory:')
12
+
13
+ ActiveRecord::Schema.define do
14
+ [:links, :links_transitive_closure_tuples].each do |table|
15
+ create_table table do |t|
16
+ t.integer :ancestor_id
17
+ t.integer :descendant_id
18
+ t.string :ancestor_type
19
+ t.string :descendant_type
20
+ end
21
+ end
22
+
23
+ create_table :nodes do |t|
24
+ t.string :data
25
+ end
26
+ end
27
+
28
+ class Link < ActiveRecord::Base
29
+ acts_as_dag_link
30
+ end
31
+
32
+ class Node < ActiveRecord::Base
33
+ acts_as_dag_node_linked_by 'Link'
34
+ end
35
+
36
+ REPETITIONS = 5
37
+
38
+ class BenchmarkTestCase < ActiveSupport::TestCase
39
+ def teardown
40
+ Node.delete_all
41
+ Link.delete_all
42
+ end
43
+ end
@@ -0,0 +1,41 @@
1
+ require File.dirname(__FILE__) + '/helper'
2
+
3
+ class LinearBenchmark < BenchmarkTestCase
4
+ def test_speed
5
+ Benchmark.bm do |x|
6
+ root = Node.create
7
+ last_node = root
8
+
9
+ 100.times do |i|
10
+ target = Node.create
11
+
12
+ x.report("Graph depth: #{i+1}") { Link.connect(last_node, target) }
13
+
14
+ assert_equal 1, last_node.children.length
15
+ assert_equal i+1, root.descendants.length
16
+
17
+ last_node = target
18
+ end
19
+ end
20
+ end
21
+
22
+ def test_deletion_from_long_list
23
+ nodes = []
24
+ last_node = Node.create
25
+
26
+ puts 'Building long list...'
27
+ 50.times do |i|
28
+ target = Node.create
29
+ Link.connect(last_node, target)
30
+ last_node = target
31
+
32
+ nodes << target
33
+ end
34
+
35
+ Benchmark.bm do |x|
36
+ nodes.each_with_index do |node, i|
37
+ x.report("Destroying node #{i}") { node.destroy }
38
+ end
39
+ end
40
+ end
41
+ end
@@ -134,6 +134,17 @@ module Dagnabit
134
134
  tc = CustomTransitiveClosureLink.find(:first, :conditions => { :the_ancestor_id => n1.id, :the_descendant_id => n3.id })
135
135
  assert_nil tc, 'expected to not find path from n1 to n3'
136
136
  end
137
+
138
+ should "not recalculate transitive closure if neither a link's source nor target changed" do
139
+ n1 = ::Node.create
140
+ n2 = ::Node.create
141
+
142
+ l1 = ::Link.new(:ancestor => n1, :descendant => n2)
143
+
144
+ l1.expects(:update_transitive_closure_for_destroy).never
145
+ l1.save
146
+ l1.save
147
+ end
137
148
  end
138
149
  end
139
150
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: dagnabit
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.2.1
4
+ version: 2.2.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - David Yip
@@ -9,7 +9,7 @@ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
11
 
12
- date: 2009-12-07 00:00:00 -06:00
12
+ date: 2010-02-04 00:00:00 -06:00
13
13
  default_executable: dagnabit-test
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
@@ -141,6 +141,8 @@ signing_key:
141
141
  specification_version: 3
142
142
  summary: Directed acyclic graph plugin for ActiveRecord
143
143
  test_files:
144
+ - test/benchmark/helper.rb
145
+ - test/benchmark/linear_benchmark.rb
144
146
  - test/connections/native_postgresql/connection.rb
145
147
  - test/connections/native_sqlite3/connection.rb
146
148
  - test/dagnabit/link/test_associations.rb