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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: abe351194af5c2a75cbaad480fce586064fddad1
4
- data.tar.gz: 283c8fd7fd5b8d27fdbe3b15bc4af195a90b15b5
3
+ metadata.gz: 5ff1f9affc659f62ba4a9b6eb0f25309b980939f
4
+ data.tar.gz: 4de2b383019e35c329b4bb11a3e7c39f1a5b2207
5
5
  SHA512:
6
- metadata.gz: 8b529a4e0c3a0937d215feb5c77647c7ef9e7877ecdca68365bc888789d6abc050675e29ac0526dc27b14f7ece94b610849fdb2a6b982093f6e4ba779a414376
7
- data.tar.gz: 12978bfbbbf31fd2d8ffcaed16c67fe1c029076af8365708ff54cb56de6accfe11879cb80b82fc5fb71880bf20d07ce777fc97550ffcd5cda54a3af3979e8497
6
+ metadata.gz: 8748539cfaf294108ff6d4e3bbf443dd42320171f5e89a0982b00b4aa32f4e6f255b6f3fa0a3726b970b5e7cf6b1b02a48e8bd0e203d892127547afb82c99567
7
+ data.tar.gz: edc08f4f3e803bf13f4d9b8dfd84cd4b690489ddab3daf3f3a39aea833fe44d93a506b50d0319a970f9dacc91b45722b3768b321023ba7ab7dda4246dc169a87
data/CHANGELOG.md CHANGED
@@ -1,5 +1,13 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.3.1
4
+
5
+ - Added path normalization to `.find_by_path`
6
+ - Added `.find_by_path!`
7
+ - Added `#full_path`
8
+ - Fixed boolean options.
9
+ - Added options validation.
10
+
3
11
  ## 0.3.0
4
12
 
5
13
  - Added "path_separator" option.
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
- counter_cache: :children_count,
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.find_by_node_path('bar/qux/quux')
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
- def has_hierarchy(options = {})
9
- cattr_accessor(:has_hierarchy_options) { options }
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
- include Order unless options[:order] == false
15
- include Path unless options[:path_cache] == false
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
@@ -4,12 +4,6 @@ module HasHierarchy
4
4
 
5
5
  included do
6
6
  before_save :cache_depth
7
-
8
- cattr_accessor :depth_column do
9
- column = has_hierarchy_options[:depth_cache]
10
- column = :depth if column == true
11
- column
12
- end
13
7
  end
14
8
 
15
9
  protected
@@ -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
@@ -1,3 +1,3 @@
1
1
  module HasHierarchy
2
- VERSION = '0.3.0'
2
+ VERSION = '0.3.1'
3
3
  end
@@ -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)
@@ -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
- # Ordering scope (parent_id) cannot be combined with lambda.
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.0
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-09-18 00:00:00.000000000 Z
11
+ date: 2014-10-22 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler