acts_as_recursive_tree 2.0.2 → 2.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/CHANGELOG.md +5 -0
- data/lib/acts_as_recursive_tree.rb +1 -0
- data/lib/acts_as_recursive_tree/acts_macro.rb +3 -6
- data/lib/acts_as_recursive_tree/associations.rb +3 -3
- data/lib/acts_as_recursive_tree/builders.rb +1 -0
- data/lib/acts_as_recursive_tree/builders/leaves.rb +1 -1
- data/lib/acts_as_recursive_tree/builders/relation_builder.rb +23 -12
- data/lib/acts_as_recursive_tree/builders/strategy.rb +27 -0
- data/lib/acts_as_recursive_tree/builders/strategy/join.rb +29 -0
- data/lib/acts_as_recursive_tree/builders/strategy/subselect.rb +23 -0
- data/lib/acts_as_recursive_tree/config.rb +22 -0
- data/lib/acts_as_recursive_tree/version.rb +1 -1
- metadata +7 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: a28e3f6eadbc8b37622ef525b25e654b13c0903f4053adb096f4f853f36ccc06
|
4
|
+
data.tar.gz: f2614872c77bf263526ac596bbb82438b75af1e49e393c6464e07515c5605288
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 9a4ccf41395828283e882f8e88b6e9c8a7edea75995219840d2c6d07da69bbb8bb6f15aeec6cddf8a105f4f8ad15d3dfddad2bf7aaeead54074fffa28030bd68
|
7
|
+
data.tar.gz: c48904528902e0554d1a46dea5883afcc28473597f4df2493ccf1015e80967b2490cae5f41fb5dac9eb7925a2c9d00feeb9637b902366e3dc1be0d6dddc3c7ab
|
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,8 @@
|
|
1
|
+
### Version 2.1.0
|
2
|
+
- BUGFIX association self_and_siblings not working
|
3
|
+
- BUGFIX primary_key of model is retrieved on first usage and not on setup
|
4
|
+
- NEW when no ordering/depth is required, then use subselect instead of joining the temp table
|
5
|
+
|
1
6
|
### Version 2.0.2
|
2
7
|
- fix for condition relation was executed before merging
|
3
8
|
|
@@ -1,5 +1,3 @@
|
|
1
|
-
require 'ostruct'
|
2
|
-
|
3
1
|
module ActsAsRecursiveTree
|
4
2
|
module ActsMacro
|
5
3
|
|
@@ -11,11 +9,10 @@ module ActsAsRecursiveTree
|
|
11
9
|
def recursive_tree(parent_key: :parent_id, parent_type_column: nil)
|
12
10
|
|
13
11
|
class_attribute :_recursive_tree_config
|
14
|
-
self._recursive_tree_config =
|
15
|
-
|
12
|
+
self._recursive_tree_config = Config.new(
|
13
|
+
model_class: self,
|
16
14
|
parent_key: parent_key.to_sym,
|
17
|
-
parent_type_column: parent_type_column.try(:to_sym)
|
18
|
-
depth_column: :recursive_depth
|
15
|
+
parent_type_column: parent_type_column.try(:to_sym)
|
19
16
|
)
|
20
17
|
|
21
18
|
include ActsAsRecursiveTree::Model
|
@@ -17,9 +17,9 @@ module ActsAsRecursiveTree
|
|
17
17
|
inverse_of: :parent
|
18
18
|
|
19
19
|
has_many :self_and_siblings,
|
20
|
-
|
21
|
-
|
22
|
-
|
20
|
+
through: :parent,
|
21
|
+
source: :children,
|
22
|
+
class_name: self.base_class.to_s
|
23
23
|
end
|
24
24
|
end
|
25
25
|
end
|
@@ -1,5 +1,8 @@
|
|
1
1
|
module ActsAsRecursiveTree
|
2
2
|
module Builders
|
3
|
+
#
|
4
|
+
# Constructs the Arel necessary for recursion.
|
5
|
+
#
|
3
6
|
class RelationBuilder
|
4
7
|
|
5
8
|
def self.build(klass, ids, exclude_ids: false, &block)
|
@@ -9,6 +12,7 @@ module ActsAsRecursiveTree
|
|
9
12
|
attr_reader :klass, :ids, :recursive_temp_table, :travers_loc_table, :without_ids
|
10
13
|
mattr_reader(:random) { Random.new }
|
11
14
|
|
15
|
+
# Delegators for easier accessing config and query options
|
12
16
|
delegate :primary_key, :depth_column, :parent_key, :parent_type_column, to: :@config
|
13
17
|
delegate :depth_present?, :depth, :condition, :ensure_ordering, to: :@query_opts
|
14
18
|
|
@@ -25,6 +29,13 @@ module ActsAsRecursiveTree
|
|
25
29
|
@travers_loc_table = Arel::Table.new("traverse_#{rand_int}_loc")
|
26
30
|
end
|
27
31
|
|
32
|
+
#
|
33
|
+
# Constructs a new QueryOptions and yield it to the proc if one is present.
|
34
|
+
# Subclasses may override this method to provide sane defaults.
|
35
|
+
#
|
36
|
+
# @param proc [Proc] a proc or nil
|
37
|
+
#
|
38
|
+
# @return [ActsAsRecursiveTree::Options::QueryOptions] the new QueryOptions instance
|
28
39
|
def get_query_options(proc)
|
29
40
|
opts = ActsAsRecursiveTree::Options::QueryOptions.new
|
30
41
|
|
@@ -38,18 +49,9 @@ module ActsAsRecursiveTree
|
|
38
49
|
end
|
39
50
|
|
40
51
|
def build
|
41
|
-
|
42
|
-
create_select_manger.as(recursive_temp_table.name)
|
43
|
-
).on(
|
44
|
-
base_table[primary_key].eq(recursive_temp_table[primary_key])
|
45
|
-
)
|
46
|
-
|
47
|
-
relation = klass.joins(final_select_mgr.join_sources)
|
52
|
+
relation = Strategy.for_query_options(@query_opts).build(self)
|
48
53
|
|
49
54
|
relation = apply_except_id(relation)
|
50
|
-
relation = apply_depth(relation)
|
51
|
-
relation = apply_order(relation)
|
52
|
-
|
53
55
|
relation
|
54
56
|
end
|
55
57
|
|
@@ -69,8 +71,14 @@ module ActsAsRecursiveTree
|
|
69
71
|
relation.order(recursive_temp_table[depth_column].asc)
|
70
72
|
end
|
71
73
|
|
72
|
-
def create_select_manger
|
73
|
-
|
74
|
+
def create_select_manger(column = nil)
|
75
|
+
projections = if column
|
76
|
+
travers_loc_table[column]
|
77
|
+
else
|
78
|
+
Arel.star
|
79
|
+
end
|
80
|
+
|
81
|
+
travers_loc_table.project(projections).with(:recursive, build_cte_table)
|
74
82
|
end
|
75
83
|
|
76
84
|
def build_cte_table
|
@@ -125,6 +133,9 @@ module ActsAsRecursiveTree
|
|
125
133
|
relation.merge(condition)
|
126
134
|
end
|
127
135
|
|
136
|
+
#
|
137
|
+
# U
|
138
|
+
#
|
128
139
|
def build_join_condition
|
129
140
|
raise 'not implemented'
|
130
141
|
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
module ActsAsRecursiveTree
|
2
|
+
module Builders
|
3
|
+
#
|
4
|
+
# Strategy module for different strategies of how to build the resulting query.
|
5
|
+
#
|
6
|
+
module Strategy
|
7
|
+
extend ActiveSupport::Autoload
|
8
|
+
|
9
|
+
autoload :Join
|
10
|
+
autoload :Subselect
|
11
|
+
|
12
|
+
#
|
13
|
+
# Returns a Strategy appropriate for query_opts
|
14
|
+
#
|
15
|
+
# @param query_opts [ActsAsRecursiveTree::Options::QueryOptions]
|
16
|
+
#
|
17
|
+
# @return a strategy class best suited for the opts
|
18
|
+
def self.for_query_options(query_opts)
|
19
|
+
if query_opts.depth_present? || query_opts.ensure_ordering
|
20
|
+
Join
|
21
|
+
else
|
22
|
+
Subselect
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
module ActsAsRecursiveTree
|
2
|
+
module Builders
|
3
|
+
module Strategy
|
4
|
+
#
|
5
|
+
# Build a relation using an INNER JOIN.
|
6
|
+
#
|
7
|
+
module Join
|
8
|
+
#
|
9
|
+
# Builds the relation.
|
10
|
+
#
|
11
|
+
# @param builder [ActsAsRecursiveTree::Builders::RelationBuilder]
|
12
|
+
# @return [ActiveRecord::Relation]
|
13
|
+
def self.build(builder)
|
14
|
+
final_select_mgr = builder.base_table.join(
|
15
|
+
builder.create_select_manger.as(builder.recursive_temp_table.name)
|
16
|
+
).on(
|
17
|
+
builder.base_table[builder.primary_key].eq(builder.recursive_temp_table[builder.primary_key])
|
18
|
+
)
|
19
|
+
|
20
|
+
relation = builder.klass.joins(final_select_mgr.join_sources)
|
21
|
+
|
22
|
+
relation = builder.apply_depth(relation)
|
23
|
+
relation = builder.apply_order(relation)
|
24
|
+
relation
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
module ActsAsRecursiveTree
|
2
|
+
module Builders
|
3
|
+
module Strategy
|
4
|
+
#
|
5
|
+
# Strategy for building a relation using an WHERE ID IN(...).
|
6
|
+
#
|
7
|
+
module Subselect
|
8
|
+
#
|
9
|
+
# Builds the relation.
|
10
|
+
#
|
11
|
+
# @param builder [ActsAsRecursiveTree::Builders::RelationBuilder]
|
12
|
+
# @return [ActiveRecord::Relation]
|
13
|
+
def self.build(builder)
|
14
|
+
builder.klass.where(
|
15
|
+
builder.base_table[builder.primary_key].in(
|
16
|
+
builder.create_select_manger(builder.primary_key)
|
17
|
+
)
|
18
|
+
)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
module ActsAsRecursiveTree
|
2
|
+
#
|
3
|
+
# Stores the configuration of one Model class
|
4
|
+
#
|
5
|
+
class Config
|
6
|
+
attr_reader :parent_key, :parent_type_column, :depth_column
|
7
|
+
|
8
|
+
def initialize(model_class:, parent_key:, parent_type_column:, depth_column: :recursive_depth)
|
9
|
+
@model_class = model_class
|
10
|
+
@parent_key = parent_key
|
11
|
+
@parent_type_column = parent_type_column
|
12
|
+
@depth_column = depth_column
|
13
|
+
end
|
14
|
+
|
15
|
+
#
|
16
|
+
# Returns the primary key for the model class.
|
17
|
+
# @return [Symbol]
|
18
|
+
def primary_key
|
19
|
+
@primary_key ||= @model_class.primary_key.to_sym
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: acts_as_recursive_tree
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.0
|
4
|
+
version: 2.1.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Wolfgang Wedelich-John
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2018-
|
11
|
+
date: 2018-04-06 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activerecord
|
@@ -127,6 +127,10 @@ files:
|
|
127
127
|
- lib/acts_as_recursive_tree/builders/descendants.rb
|
128
128
|
- lib/acts_as_recursive_tree/builders/leaves.rb
|
129
129
|
- lib/acts_as_recursive_tree/builders/relation_builder.rb
|
130
|
+
- lib/acts_as_recursive_tree/builders/strategy.rb
|
131
|
+
- lib/acts_as_recursive_tree/builders/strategy/join.rb
|
132
|
+
- lib/acts_as_recursive_tree/builders/strategy/subselect.rb
|
133
|
+
- lib/acts_as_recursive_tree/config.rb
|
130
134
|
- lib/acts_as_recursive_tree/model.rb
|
131
135
|
- lib/acts_as_recursive_tree/options.rb
|
132
136
|
- lib/acts_as_recursive_tree/options/depth_condition.rb
|
@@ -165,7 +169,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
165
169
|
version: '0'
|
166
170
|
requirements: []
|
167
171
|
rubyforge_project:
|
168
|
-
rubygems_version: 2.6
|
172
|
+
rubygems_version: 2.7.6
|
169
173
|
signing_key:
|
170
174
|
specification_version: 4
|
171
175
|
summary: Drop in replacement for acts_as_tree but using recursive queries
|
@@ -180,4 +184,3 @@ test_files:
|
|
180
184
|
- spec/model/relation_spec.rb
|
181
185
|
- spec/spec_helper.rb
|
182
186
|
- spec/values_spec.rb
|
183
|
-
has_rdoc:
|