Skip to content
This repository
Browse code

- Added some tests for node creation through scopes

- Fixed some errors in de README file
  • Loading branch information...
commit 22a19844ef8fa5e407cf3c5e8abdcd3c41a59232 1 parent 2bd091c
Stefan Kroes authored
43 README.rdoc
Source Rendered
@@ -6,17 +6,21 @@ Ancestry allows the records of a ActiveRecord model to be organised in a tree st
6 6
7 7 To apply Ancestry to any ActiveRecord model, follow these simple steps:
8 8
9   -1. Install Gem
  9 +1. Install gem
  10 + - Install gemcutter gem: sudo gem install gemcutter (maybe you need: gem update --system)
  11 + - Add gemcutter.org as default gem source: gem tumble
10 12 - Add to config/environment.rb: config.gem 'ancestry'
11 13 - Install required gems: sudo rake gems:install
12   - - Alternatively: sudo gem install ancestry
  14 + - Alternatively: sudo gem install ancestry
  15 + - If you don't want gemcutter: config.gem 'ancestry', :source => 'gemcutter.org'
  16 + - Alternatively: sudo gem install ancestry --source gemcutter.org
13 17
14   -2. Add Ancestry Column to Your Table
  18 +2. Add ancestry column to your table
15 19 - Create migration: ./script/generate migration add_ancestry_to_[table] ancestry:string
16 20 - Add index to migration: add_index [table], :ancestry / remove_index [table], :ancestry
17 21 - Migrate your database: rake db:migrate
18 22
19   -3. Add Ancestry to Your Model
  23 +3. Add ancestry to your model
20 24 - Add to app/models/[model].rb: acts_as_tree
21 25
22 26 Your model is now a tree!
@@ -52,25 +56,28 @@ To navigate an Ancestry model, use the following methods on any instance / recor
52 56 [subtree] Scopes the model on descendants and itself
53 57 [subtree_ids] Returns a list of all ids in the record's subtree
54 58
55   -= Scopes
  59 += (Named) Scopes
56 60
57 61 Where possible, the navigation methods return scopes instead of records, this means additional ordering, conditions, limits, etc. can be applied and that the result can be either retrieved, counted or checked for existence. For example:
58 62
59 63 node.children.exists?(:name => 'Mary')
60   -
61 64 node.subtree.all(:order => :name, :limit => 10).each do; ...; end
62   -
63 65 node.descendants.count
64 66
65   -= Named Scopes
  67 +For convenience, a couple of named scopes are included at the class level:
66 68
67   -For convenience, a couple of named scopes are included as class level:
  69 +[roots] Only root nodes
  70 +[ancestors_of(node)] Only ancestors of node, node can be either a record or an id
  71 +[children_of(node)] Only children of node, node can be either a record or an id
  72 +[descendants_of(node)] Only descendants of node, node can be either a record or an id
  73 +[siblings_of(node)] Only siblings of node, node can be either a record or an id
68 74
69   -[root] Only root nodes
70   -[ancestor_of(node)] Only ancestors of node, node can be either a record or an id
71   -[child_of(node)] Only children of node, node can be either a record or an id
72   -[descendant_of(node)] Only descendants of node, node can be either a record or an id
73   -[sibling_of(node)] Only siblings of node, node can be either a record or an id
  75 +Thanks to some convenient rails magic, it is even possible to create nodes through the children and siblings scopes:
  76 +
  77 +node.children.create
  78 +node.siblings.create!
  79 +TestNode.children_of(node_id).new
  80 +TestNode.siblings_of(node_id).create
74 81
75 82 = acts_as_tree Options
76 83
@@ -78,9 +85,9 @@ The acts_as_tree methods supports two options:
78 85
79 86 [ancestry_column] Pass in a symbol to instruct Ancestry to use a different column name to store record ancestry
80 87 [orphan_strategy] Instruct Ancestry what to do with children of a node that is destroyed:
81   - [:destroy] All children are destroyed as well (default)
82   - [:rootify] The children of the destroyed node become root nodes
83   - [:restrict] An AncestryException is raised if any children exist
  88 + :destroy All children are destroyed as well (default)
  89 + :rootify The children of the destroyed node become root nodes
  90 + :restrict An AncestryException is raised if any children exist
84 91
85 92 = Arrangement
86 93
@@ -129,7 +136,7 @@ In the example above, the ancestry column is created as a string. This puts a li
129 136
130 137 = Future Work
131 138
132   -I will try to keep Ancestry up to date with changing versions of Rails and Ruby and also with any bug reports I might receive. I will implement new features on request and only as I see fit. Something that definitely needs to be added in the future is constraints on depth, something like: tree_node.subtree.to_depth(4)
  139 +I will try to keep Ancestry up to date with changing versions of Rails and Ruby and also with any bug reports I might receive. I will implement new features on request as I see fit. Something that definitely needs to be added in the future is constraints on depth, something like: tree_node.subtree.to_depth(4)
