has_hierarchy 0.3.0 → 0.3.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +8 -0
- data/README.md +3 -2
- data/lib/has_hierarchy.rb +32 -4
- data/lib/has_hierarchy/depth_cache.rb +0 -6
- data/lib/has_hierarchy/path.rb +9 -15
- data/lib/has_hierarchy/version.rb +1 -1
- data/spec/has_hierarchy_spec.rb +16 -1
- data/spec/support/models.rb +3 -2
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 5ff1f9affc659f62ba4a9b6eb0f25309b980939f
|
4
|
+
data.tar.gz: 4de2b383019e35c329b4bb11a3e7c39f1a5b2207
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 8748539cfaf294108ff6d4e3bbf443dd42320171f5e89a0982b00b4aa32f4e6f255b6f3fa0a3726b970b5e7cf6b1b02a48e8bd0e203d892127547afb82c99567
|
7
|
+
data.tar.gz: edc08f4f3e803bf13f4d9b8dfd84cd4b690489ddab3daf3f3a39aea833fe44d93a506b50d0319a970f9dacc91b45722b3768b321023ba7ab7dda4246dc169a87
|
data/CHANGELOG.md
CHANGED
data/README.md
CHANGED
@@ -32,7 +32,8 @@ $ rails g model Item \
|
|
32
32
|
```ruby
|
33
33
|
class Item < ActiveRecord::Base
|
34
34
|
has_hierarchy path_part: :name,
|
35
|
-
|
35
|
+
depth_cache: true,
|
36
|
+
counter_cache: true,
|
36
37
|
dependent: :destroy
|
37
38
|
end
|
38
39
|
|
@@ -71,7 +72,7 @@ Item.ordered.tree
|
|
71
72
|
# }
|
72
73
|
# }
|
73
74
|
|
74
|
-
Item.
|
75
|
+
Item.find_by_path('bar/qux/quux')
|
75
76
|
# => quux
|
76
77
|
```
|
77
78
|
|
data/lib/has_hierarchy.rb
CHANGED
@@ -5,14 +5,25 @@ require 'has_hierarchy/path'
|
|
5
5
|
require 'has_hierarchy/depth_cache'
|
6
6
|
|
7
7
|
module HasHierarchy
|
8
|
-
|
9
|
-
|
8
|
+
DEFAULT_OPTIONS = {
|
9
|
+
scope: nil,
|
10
|
+
order: :position,
|
11
|
+
path_cache: :path,
|
12
|
+
path_part: :id,
|
13
|
+
path_separator: '/',
|
14
|
+
depth_cache: :depth,
|
15
|
+
counter_cache: :children_count,
|
16
|
+
dependent: nil
|
17
|
+
}
|
10
18
|
|
19
|
+
def has_hierarchy(options = {})
|
11
20
|
extend ClassMethods
|
12
21
|
include InstanceMethods
|
13
22
|
|
14
|
-
|
15
|
-
|
23
|
+
setup_has_hierarchy_options(options)
|
24
|
+
|
25
|
+
include Order if options[:order]
|
26
|
+
include Path if options[:path_cache]
|
16
27
|
include DepthCache if options[:depth_cache]
|
17
28
|
|
18
29
|
belongs_to :parent, class_name: self.name,
|
@@ -47,6 +58,23 @@ module HasHierarchy
|
|
47
58
|
|
48
59
|
protected
|
49
60
|
|
61
|
+
def setup_has_hierarchy_options(options)
|
62
|
+
options.assert_valid_keys(DEFAULT_OPTIONS.keys)
|
63
|
+
|
64
|
+
# Set to false if nil.
|
65
|
+
options.reverse_merge!(depth_cache: false, counter_cache: false)
|
66
|
+
|
67
|
+
DEFAULT_OPTIONS.each do |key, value|
|
68
|
+
options[key] = value if options[key].nil? or options[key] == true
|
69
|
+
end
|
70
|
+
|
71
|
+
cattr_accessor(:path_column) { options[:path_cache] }
|
72
|
+
cattr_accessor(:path_part_column) { options[:path_part] }
|
73
|
+
cattr_accessor(:path_separator) { options[:path_separator] }
|
74
|
+
cattr_accessor(:depth_column) { options[:depth_cache] }
|
75
|
+
cattr_accessor(:has_hierarchy_options) { options }
|
76
|
+
end
|
77
|
+
|
50
78
|
def define_tree_scope(tree_scope)
|
51
79
|
scope :tree_scope, case tree_scope
|
52
80
|
when Proc
|
data/lib/has_hierarchy/path.rb
CHANGED
@@ -5,31 +5,21 @@ module HasHierarchy
|
|
5
5
|
included do
|
6
6
|
before_create :populate_path
|
7
7
|
before_update :rebuild_subtree, if: :need_to_rebuild_subtree?
|
8
|
-
|
9
|
-
cattr_accessor :path_column do
|
10
|
-
column = has_hierarchy_options[:path_cache]
|
11
|
-
column = :path if column.nil? or column == true
|
12
|
-
column
|
13
|
-
end
|
14
|
-
|
15
|
-
cattr_accessor :path_separator do
|
16
|
-
has_hierarchy_options[:path_separator] || '/'
|
17
|
-
end
|
18
|
-
|
19
|
-
cattr_accessor :path_part_column do
|
20
|
-
has_hierarchy_options[:path_part] || :id
|
21
|
-
end
|
22
8
|
end
|
23
9
|
|
24
10
|
module ClassMethods
|
25
11
|
def find_by_path(path)
|
26
12
|
sep = path_separator
|
27
|
-
parts = path.split(sep)
|
13
|
+
parts = path.gsub(/\#{sep}*$/, '').split(sep)
|
28
14
|
part = parts.pop
|
29
15
|
path = parts.length > 0 ? parts.join(sep) + sep : ''
|
30
16
|
|
31
17
|
where(path_part_column => part, path_column => path).first
|
32
18
|
end
|
19
|
+
|
20
|
+
def find_by_path!(path)
|
21
|
+
find_by_path(path) or raise ActiveRecord::RecordNotFound
|
22
|
+
end
|
33
23
|
end
|
34
24
|
|
35
25
|
def root
|
@@ -72,6 +62,10 @@ module HasHierarchy
|
|
72
62
|
self[path_column] = path
|
73
63
|
end
|
74
64
|
|
65
|
+
def full_path
|
66
|
+
path + path_part
|
67
|
+
end
|
68
|
+
|
75
69
|
protected
|
76
70
|
|
77
71
|
def path_part
|
data/spec/has_hierarchy_spec.rb
CHANGED
@@ -110,11 +110,26 @@ shared_examples 'materialized path' do
|
|
110
110
|
describe '.find_by_path' do
|
111
111
|
it 'returns node' do
|
112
112
|
expect(described_class.find_by_path('bar')).to eq(bar)
|
113
|
-
expect(described_class.find_by_path('bar/qux')).to eq(qux)
|
113
|
+
expect(described_class.find_by_path('bar/qux/')).to eq(qux)
|
114
114
|
expect(described_class.find_by_path('bar/qux/quux')).to eq(quux)
|
115
115
|
end
|
116
116
|
end
|
117
117
|
|
118
|
+
describe '.find_by_path!' do
|
119
|
+
it 'returns node or raises RecordNotFound' do
|
120
|
+
expect(described_class.find_by_path!('bar/qux/')).to eq(qux)
|
121
|
+
expect{ described_class.find_by_path!('wrong') }.to raise_error(ActiveRecord::RecordNotFound)
|
122
|
+
end
|
123
|
+
end
|
124
|
+
|
125
|
+
describe '#full_path' do
|
126
|
+
it 'returns full node path' do
|
127
|
+
expect(bar.full_path).to eq('bar')
|
128
|
+
expect(qux.full_path).to eq('bar/qux')
|
129
|
+
expect(quux.full_path).to eq('bar/qux/quux')
|
130
|
+
end
|
131
|
+
end
|
132
|
+
|
118
133
|
describe '#root' do
|
119
134
|
it 'returns first node ancestor' do
|
120
135
|
expect(baz.root).to eq(bar)
|
data/spec/support/models.rb
CHANGED
@@ -6,7 +6,8 @@ end
|
|
6
6
|
|
7
7
|
class AdjacencyListTreeItem < Item
|
8
8
|
has_hierarchy counter_cache: :children_count,
|
9
|
-
path_cache: false
|
9
|
+
path_cache: false,
|
10
|
+
order: true
|
10
11
|
end
|
11
12
|
|
12
13
|
class MaterializedPathTreeItem < Item
|
@@ -24,6 +25,6 @@ end
|
|
24
25
|
|
25
26
|
class ScopedWithLambdaTreeItem < Item
|
26
27
|
has_hierarchy scope: ->(item){ where(category: item.category) },
|
27
|
-
#
|
28
|
+
# parent_id scope cannot be combined with lambda.
|
28
29
|
order: false
|
29
30
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: has_hierarchy
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.3.
|
4
|
+
version: 0.3.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Kolesnikov Danil
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2014-
|
11
|
+
date: 2014-10-22 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|