acts_as_recursive_tree 3.2.0 → 3.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.github/workflows/ci.yml +7 -3
- data/Appraisals +9 -2
- data/CHANGELOG.md +8 -0
- data/README.md +6 -1
- data/acts_as_recursive_tree.gemspec +3 -3
- data/gemfiles/ar_70.gemfile +2 -2
- data/gemfiles/ar_next.gemfile +10 -0
- data/lib/acts_as_recursive_tree/model.rb +9 -7
- data/lib/acts_as_recursive_tree/preloaders/descendants.rb +8 -3
- data/lib/acts_as_recursive_tree/version.rb +1 -1
- data/spec/acts_as_recursive_tree/builders/ancestors_spec.rb +17 -0
- data/spec/acts_as_recursive_tree/builders/descendants_spec.rb +18 -0
- data/spec/acts_as_recursive_tree/builders/leaves_spec.rb +18 -0
- data/spec/{values_spec.rb → acts_as_recursive_tree/options/values_spec.rb} +13 -13
- data/spec/acts_as_recursive_tree/preloaders/descendants_spec.rb +19 -4
- data/spec/model/location_spec.rb +1 -1
- data/spec/model/node_spec.rb +1 -1
- data/spec/model/relation_spec.rb +46 -35
- data/spec/spec_helper.rb +2 -2
- data/spec/{builders_spec.rb → support/shared_examples/builders.rb} +10 -58
- data/spec/support/tree_methods.rb +15 -3
- metadata +20 -13
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: f74110127d12218381c9578cf59546b125dddd7f2f994dcbc8fff16b13f27f9f
|
4
|
+
data.tar.gz: e63babd0dc010e7cded02689cc9fb3ae54f8a9a817de3c00031cbc118e2a652c
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 3711b930aa6bbb744cdf6ad0e34af98df9065294c0d8d498ec7daafb1ebd8e534acbab8195a5752b47dd1da5650a73e4a2c72d3371d6d2856d885f0cae0d4331
|
7
|
+
data.tar.gz: 3697fb438ee57c0cbb3d652c26278f6bcd016eab1f8c1d1d60cb0b319f74dd1566af889827a1fca7823b201d16a692b32a9411a95a2850e3f582c928f01aa378
|
data/.github/workflows/ci.yml
CHANGED
@@ -20,7 +20,7 @@ jobs:
|
|
20
20
|
strategy:
|
21
21
|
matrix:
|
22
22
|
ruby-version: ['2.5', '2.6', '2.7', '3.0', '3.1', '3.2']
|
23
|
-
gemfile: [ar_52, ar_60, ar_61, ar_70]
|
23
|
+
gemfile: [ar_52, ar_60, ar_61, ar_70, ar_next]
|
24
24
|
exclude:
|
25
25
|
- ruby-version: '3.2'
|
26
26
|
gemfile: ar_52
|
@@ -36,9 +36,13 @@ jobs:
|
|
36
36
|
gemfile: ar_61
|
37
37
|
- ruby-version: '3.0'
|
38
38
|
gemfile: ar_52
|
39
|
-
- ruby-version: '2.5'
|
40
|
-
gemfile: ar_70
|
41
39
|
- ruby-version: '2.6'
|
40
|
+
gemfile: ar_next
|
41
|
+
- ruby-version: '2.6'
|
42
|
+
gemfile: ar_70
|
43
|
+
- ruby-version: '2.5'
|
44
|
+
gemfile: ar_next
|
45
|
+
- ruby-version: '2.5'
|
42
46
|
gemfile: ar_70
|
43
47
|
env: # $BUNDLE_GEMFILE must be set at the job level, so it is set for all steps
|
44
48
|
BUNDLE_GEMFILE: ${{ github.workspace }}/gemfiles/${{ matrix.gemfile }}.gemfile
|
data/Appraisals
CHANGED
@@ -16,6 +16,13 @@ appraise 'ar-61' do
|
|
16
16
|
end
|
17
17
|
|
18
18
|
appraise 'ar-70' do
|
19
|
-
gem 'activerecord', '~> 7.0
|
20
|
-
gem 'activesupport', '~> 7.0
|
19
|
+
gem 'activerecord', '~> 7.0'
|
20
|
+
gem 'activesupport', '~> 7.0'
|
21
|
+
end
|
22
|
+
|
23
|
+
appraise 'ar-next' do
|
24
|
+
git 'https://github.com/rails/rails.git', branch: 'main' do
|
25
|
+
gem 'activerecord'
|
26
|
+
gem 'activesupport'
|
27
|
+
end
|
21
28
|
end
|
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,11 @@
|
|
1
|
+
### Version 3.4.0
|
2
|
+
- Rails 7.1 compatibility
|
3
|
+
- Added ar_next to test matrix
|
4
|
+
- Added updated databasecleaner to test latest active record from git
|
5
|
+
|
6
|
+
### Version 3.3.0
|
7
|
+
- added __includes:__ option to __preload_tree__
|
8
|
+
|
1
9
|
### Version 3.2.0
|
2
10
|
- Added #preload_tree method to preload the parent/child relations of a single node
|
3
11
|
|
data/README.md
CHANGED
@@ -18,6 +18,7 @@ ActsAsRecursiveTree currently supports following ActiveRecord versions and is te
|
|
18
18
|
* ActiveRecord 6.0.x
|
19
19
|
* ActiveRecord 6.1.x
|
20
20
|
* ActiveRecord 7.0.x
|
21
|
+
* ActiveRecord 7.1.x
|
21
22
|
|
22
23
|
## Supported Rubies
|
23
24
|
ActsAsRecursiveTree is tested with following rubies:
|
@@ -134,7 +135,11 @@ __Additional methods:__
|
|
134
135
|
__Utility methods:__
|
135
136
|
* `root?` - returns true if this node is a root node
|
136
137
|
* `leaf?` - returns true if this node is a leave node
|
137
|
-
* `preload_tree` - fetches all descendants of this node and
|
138
|
+
* `preload_tree` - fetches all descendants of this node and assigns the proper parent/children associations. You are then able to traverse the tree through the children/parent association without querying the database again. You can also pass arguments to `includes` which will be forwarded when fetching records.
|
139
|
+
|
140
|
+
```ruby
|
141
|
+
node.preload_tree(includes: [:association, :another_association])
|
142
|
+
```
|
138
143
|
|
139
144
|
## Customizing the recursion
|
140
145
|
|
@@ -23,12 +23,12 @@ Gem::Specification.new do |spec|
|
|
23
23
|
spec.test_files = spec.files.grep(%r{^spec/})
|
24
24
|
spec.require_paths = ['lib']
|
25
25
|
|
26
|
-
spec.add_runtime_dependency 'activerecord', '>= 5.2.0', '<
|
27
|
-
spec.add_runtime_dependency 'activesupport', '>= 5.2.0', '<
|
26
|
+
spec.add_runtime_dependency 'activerecord', '>= 5.2.0', '< 8'
|
27
|
+
spec.add_runtime_dependency 'activesupport', '>= 5.2.0', '< 8'
|
28
28
|
spec.add_runtime_dependency 'zeitwerk', '>= 2.4'
|
29
29
|
|
30
30
|
spec.add_development_dependency 'appraisal', '~> 2.4'
|
31
|
-
spec.add_development_dependency 'database_cleaner', '~> 1
|
31
|
+
spec.add_development_dependency 'database_cleaner-active_record', '~> 2.1'
|
32
32
|
spec.add_development_dependency 'rake'
|
33
33
|
spec.add_development_dependency 'rspec-rails', '>= 3.5'
|
34
34
|
spec.add_development_dependency 'rubocop', '~> 1.23.0'
|
data/gemfiles/ar_70.gemfile
CHANGED
@@ -94,8 +94,10 @@ module ActsAsRecursiveTree
|
|
94
94
|
#
|
95
95
|
# Fetches all descendants of this node and assigns the parent/children associations
|
96
96
|
#
|
97
|
-
|
98
|
-
|
97
|
+
# @param includes [Array|Hash] pass the same arguments that should be passed to the #includes() method.
|
98
|
+
#
|
99
|
+
def preload_tree(includes: nil)
|
100
|
+
ActsAsRecursiveTree::Preloaders::Descendants.new(self, includes: includes).preload!
|
99
101
|
true
|
100
102
|
end
|
101
103
|
|
@@ -107,11 +109,11 @@ module ActsAsRecursiveTree
|
|
107
109
|
|
108
110
|
module ClassMethods
|
109
111
|
def self_and_ancestors_of(ids, &block)
|
110
|
-
Builders::Ancestors.build(self, ids, &block)
|
112
|
+
ActsAsRecursiveTree::Builders::Ancestors.build(self, ids, &block)
|
111
113
|
end
|
112
114
|
|
113
115
|
def ancestors_of(ids, &block)
|
114
|
-
Builders::Ancestors.build(self, ids, exclude_ids: true, &block)
|
116
|
+
ActsAsRecursiveTree::Builders::Ancestors.build(self, ids, exclude_ids: true, &block)
|
115
117
|
end
|
116
118
|
|
117
119
|
def roots_of(ids)
|
@@ -119,15 +121,15 @@ module ActsAsRecursiveTree
|
|
119
121
|
end
|
120
122
|
|
121
123
|
def self_and_descendants_of(ids, &block)
|
122
|
-
Builders::Descendants.build(self, ids, &block)
|
124
|
+
ActsAsRecursiveTree::Builders::Descendants.build(self, ids, &block)
|
123
125
|
end
|
124
126
|
|
125
127
|
def descendants_of(ids, &block)
|
126
|
-
Builders::Descendants.build(self, ids, exclude_ids: true, &block)
|
128
|
+
ActsAsRecursiveTree::Builders::Descendants.build(self, ids, exclude_ids: true, &block)
|
127
129
|
end
|
128
130
|
|
129
131
|
def leaves_of(ids, &block)
|
130
|
-
Builders::Leaves.build(self, ids, &block)
|
132
|
+
ActsAsRecursiveTree::Builders::Leaves.build(self, ids, &block)
|
131
133
|
end
|
132
134
|
end
|
133
135
|
end
|
@@ -7,9 +7,10 @@ module ActsAsRecursiveTree
|
|
7
7
|
# based on the preloaded data. After this, calling #parent or #children will not trigger a database query.
|
8
8
|
#
|
9
9
|
class Descendants
|
10
|
-
def initialize(node)
|
11
|
-
@node
|
10
|
+
def initialize(node, includes: nil)
|
11
|
+
@node = node
|
12
12
|
@parent_key = node._recursive_tree_config.parent_key
|
13
|
+
@includes = includes
|
13
14
|
end
|
14
15
|
|
15
16
|
def preload!
|
@@ -19,7 +20,11 @@ module ActsAsRecursiveTree
|
|
19
20
|
private
|
20
21
|
|
21
22
|
def records
|
22
|
-
@records ||=
|
23
|
+
@records ||= begin
|
24
|
+
descendants = @node.descendants
|
25
|
+
descendants = descendants.includes(*@includes) if @includes
|
26
|
+
descendants.to_a
|
27
|
+
end
|
23
28
|
end
|
24
29
|
|
25
30
|
def apply_records(parent_node)
|
@@ -0,0 +1,17 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'spec_helper'
|
4
|
+
|
5
|
+
RSpec.describe ActsAsRecursiveTree::Builders::Ancestors do
|
6
|
+
context 'basic' do
|
7
|
+
it_behaves_like 'build recursive query'
|
8
|
+
it_behaves_like 'ancestor query'
|
9
|
+
include_context 'context with ordering'
|
10
|
+
end
|
11
|
+
|
12
|
+
context 'with options' do
|
13
|
+
include_context 'setup with enforced ordering' do
|
14
|
+
it_behaves_like 'with ordering'
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'spec_helper'
|
4
|
+
|
5
|
+
RSpec.describe ActsAsRecursiveTree::Builders::Descendants do
|
6
|
+
context 'basic' do
|
7
|
+
it_behaves_like 'build recursive query'
|
8
|
+
it_behaves_like 'descendant query'
|
9
|
+
include_context 'context without ordering'
|
10
|
+
end
|
11
|
+
|
12
|
+
context 'with options' do
|
13
|
+
include_context 'setup with enforced ordering' do
|
14
|
+
let(:ordering) { true }
|
15
|
+
it_behaves_like 'with ordering'
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'spec_helper'
|
4
|
+
|
5
|
+
RSpec.describe ActsAsRecursiveTree::Builders::Leaves do
|
6
|
+
context 'basic' do
|
7
|
+
it_behaves_like 'build recursive query'
|
8
|
+
it_behaves_like 'descendant query'
|
9
|
+
include_context 'context without ordering'
|
10
|
+
end
|
11
|
+
|
12
|
+
context 'with options' do
|
13
|
+
include_context 'setup with enforced ordering' do
|
14
|
+
let(:ordering) { true }
|
15
|
+
it_behaves_like 'without ordering'
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
@@ -2,21 +2,21 @@
|
|
2
2
|
|
3
3
|
require 'spec_helper'
|
4
4
|
|
5
|
-
|
6
|
-
|
5
|
+
RSpec.describe ActsAsRecursiveTree::Options::Values do
|
6
|
+
shared_examples 'single values' do
|
7
|
+
subject(:value) { described_class.create(single_value) }
|
7
8
|
|
8
|
-
|
9
|
+
it { is_expected.to be_a described_class::SingleValue }
|
9
10
|
|
10
|
-
|
11
|
-
|
12
|
-
|
11
|
+
it 'apply_toes' do
|
12
|
+
expect(value.apply_to(attribute).to_sql).to end_with " = #{single_value}"
|
13
|
+
end
|
13
14
|
|
14
|
-
|
15
|
-
|
15
|
+
it 'apply_negated_toes' do
|
16
|
+
expect(value.apply_negated_to(attribute).to_sql).to end_with " != #{single_value}"
|
17
|
+
end
|
16
18
|
end
|
17
|
-
end
|
18
19
|
|
19
|
-
describe ActsAsRecursiveTree::Options::Values do
|
20
20
|
let(:table) { Arel::Table.new('test_table') }
|
21
21
|
let(:attribute) { table['test_attr'] }
|
22
22
|
|
@@ -44,7 +44,7 @@ describe ActsAsRecursiveTree::Options::Values do
|
|
44
44
|
|
45
45
|
let(:array) { [1, 2, 3] }
|
46
46
|
|
47
|
-
it { is_expected.to be_a
|
47
|
+
it { is_expected.to be_a described_class::MultiValue }
|
48
48
|
|
49
49
|
it 'apply_toes' do
|
50
50
|
expect(value.apply_to(attribute).to_sql).to end_with " IN (#{array.join(', ')})"
|
@@ -60,7 +60,7 @@ describe ActsAsRecursiveTree::Options::Values do
|
|
60
60
|
|
61
61
|
let(:range) { 1..3 }
|
62
62
|
|
63
|
-
it { is_expected.to be_a
|
63
|
+
it { is_expected.to be_a described_class::RangeValue }
|
64
64
|
|
65
65
|
it 'apply_toes' do
|
66
66
|
expect(value.apply_to(attribute).to_sql).to end_with "BETWEEN #{range.begin} AND #{range.end}"
|
@@ -83,7 +83,7 @@ describe ActsAsRecursiveTree::Options::Values do
|
|
83
83
|
end
|
84
84
|
end
|
85
85
|
|
86
|
-
it { is_expected.to be_a
|
86
|
+
it { is_expected.to be_a described_class::Relation }
|
87
87
|
|
88
88
|
it 'apply_toes' do
|
89
89
|
expect(value.apply_to(attribute).to_sql).to match(/IN \(SELECT.*\)/)
|
@@ -5,8 +5,9 @@ require 'spec_helper'
|
|
5
5
|
RSpec.describe ActsAsRecursiveTree::Preloaders::Descendants do
|
6
6
|
include TreeMethods
|
7
7
|
|
8
|
-
let(:preloader) { described_class.new(root.reload) }
|
9
|
-
let(:
|
8
|
+
let(:preloader) { described_class.new(root.reload, includes: included_associations) }
|
9
|
+
let(:included_associations) { nil }
|
10
|
+
let(:root) { create_tree(2, create_node_info: true) }
|
10
11
|
let(:children) { root.children }
|
11
12
|
|
12
13
|
describe '#preload! will set the associations target attribute' do
|
@@ -14,16 +15,30 @@ RSpec.describe ActsAsRecursiveTree::Preloaders::Descendants do
|
|
14
15
|
preloader.preload!
|
15
16
|
end
|
16
17
|
|
17
|
-
it 'sets the children
|
18
|
+
it 'sets the children association' do
|
18
19
|
children.each do |child|
|
19
20
|
expect(child.association(:children).target).not_to be_nil
|
20
21
|
end
|
21
22
|
end
|
22
23
|
|
23
|
-
it 'sets the parent
|
24
|
+
it 'sets the parent association' do
|
24
25
|
children.each do |child|
|
25
26
|
expect(child.association(:parent).target).not_to be_nil
|
26
27
|
end
|
27
28
|
end
|
28
29
|
end
|
30
|
+
|
31
|
+
describe '#preload! will include associations' do
|
32
|
+
let(:included_associations) { :node_info }
|
33
|
+
|
34
|
+
before do
|
35
|
+
preloader.preload!
|
36
|
+
end
|
37
|
+
|
38
|
+
it 'sets the children association' do
|
39
|
+
children.each do |child|
|
40
|
+
expect(child.association(included_associations).target).not_to be_nil
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
29
44
|
end
|
data/spec/model/location_spec.rb
CHANGED
data/spec/model/node_spec.rb
CHANGED
data/spec/model/relation_spec.rb
CHANGED
@@ -2,57 +2,68 @@
|
|
2
2
|
|
3
3
|
require 'spec_helper'
|
4
4
|
|
5
|
-
describe 'Relation' do
|
6
|
-
|
7
|
-
node = Node.create!(name: 'root') if node.nil?
|
8
|
-
|
9
|
-
1.upto(max_level - current_level) do |index|
|
10
|
-
child = node.children.create!(name: "child #{index} - level #{current_level}", active: stop_at > current_level)
|
11
|
-
child.create_node_info(status: stop_at > current_level ? 'foo' : 'bar')
|
12
|
-
create_tree(max_level, current_level: current_level + 1, node: child, stop_at: stop_at)
|
13
|
-
end
|
5
|
+
RSpec.describe 'Relation' do
|
6
|
+
include TreeMethods
|
14
7
|
|
15
|
-
|
16
|
-
end
|
8
|
+
let(:root) { create_tree(4, stop_at: 2) }
|
17
9
|
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
end
|
10
|
+
describe '#descendants' do
|
11
|
+
context 'with simple relation' do
|
12
|
+
let(:descendants) { root.descendants { |opts| opts.condition = Node.where(active: true) }.to_a }
|
22
13
|
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
expect(node.active).to be_truthy
|
14
|
+
it 'returns only active nodes' do
|
15
|
+
descendants.each do |node|
|
16
|
+
expect(node.active).to be_truthy
|
17
|
+
end
|
28
18
|
end
|
29
19
|
end
|
30
20
|
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
21
|
+
context 'with condition on joined association' do
|
22
|
+
let(:descendants) do
|
23
|
+
root.descendants do |opts|
|
24
|
+
opts.condition = Node.joins(:node_info).where.not(node_infos: { status: 'bar' })
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
it 'returns only node with condition fulfilled' do
|
29
|
+
descendants.each do |node|
|
30
|
+
expect(node.node_info.status).to eql('foo')
|
31
|
+
end
|
35
32
|
end
|
36
33
|
end
|
37
34
|
end
|
38
35
|
|
39
|
-
|
40
|
-
|
41
|
-
ancestors
|
36
|
+
describe '#ancestors' do
|
37
|
+
context 'with simple_relation' do
|
38
|
+
let(:ancestors) { root.leaves.first.ancestors { |opts| opts.condition = Node.where(active: false) }.to_a }
|
42
39
|
|
43
|
-
|
44
|
-
|
40
|
+
it 'return only active nodes' do
|
41
|
+
ancestors.each do |node|
|
42
|
+
expect(node.active).to be_falsey
|
43
|
+
end
|
45
44
|
end
|
46
45
|
|
47
|
-
|
46
|
+
it 'does not return the root node' do
|
47
|
+
expect(ancestors).not_to include(root)
|
48
|
+
end
|
48
49
|
end
|
49
50
|
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
51
|
+
context 'with condition on joined association' do
|
52
|
+
let(:ancestors) do
|
53
|
+
root.leaves.first.ancestors do |opts|
|
54
|
+
opts.condition = Node.joins(:node_info).where.not(node_infos: { status: 'foo' })
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
it 'return only nodes for the matching condition' do
|
59
|
+
ancestors.each do |node|
|
60
|
+
expect(node.node_info.status).to eql('bar')
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
it 'does not return the root node' do
|
65
|
+
expect(ancestors).not_to include(root)
|
54
66
|
end
|
55
|
-
expect(ancestors).not_to include(@root)
|
56
67
|
end
|
57
68
|
end
|
58
69
|
end
|
data/spec/spec_helper.rb
CHANGED
@@ -9,7 +9,7 @@ require 'active_record'
|
|
9
9
|
require 'acts_as_recursive_tree'
|
10
10
|
require_relative 'db/database'
|
11
11
|
|
12
|
-
require 'database_cleaner'
|
12
|
+
require 'database_cleaner-active_record'
|
13
13
|
|
14
14
|
# Requires supporting ruby files with custom matchers and macros, etc,
|
15
15
|
# in spec/support/ and its subdirectories.
|
@@ -76,7 +76,7 @@ RSpec.configure do |config|
|
|
76
76
|
# # - http://myronmars.to/n/dev-blog/2012/06/rspecs-new-expectation-syntax
|
77
77
|
# # - http://www.teaisaweso.me/blog/2013/05/27/rspecs-new-message-expectation-syntax/
|
78
78
|
# # - http://myronmars.to/n/dev-blog/2014/05/notable-changes-in-rspec-3#new__config_option_to_disable_rspeccore_monkey_patching
|
79
|
-
|
79
|
+
config.disable_monkey_patching!
|
80
80
|
#
|
81
81
|
# # This setting enables warnings. It's recommended, but in some cases may
|
82
82
|
# # be too noisy due to issues in dependencies.
|
@@ -1,15 +1,11 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
require 'spec_helper'
|
4
|
-
|
5
|
-
shared_context 'setup with enforced ordering' do
|
1
|
+
RSpec.shared_context 'setup with enforced ordering' do
|
6
2
|
let(:ordering) { false }
|
7
3
|
include_context 'base_setup' do
|
8
4
|
let(:proc) { ->(config) { config.ensure_ordering! } }
|
9
5
|
end
|
10
6
|
end
|
11
7
|
|
12
|
-
shared_context 'base_setup' do
|
8
|
+
RSpec.shared_context 'base_setup' do
|
13
9
|
subject(:query) { builder.build.to_sql }
|
14
10
|
|
15
11
|
let(:model_id) { 1 }
|
@@ -21,7 +17,7 @@ shared_context 'base_setup' do
|
|
21
17
|
end
|
22
18
|
end
|
23
19
|
|
24
|
-
shared_examples 'basic recursive examples' do
|
20
|
+
RSpec.shared_examples 'basic recursive examples' do
|
25
21
|
it { is_expected.to start_with "SELECT \"#{model_class.table_name}\".* FROM \"#{model_class.table_name}\"" }
|
26
22
|
|
27
23
|
it { is_expected.to match(/WHERE "#{model_class.table_name}"."#{model_class.primary_key}" = #{model_id}/) }
|
@@ -35,7 +31,7 @@ shared_examples 'basic recursive examples' do
|
|
35
31
|
}
|
36
32
|
end
|
37
33
|
|
38
|
-
shared_examples 'build recursive query' do
|
34
|
+
RSpec.shared_examples 'build recursive query' do
|
39
35
|
context 'simple id' do
|
40
36
|
context 'with simple class' do
|
41
37
|
include_context 'base_setup' do
|
@@ -67,79 +63,35 @@ shared_examples 'build recursive query' do
|
|
67
63
|
end
|
68
64
|
end
|
69
65
|
|
70
|
-
shared_examples 'ancestor query' do
|
66
|
+
RSpec.shared_examples 'ancestor query' do
|
71
67
|
include_context 'base_setup'
|
72
68
|
|
73
69
|
it { is_expected.to match(/"#{builder.travers_loc_table.name}"."#{model_class._recursive_tree_config.parent_key}" = "#{model_class.table_name}"."#{model_class.primary_key}"/) }
|
74
70
|
end
|
75
71
|
|
76
|
-
shared_examples 'descendant query' do
|
72
|
+
RSpec.shared_examples 'descendant query' do
|
77
73
|
include_context 'base_setup'
|
78
74
|
|
79
75
|
it { is_expected.to match(/"#{model_class.table_name}"."#{model_class._recursive_tree_config.parent_key}" = "#{builder.travers_loc_table.name}"."#{model_class.primary_key}"/) }
|
80
76
|
it { is_expected.to match(/#{Regexp.escape(builder.travers_loc_table.project(builder.travers_loc_table[model_class.primary_key]).to_sql)}/) }
|
81
77
|
end
|
82
78
|
|
83
|
-
shared_context 'context with ordering' do
|
79
|
+
RSpec.shared_context 'context with ordering' do
|
84
80
|
include_context 'base_setup' do
|
85
81
|
it_behaves_like 'with ordering'
|
86
82
|
end
|
87
83
|
end
|
88
84
|
|
89
|
-
shared_context 'context without ordering' do
|
85
|
+
RSpec.shared_context 'context without ordering' do
|
90
86
|
include_context 'base_setup' do
|
91
87
|
it_behaves_like 'without ordering'
|
92
88
|
end
|
93
89
|
end
|
94
90
|
|
95
|
-
shared_examples 'with ordering' do
|
91
|
+
RSpec.shared_examples 'with ordering' do
|
96
92
|
it { is_expected.to match(/ORDER BY #{Regexp.escape(builder.recursive_temp_table[model_class._recursive_tree_config.depth_column].asc.to_sql)}/) }
|
97
93
|
end
|
98
94
|
|
99
|
-
shared_examples 'without ordering' do
|
95
|
+
RSpec.shared_examples 'without ordering' do
|
100
96
|
it { is_expected.not_to match(/ORDER BY/) }
|
101
97
|
end
|
102
|
-
|
103
|
-
describe ActsAsRecursiveTree::Builders::Descendants do
|
104
|
-
context 'basic' do
|
105
|
-
it_behaves_like 'build recursive query'
|
106
|
-
it_behaves_like 'descendant query'
|
107
|
-
include_context 'context without ordering'
|
108
|
-
end
|
109
|
-
|
110
|
-
context 'with options' do
|
111
|
-
include_context 'setup with enforced ordering' do
|
112
|
-
let(:ordering) { true }
|
113
|
-
it_behaves_like 'with ordering'
|
114
|
-
end
|
115
|
-
end
|
116
|
-
end
|
117
|
-
|
118
|
-
describe ActsAsRecursiveTree::Builders::Ancestors do
|
119
|
-
context 'basic' do
|
120
|
-
it_behaves_like 'build recursive query'
|
121
|
-
it_behaves_like 'ancestor query'
|
122
|
-
include_context 'context with ordering'
|
123
|
-
end
|
124
|
-
|
125
|
-
context 'with options' do
|
126
|
-
include_context 'setup with enforced ordering' do
|
127
|
-
it_behaves_like 'with ordering'
|
128
|
-
end
|
129
|
-
end
|
130
|
-
end
|
131
|
-
|
132
|
-
describe ActsAsRecursiveTree::Builders::Leaves do
|
133
|
-
context 'basic' do
|
134
|
-
it_behaves_like 'build recursive query'
|
135
|
-
it_behaves_like 'descendant query'
|
136
|
-
include_context 'context without ordering'
|
137
|
-
end
|
138
|
-
|
139
|
-
context 'with options' do
|
140
|
-
include_context 'setup with enforced ordering' do
|
141
|
-
let(:ordering) { true }
|
142
|
-
it_behaves_like 'without ordering'
|
143
|
-
end
|
144
|
-
end
|
145
|
-
end
|
@@ -2,12 +2,24 @@
|
|
2
2
|
|
3
3
|
# Helper methods for simple tree creation
|
4
4
|
module TreeMethods
|
5
|
-
def create_tree(max_level, current_level
|
5
|
+
def create_tree(max_level, current_level: 0, node: nil, create_node_info: false, stop_at: -1)
|
6
6
|
node = Node.create!(name: 'root') if node.nil?
|
7
7
|
|
8
8
|
1.upto(max_level - current_level) do |index|
|
9
|
-
child = node.children.create!(
|
10
|
-
|
9
|
+
child = node.children.create!(
|
10
|
+
name: "child #{index} - level #{current_level}",
|
11
|
+
active: stop_at > current_level
|
12
|
+
)
|
13
|
+
|
14
|
+
child.create_node_info(status: stop_at > current_level ? 'foo' : 'bar') if create_node_info
|
15
|
+
|
16
|
+
create_tree(
|
17
|
+
max_level,
|
18
|
+
current_level: current_level + 1,
|
19
|
+
node: child,
|
20
|
+
create_node_info: create_node_info,
|
21
|
+
stop_at: stop_at
|
22
|
+
)
|
11
23
|
end
|
12
24
|
|
13
25
|
node
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: acts_as_recursive_tree
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 3.
|
4
|
+
version: 3.4.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Wolfgang Wedelich-John
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2023-
|
12
|
+
date: 2023-03-13 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: activerecord
|
@@ -20,7 +20,7 @@ dependencies:
|
|
20
20
|
version: 5.2.0
|
21
21
|
- - "<"
|
22
22
|
- !ruby/object:Gem::Version
|
23
|
-
version: '
|
23
|
+
version: '8'
|
24
24
|
type: :runtime
|
25
25
|
prerelease: false
|
26
26
|
version_requirements: !ruby/object:Gem::Requirement
|
@@ -30,7 +30,7 @@ dependencies:
|
|
30
30
|
version: 5.2.0
|
31
31
|
- - "<"
|
32
32
|
- !ruby/object:Gem::Version
|
33
|
-
version: '
|
33
|
+
version: '8'
|
34
34
|
- !ruby/object:Gem::Dependency
|
35
35
|
name: activesupport
|
36
36
|
requirement: !ruby/object:Gem::Requirement
|
@@ -40,7 +40,7 @@ dependencies:
|
|
40
40
|
version: 5.2.0
|
41
41
|
- - "<"
|
42
42
|
- !ruby/object:Gem::Version
|
43
|
-
version: '
|
43
|
+
version: '8'
|
44
44
|
type: :runtime
|
45
45
|
prerelease: false
|
46
46
|
version_requirements: !ruby/object:Gem::Requirement
|
@@ -50,7 +50,7 @@ dependencies:
|
|
50
50
|
version: 5.2.0
|
51
51
|
- - "<"
|
52
52
|
- !ruby/object:Gem::Version
|
53
|
-
version: '
|
53
|
+
version: '8'
|
54
54
|
- !ruby/object:Gem::Dependency
|
55
55
|
name: zeitwerk
|
56
56
|
requirement: !ruby/object:Gem::Requirement
|
@@ -80,19 +80,19 @@ dependencies:
|
|
80
80
|
- !ruby/object:Gem::Version
|
81
81
|
version: '2.4'
|
82
82
|
- !ruby/object:Gem::Dependency
|
83
|
-
name: database_cleaner
|
83
|
+
name: database_cleaner-active_record
|
84
84
|
requirement: !ruby/object:Gem::Requirement
|
85
85
|
requirements:
|
86
86
|
- - "~>"
|
87
87
|
- !ruby/object:Gem::Version
|
88
|
-
version: '1
|
88
|
+
version: '2.1'
|
89
89
|
type: :development
|
90
90
|
prerelease: false
|
91
91
|
version_requirements: !ruby/object:Gem::Requirement
|
92
92
|
requirements:
|
93
93
|
- - "~>"
|
94
94
|
- !ruby/object:Gem::Version
|
95
|
-
version: '1
|
95
|
+
version: '2.1'
|
96
96
|
- !ruby/object:Gem::Dependency
|
97
97
|
name: rake
|
98
98
|
requirement: !ruby/object:Gem::Requirement
|
@@ -205,6 +205,7 @@ files:
|
|
205
205
|
- gemfiles/ar_60.gemfile
|
206
206
|
- gemfiles/ar_61.gemfile
|
207
207
|
- gemfiles/ar_70.gemfile
|
208
|
+
- gemfiles/ar_next.gemfile
|
208
209
|
- lib/acts_as_recursive_tree.rb
|
209
210
|
- lib/acts_as_recursive_tree/acts_macro.rb
|
210
211
|
- lib/acts_as_recursive_tree/associations.rb
|
@@ -226,8 +227,11 @@ files:
|
|
226
227
|
- lib/acts_as_recursive_tree/railtie.rb
|
227
228
|
- lib/acts_as_recursive_tree/scopes.rb
|
228
229
|
- lib/acts_as_recursive_tree/version.rb
|
230
|
+
- spec/acts_as_recursive_tree/builders/ancestors_spec.rb
|
231
|
+
- spec/acts_as_recursive_tree/builders/descendants_spec.rb
|
232
|
+
- spec/acts_as_recursive_tree/builders/leaves_spec.rb
|
233
|
+
- spec/acts_as_recursive_tree/options/values_spec.rb
|
229
234
|
- spec/acts_as_recursive_tree/preloaders/descendants_spec.rb
|
230
|
-
- spec/builders_spec.rb
|
231
235
|
- spec/db/database.rb
|
232
236
|
- spec/db/database.yml
|
233
237
|
- spec/db/models.rb
|
@@ -236,8 +240,8 @@ files:
|
|
236
240
|
- spec/model/node_spec.rb
|
237
241
|
- spec/model/relation_spec.rb
|
238
242
|
- spec/spec_helper.rb
|
243
|
+
- spec/support/shared_examples/builders.rb
|
239
244
|
- spec/support/tree_methods.rb
|
240
|
-
- spec/values_spec.rb
|
241
245
|
homepage: https://github.com/1and1/acts_as_recursive_tree
|
242
246
|
licenses:
|
243
247
|
- MIT
|
@@ -264,8 +268,11 @@ signing_key:
|
|
264
268
|
specification_version: 4
|
265
269
|
summary: Drop in replacement for acts_as_tree but using recursive queries
|
266
270
|
test_files:
|
271
|
+
- spec/acts_as_recursive_tree/builders/ancestors_spec.rb
|
272
|
+
- spec/acts_as_recursive_tree/builders/descendants_spec.rb
|
273
|
+
- spec/acts_as_recursive_tree/builders/leaves_spec.rb
|
274
|
+
- spec/acts_as_recursive_tree/options/values_spec.rb
|
267
275
|
- spec/acts_as_recursive_tree/preloaders/descendants_spec.rb
|
268
|
-
- spec/builders_spec.rb
|
269
276
|
- spec/db/database.rb
|
270
277
|
- spec/db/database.yml
|
271
278
|
- spec/db/models.rb
|
@@ -274,5 +281,5 @@ test_files:
|
|
274
281
|
- spec/model/node_spec.rb
|
275
282
|
- spec/model/relation_spec.rb
|
276
283
|
- spec/spec_helper.rb
|
284
|
+
- spec/support/shared_examples/builders.rb
|
277
285
|
- spec/support/tree_methods.rb
|
278
|
-
- spec/values_spec.rb
|