with_recursive_tree 0.1.1 → 0.2.1
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/README.md +10 -0
- data/lib/with_recursive_tree/backport.rb +60 -0
- data/lib/with_recursive_tree/version.rb +1 -1
- data/lib/with_recursive_tree.rb +4 -0
- metadata +10 -9
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 92e7fa34c82ec4cde4ba95072d52009f5c34925df14fdadbeb1e82dbfae61524
|
4
|
+
data.tar.gz: 3b463ddbb8dc0170a72fc1b80d77a435b38baa3b6007e69e1ef43f688adde112
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: b4459dccf11b54213f50269c227e9c05af2efff4347905c5504db438fa9b0970ed47c66cbf0b9938a74f4fc95acfc3f5d20bfa9f6654547b4fcbc89df538b811
|
7
|
+
data.tar.gz: 873f7e500d51a922defb6bd8eaade92a864d99de5d80d835a2ef2cd4c6f1107928526b0eb5777919a560dbbb50df6f534b0619f4c65eee1c3d648b1f4f318cc3
|
data/README.md
CHANGED
@@ -144,6 +144,16 @@ A
|
|
144
144
|
---R
|
145
145
|
```
|
146
146
|
|
147
|
+
## Compatibility
|
148
|
+
|
149
|
+
with_recursive_tree is compatible with:
|
150
|
+
|
151
|
+
* Rails 6.0 and above
|
152
|
+
* Ruby 3.1 and above
|
153
|
+
* Postgres version 13 and above
|
154
|
+
* MySQL version 8 and above
|
155
|
+
* SQLite3 version 3.34 and above
|
156
|
+
|
147
157
|
## Benchmarks
|
148
158
|
|
149
159
|
You can run some [benchmarks](/benchmarks/benchmark.rb) to compare with_recursive_tree agains [acts_as_tree](https://github.com/amerine/acts_as_tree), [ancestry](https://github.com/stefankroes/ancestry/) and [closure_tree](https://github.com/ClosureTree/closure_tree).
|
@@ -0,0 +1,60 @@
|
|
1
|
+
module WithRecursiveTree
|
2
|
+
def ancestors
|
3
|
+
self_and_ancestors.where.not self.class.with_recursive_tree_primary_key => send(self.class.with_recursive_tree_primary_key)
|
4
|
+
end
|
5
|
+
|
6
|
+
def descendants
|
7
|
+
self_and_descendants.where.not self.class.with_recursive_tree_primary_key => send(self.class.with_recursive_tree_primary_key)
|
8
|
+
end
|
9
|
+
|
10
|
+
def self_and_ancestors
|
11
|
+
sql = <<-SQL
|
12
|
+
WITH RECURSIVE tree AS (
|
13
|
+
#{self.class.where(self.class.with_recursive_tree_primary_key => send(self.class.with_recursive_tree_primary_key)).to_sql}
|
14
|
+
UNION ALL
|
15
|
+
#{self.class.joins("JOIN tree ON #{self.class.table_name}.#{self.class.with_recursive_tree_primary_key} = tree.#{self.class.with_recursive_tree_foreign_key}").to_sql}
|
16
|
+
) SELECT * FROM tree
|
17
|
+
SQL
|
18
|
+
|
19
|
+
self.class.select("*").from("(#{sql}) AS #{self.class.table_name}")
|
20
|
+
end
|
21
|
+
|
22
|
+
def self_and_descendants
|
23
|
+
anchor_path = if defined?(ActiveRecord::ConnectionAdapters::PostgreSQLAdapter)
|
24
|
+
"ARRAY[#{self.class.with_recursive_tree_order_column}]::text[]"
|
25
|
+
elsif defined?(ActiveRecord::ConnectionAdapters::MySQL)
|
26
|
+
"CAST(CONCAT('/', #{self.class.with_recursive_tree_primary_key}, '/') AS CHAR(512))"
|
27
|
+
elsif defined?(ActiveRecord::ConnectionAdapters::SQLite3Adapter)
|
28
|
+
"'/' || #{self.class.with_recursive_tree_primary_key} || '/'"
|
29
|
+
end
|
30
|
+
|
31
|
+
recursive_path = if defined?(ActiveRecord::ConnectionAdapters::PostgreSQLAdapter)
|
32
|
+
"tree.path || #{self.class.table_name}.#{self.class.with_recursive_tree_order_column}::text"
|
33
|
+
elsif defined?(ActiveRecord::ConnectionAdapters::MySQL)
|
34
|
+
"CONCAT(tree.path, #{self.class.table_name}.#{self.class.with_recursive_tree_primary_key}, '/')"
|
35
|
+
elsif defined?(ActiveRecord::ConnectionAdapters::SQLite3)
|
36
|
+
"tree.path || #{self.class.table_name}.#{self.class.with_recursive_tree_primary_key} || '/'"
|
37
|
+
end
|
38
|
+
|
39
|
+
recursive_query = self.class.joins("JOIN tree ON #{self.class.table_name}.#{self.class.with_recursive_tree_foreign_key} = tree.#{self.class.with_recursive_tree_primary_key}").select("#{self.class.table_name}.*, #{recursive_path} AS path, depth + 1 AS depth")
|
40
|
+
|
41
|
+
# order by is only available in SQLIte for rails versions older than 7.2
|
42
|
+
if defined?(ActiveRecord::ConnectionAdapters::SQLite3)
|
43
|
+
recursive_query = recursive_query.order(self.class.with_recursive_tree_order)
|
44
|
+
end
|
45
|
+
|
46
|
+
sql = <<-SQL
|
47
|
+
WITH RECURSIVE tree AS (
|
48
|
+
#{self.class.where(self.class.with_recursive_tree_primary_key => send(self.class.with_recursive_tree_primary_key)).select("*, #{anchor_path} AS path, 0 AS depth").to_sql}
|
49
|
+
UNION ALL
|
50
|
+
#{Arel.sql(recursive_query.to_sql)}
|
51
|
+
) SELECT * FROM tree
|
52
|
+
SQL
|
53
|
+
|
54
|
+
self.class.select("*").from("(#{sql}) AS #{self.class.table_name}")
|
55
|
+
end
|
56
|
+
|
57
|
+
def siblings
|
58
|
+
self_and_siblings.where.not self.class.with_recursive_tree_primary_key => send(self.class.with_recursive_tree_primary_key)
|
59
|
+
end
|
60
|
+
end
|
data/lib/with_recursive_tree.rb
CHANGED
@@ -122,6 +122,10 @@ module WithRecursiveTree
|
|
122
122
|
end
|
123
123
|
end
|
124
124
|
|
125
|
+
if Gem::Dependency.new("", "< 7.2.0").match?("", ActiveRecord::VERSION::STRING)
|
126
|
+
require "with_recursive_tree/backport"
|
127
|
+
end
|
128
|
+
|
125
129
|
ActiveSupport.on_load :active_record do
|
126
130
|
include WithRecursiveTree
|
127
131
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: with_recursive_tree
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.2.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Patricio Mac Adden
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2025-01-03 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activerecord
|
@@ -16,42 +16,42 @@ dependencies:
|
|
16
16
|
requirements:
|
17
17
|
- - ">="
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version: '
|
19
|
+
version: '6.0'
|
20
20
|
type: :runtime
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
24
|
- - ">="
|
25
25
|
- !ruby/object:Gem::Version
|
26
|
-
version: '
|
26
|
+
version: '6.0'
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
28
|
name: activesupport
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
30
30
|
requirements:
|
31
31
|
- - ">="
|
32
32
|
- !ruby/object:Gem::Version
|
33
|
-
version: '
|
33
|
+
version: '6.0'
|
34
34
|
type: :runtime
|
35
35
|
prerelease: false
|
36
36
|
version_requirements: !ruby/object:Gem::Requirement
|
37
37
|
requirements:
|
38
38
|
- - ">="
|
39
39
|
- !ruby/object:Gem::Version
|
40
|
-
version: '
|
40
|
+
version: '6.0'
|
41
41
|
- !ruby/object:Gem::Dependency
|
42
42
|
name: railties
|
43
43
|
requirement: !ruby/object:Gem::Requirement
|
44
44
|
requirements:
|
45
45
|
- - ">="
|
46
46
|
- !ruby/object:Gem::Version
|
47
|
-
version: '
|
47
|
+
version: '6.0'
|
48
48
|
type: :runtime
|
49
49
|
prerelease: false
|
50
50
|
version_requirements: !ruby/object:Gem::Requirement
|
51
51
|
requirements:
|
52
52
|
- - ">="
|
53
53
|
- !ruby/object:Gem::Version
|
54
|
-
version: '
|
54
|
+
version: '6.0'
|
55
55
|
description: Tree structures for ActiveRecord
|
56
56
|
email:
|
57
57
|
- patriciomacadden@gmail.com
|
@@ -62,6 +62,7 @@ files:
|
|
62
62
|
- README.md
|
63
63
|
- Rakefile
|
64
64
|
- lib/with_recursive_tree.rb
|
65
|
+
- lib/with_recursive_tree/backport.rb
|
65
66
|
- lib/with_recursive_tree/version.rb
|
66
67
|
homepage: https://github.com/sinaptia/with_recursive_tree
|
67
68
|
licenses: []
|
@@ -76,7 +77,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
76
77
|
requirements:
|
77
78
|
- - ">="
|
78
79
|
- !ruby/object:Gem::Version
|
79
|
-
version: '0'
|
80
|
+
version: '3.0'
|
80
81
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
81
82
|
requirements:
|
82
83
|
- - ">="
|