133 140
134 141 = Feedback
135 142
10 lib/ancestry/acts_as_tree.rb
@@ -29,11 +29,11 @@ def acts_as_tree options = {}
29 29 validates_format_of ancestry_column, :with => /^[0-9]+(\/[0-9]+)*$/, :allow_nil => true
30 30
31 31 # Named scopes
32   - named_scope :root, :conditions => {ancestry_column => nil}
33   - named_scope :ancestor_of, lambda{ |object| {:conditions => to_node(object).ancestor_conditions} }
34   - named_scope :child_of, lambda{ |object| {:conditions => to_node(object).child_conditions} }
35   - named_scope :descendant_of, lambda{ |object| {:conditions => to_node(object).descendant_conditions} }
36   - named_scope :sibling_of, lambda{ |object| {:conditions => to_node(object).sibling_conditions} }
  32 + named_scope :roots, :conditions => {ancestry_column => nil}
  33 + named_scope :ancestors_of, lambda{ |object| {:conditions => to_node(object).ancestor_conditions} }
  34 + named_scope :children_of, lambda{ |object| {:conditions => to_node(object).child_conditions} }
  35 + named_scope :descendants_of, lambda{ |object| {:conditions => to_node(object).descendant_conditions} }
  36 + named_scope :siblings_of, lambda{ |object| {:conditions => to_node(object).sibling_conditions} }
37 37
38 38 # Update descendants with new ancestry before save
39 39 before_save :update_descendants_with_new_ancestry
47 test/acts_as_tree_test.rb
@@ -187,21 +187,21 @@ def test_named_scopes
187 187 roots = setup_test_nodes TestNode, 3, 3
188 188
189 189 # Roots assertion
190   - assert_equal roots.map(&:first), TestNode.root.all
  190 + assert_equal roots.map(&:first), TestNode.roots.all
191 191
192 192 TestNode.all.each do |test_node|
193   - # Assertions for ancestor_of named scope
194   - assert_equal test_node.ancestors, TestNode.ancestor_of(test_node)
195   - assert_equal test_node.ancestors, TestNode.ancestor_of(test_node.id)
196   - # Assertions for child_of named scope
197   - assert_equal test_node.children, TestNode.child_of(test_node)
198   - assert_equal test_node.children, TestNode.child_of(test_node.id)
199   - # Assertions for descendant_of named scope
200   - assert_equal test_node.descendants, TestNode.descendant_of(test_node)
201   - assert_equal test_node.descendants, TestNode.descendant_of(test_node.id)
202   - # Assertions for sibling_of named scope
203   - assert_equal test_node.siblings, TestNode.sibling_of(test_node)
204   - assert_equal test_node.siblings, TestNode.sibling_of(test_node.id)
  193 + # Assertions for ancestors_of named scope
  194 + assert_equal test_node.ancestors, TestNode.ancestors_of(test_node)
  195 + assert_equal test_node.ancestors, TestNode.ancestors_of(test_node.id)
  196 + # Assertions for children_of named scope
  197 + assert_equal test_node.children, TestNode.children_of(test_node)
  198 + assert_equal test_node.children, TestNode.children_of(test_node.id)
  199 + # Assertions for descendants_of named scope
  200 + assert_equal test_node.descendants, TestNode.descendants_of(test_node)
  201 + assert_equal test_node.descendants, TestNode.descendants_of(test_node.id)
  202 + # Assertions for siblings_of named scope
  203 + assert_equal test_node.siblings, TestNode.siblings_of(test_node)
  204 + assert_equal test_node.siblings, TestNode.siblings_of(test_node.id)
205 205 end
206 206 end
207 207
@@ -259,7 +259,7 @@ def test_orphan_destroy_strategy
259 259 assert_difference 'TestNode.count', -root.subtree.size do
260 260 root.destroy
261 261 end
262   - node = TestNode.root.first.children.first
  262 + node = TestNode.roots.first.children.first
263 263 assert_difference 'TestNode.count', -node.subtree.size do
264 264 node.destroy
265 265 end
@@ -268,7 +268,7 @@ def test_orphan_destroy_strategy
268 268 def test_orphan_restrict_strategy
269 269 TestNode.orphan_strategy = :restrict
270 270 setup_test_nodes(TestNode, 3, 3)
271   - root = TestNode.root.first
  271 + root = TestNode.roots.first
272 272 assert_raise Ancestry::AncestryException do
273 273 root.destroy
274 274 end
@@ -357,4 +357,21 @@ def test_arrangement
357 357 end
358 358 end
359 359 end
  360 +
  361 + def test_node_creation_though_scope
  362 + node = TestNode.create!
  363 + child = node.children.create
  364 + assert_equal node, child.parent
  365 +
  366 + other_child = child.siblings.create!
  367 + assert_equal node, other_child.parent
  368 +
  369 + grandchild = TestNode.children_of(child).new
  370 + grandchild.save
  371 + assert_equal child, grandchild.parent
  372 +
  373 + other_grandchild = TestNode.siblings_of(grandchild).new
  374 + other_grandchild.save!
  375 + assert_equal child, other_grandchild.parent
  376 + end
360 377 end
4 test/database.yml
... ... @@ -1,9 +1,9 @@
1 1 sqlite:
2 2 adapter: sqlite
3   - dbfile: vendor/plugins/ancestry/test/ancestry_plugin.sqlite.db
  3 + database: vendor/plugins/ancestry/test/ancestry_plugin.sqlite.db
4 4 sqlite3:
5 5 adapter: sqlite3
6   - dbfile: vendor/plugins/ancestry/test/ancestry_plugin.sqlite3.db
  6 + database: vendor/plugins/ancestry/test/ancestry_plugin.sqlite3.db
7 7 postgresql:
8 8 adapter: postgresql
9 9 username: ancestry_plugin_test

0 comments on commit 22a1984

Please sign in to comment.
Something went wrong with that request. Please try again.