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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: 064f977e7f4e77083f3a967fce16c6c47fc29ee9
4
- data.tar.gz: 2b8e5949381e248c33034868ee816126367e19bd
2
+ SHA256:
3
+ metadata.gz: a28e3f6eadbc8b37622ef525b25e654b13c0903f4053adb096f4f853f36ccc06
4
+ data.tar.gz: f2614872c77bf263526ac596bbb82438b75af1e49e393c6464e07515c5605288
5
5
  SHA512:
6
- metadata.gz: 91e3f8cdf111f4efed5618391d806ccab6e5bdb2c8e5325862292e23a67d990aaa86de199dfffabade3f0ee6a18ba501d9032e9a700b9dba567eb75e0d6265ec
7
- data.tar.gz: cb6576280d42539dc013e96b07414cae5ad49b416a28518c742731fb43697ec9fc997da237cf8f0cbc5f53c01bf530fd37353bb3108cf9e1e06313c2174aecc9
6
+ metadata.gz: 9a4ccf41395828283e882f8e88b6e9c8a7edea75995219840d2c6d07da69bbb8bb6f15aeec6cddf8a105f4f8ad15d3dfddad2bf7aaeead54074fffa28030bd68
7
+ data.tar.gz: c48904528902e0554d1a46dea5883afcc28473597f4df2493ccf1015e80967b2490cae5f41fb5dac9eb7925a2c9d00feeb9637b902366e3dc1be0d6dddc3c7ab
@@ -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
 
@@ -4,6 +4,7 @@ require_relative 'acts_as_recursive_tree/railtie' if defined?(Rails)
4
4
  module ActsAsRecursiveTree
5
5
  extend ActiveSupport::Autoload
6
6
 
7
+ autoload :Config
7
8
  autoload :ActsMacro
8
9
  autoload :Model
9
10
  autoload :Associations
@@ -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 = OpenStruct.new(
15
- primary_key: self.primary_key.to_sym,
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
- class_name: self.base_class.to_s,
21
- primary_key: self._recursive_tree_config.parent_key,
22
- foreign_key: self._recursive_tree_config.parent_key
20
+ through: :parent,
21
+ source: :children,
22
+ class_name: self.base_class.to_s
23
23
  end
24
24
  end
25
25
  end
@@ -5,6 +5,7 @@ module ActsAsRecursiveTree
5
5
  autoload :Values
6
6
  autoload :DepthCondition
7
7
  autoload :QueryOptions
8
+ autoload :Strategy
8
9
  autoload :RelationBuilder
9
10
  autoload :Descendants
10
11
  autoload :Ancestors
@@ -2,7 +2,7 @@ module ActsAsRecursiveTree
2
2
  module Builders
3
3
  class Leaves < Descendants
4
4
 
5
- def create_select_manger
5
+ def create_select_manger(column = nil)
6
6
  select_manager = super
7
7
 
8
8
  select_manager.where(
@@ -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
- final_select_mgr = base_table.join(
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
- travers_loc_table.project(Arel.star).with(:recursive, build_cte_table)
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
@@ -1,3 +1,3 @@
1
1
  module ActsAsRecursiveTree
2
- VERSION = '2.0.2'.freeze
2
+ VERSION = '2.1.0'.freeze
3
3
  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.2
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-02-06 00:00:00.000000000 Z
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.14
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: