Skip to content

Commit f400efc

Browse files
committed
Implements optional counter caching via and additional module
1 parent 0087637 commit f400efc

File tree

4 files changed

+67
-1
lines changed

4 files changed

+67
-1
lines changed

lib/mongoid/tree.rb

+1
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,7 @@ module Tree
8383

8484
autoload :Ordering, 'mongoid/tree/ordering'
8585
autoload :Traversal, 'mongoid/tree/traversal'
86+
autoload :CounterCaching, 'mongoid/tree/counter_caching'
8687

8788
included do
8889
has_many :children, :class_name => self.name, :foreign_key => :parent_id, :inverse_of => :parent, :validate => false

lib/mongoid/tree/counter_caching.rb

+22
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
module Mongoid
2+
module Tree
3+
##
4+
# = Mongoid::Tree::CounterCaching
5+
#
6+
# Mongoid::Tree doesn't use a counter cache for the children by default.
7+
# To enable counter caching for each node's children, include
8+
# both Mongoid::Tree and Mongoid::Tree::CounterCaching into your document.
9+
module CounterCaching
10+
extend ActiveSupport::Concern
11+
12+
included do
13+
field :children_count, :type => Integer, :default => 0
14+
15+
metadata = relations['parent']
16+
metadata.options[:counter_cache] = true
17+
18+
add_counter_cache_callbacks(metadata)
19+
end
20+
end
21+
end
22+
end
+39
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
require 'spec_helper'
2+
3+
describe Mongoid::Tree::CounterCaching do
4+
5+
subject { CounterCachedNode }
6+
7+
before do
8+
setup_tree <<-ENDTREE
9+
node1:
10+
- node2:
11+
- node3
12+
- node4:
13+
- node5
14+
- node6
15+
- node7
16+
ENDTREE
17+
end
18+
19+
context 'when a child gets created' do
20+
it 'should calculate the counter cache' do
21+
expect(node(:node1).children_count).to eq(3)
22+
end
23+
end
24+
25+
context 'when a child gets destroyed' do
26+
it 'should update the counter cache' do
27+
node(:node4).destroy
28+
expect(node(:node1).children_count).to eq(2)
29+
end
30+
end
31+
32+
context 'when a child gets moved' do
33+
it 'should update the counter cache' do
34+
node(:node6).update(parent: node(:node1))
35+
expect(node(:node4).children_count).to eq(1)
36+
expect(node(:node1).children_count).to eq(4)
37+
end
38+
end
39+
end

spec/support/models/node.rb

+5-1
Original file line numberDiff line numberDiff line change
@@ -29,4 +29,8 @@ class NodeWithEmbeddedDocument < Node
2929

3030
class EmbeddedDocument
3131
include Mongoid::Document
32-
end
32+
end
33+
34+
class CounterCachedNode < Node
35+
include Mongoid::Tree::CounterCaching
36+
end

0 commit comments

Comments
 (0)