acts_as_recursive_tree 2.1.1 → 3.1.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.
Files changed (50) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/ci.yml +44 -0
  3. data/.github/workflows/lint.yml +31 -0
  4. data/.github/workflows/rubygem.yml +37 -0
  5. data/.gitignore +3 -1
  6. data/.rubocop.yml +33 -1
  7. data/.rubocop_todo.yml +28 -281
  8. data/Appraisals +21 -0
  9. data/CHANGELOG.md +16 -1
  10. data/Gemfile +2 -0
  11. data/README.md +9 -0
  12. data/Rakefile +8 -8
  13. data/acts_as_recursive_tree.gemspec +27 -18
  14. data/gemfiles/ar_52.gemfile +8 -0
  15. data/gemfiles/ar_60.gemfile +8 -0
  16. data/gemfiles/ar_61.gemfile +8 -0
  17. data/gemfiles/ar_70.gemfile +8 -0
  18. data/lib/acts_as_recursive_tree/acts_macro.rb +6 -6
  19. data/lib/acts_as_recursive_tree/associations.rb +10 -8
  20. data/lib/acts_as_recursive_tree/builders/ancestors.rb +3 -2
  21. data/lib/acts_as_recursive_tree/builders/descendants.rb +3 -1
  22. data/lib/acts_as_recursive_tree/builders/leaves.rb +7 -8
  23. data/lib/acts_as_recursive_tree/builders/relation_builder.rb +14 -10
  24. data/lib/acts_as_recursive_tree/builders/{strategy → strategies}/ancestor.rb +3 -1
  25. data/lib/acts_as_recursive_tree/builders/{strategy → strategies}/descendant.rb +3 -1
  26. data/lib/acts_as_recursive_tree/builders/{strategy → strategies}/join.rb +5 -3
  27. data/lib/acts_as_recursive_tree/builders/{strategy → strategies}/subselect.rb +3 -1
  28. data/lib/acts_as_recursive_tree/builders/{strategy.rb → strategies.rb} +3 -9
  29. data/lib/acts_as_recursive_tree/config.rb +2 -0
  30. data/lib/acts_as_recursive_tree/model.rb +9 -8
  31. data/lib/acts_as_recursive_tree/options/depth_condition.rb +3 -2
  32. data/lib/acts_as_recursive_tree/options/query_options.rb +4 -2
  33. data/lib/acts_as_recursive_tree/options/values.rb +28 -18
  34. data/lib/acts_as_recursive_tree/railtie.rb +2 -0
  35. data/lib/acts_as_recursive_tree/scopes.rb +8 -4
  36. data/lib/acts_as_recursive_tree/version.rb +3 -1
  37. data/lib/acts_as_recursive_tree.rb +7 -11
  38. data/spec/builders_spec.rb +21 -12
  39. data/spec/db/database.rb +13 -4
  40. data/spec/db/database.yml +2 -5
  41. data/spec/db/models.rb +12 -11
  42. data/spec/db/schema.rb +3 -4
  43. data/spec/model/location_spec.rb +7 -11
  44. data/spec/model/node_spec.rb +35 -49
  45. data/spec/model/relation_spec.rb +6 -11
  46. data/spec/spec_helper.rb +54 -55
  47. data/spec/values_spec.rb +30 -19
  48. metadata +111 -26
  49. data/lib/acts_as_recursive_tree/builders.rb +0 -14
  50. data/lib/acts_as_recursive_tree/options.rb +0 -9
@@ -0,0 +1,8 @@
1
+ # This file was generated by Appraisal
2
+
3
+ source "https://rubygems.org"
4
+
5
+ gem "activerecord", "~> 5.2.0"
6
+ gem "activesupport", "~> 5.2.0"
7
+
8
+ gemspec path: "../"
@@ -0,0 +1,8 @@
1
+ # This file was generated by Appraisal
2
+
3
+ source "https://rubygems.org"
4
+
5
+ gem "activerecord", "~> 6.0.0"
6
+ gem "activesupport", "~> 6.0.0"
7
+
8
+ gemspec path: "../"
@@ -0,0 +1,8 @@
1
+ # This file was generated by Appraisal
2
+
3
+ source "https://rubygems.org"
4
+
5
+ gem "activerecord", "~> 6.1.0"
6
+ gem "activesupport", "~> 6.1.0"
7
+
8
+ gemspec path: "../"
@@ -0,0 +1,8 @@
1
+ # This file was generated by Appraisal
2
+
3
+ source "https://rubygems.org"
4
+
5
+ gem "activerecord", "~> 7.0.0"
6
+ gem "activesupport", "~> 7.0.0"
7
+
8
+ gemspec path: "../"
@@ -1,17 +1,17 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module ActsAsRecursiveTree
2
4
  module ActsMacro
3
-
4
5
  ##
5
6
  # Configuration options are:
6
7
  #
7
8
  # * <tt>foreign_key</tt> - specifies the column name to use for tracking
8
9
  # of the tree (default: +parent_id+)
9
10
  def recursive_tree(parent_key: :parent_id, parent_type_column: nil)
10
-
11
11
  class_attribute :_recursive_tree_config
12
12
  self._recursive_tree_config = Config.new(
13
- model_class: self,
14
- parent_key: parent_key.to_sym,
13
+ model_class: self,
14
+ parent_key: parent_key.to_sym,
15
15
  parent_type_column: parent_type_column.try(:to_sym)
16
16
  )
17
17
 
@@ -20,6 +20,6 @@ module ActsAsRecursiveTree
20
20
  include ActsAsRecursiveTree::Scopes
21
21
  end
22
22
 
23
- alias_method :acts_as_tree, :recursive_tree
23
+ alias acts_as_tree recursive_tree
24
24
  end
25
- end
25
+ end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'active_support/concern'
2
4
 
3
5
  module ActsAsRecursiveTree
@@ -6,20 +8,20 @@ module ActsAsRecursiveTree
6
8
 
7
9
  included do
8
10
  belongs_to :parent,
9
- class_name: self.base_class.to_s,
10
- foreign_key: self._recursive_tree_config.parent_key,
11
- inverse_of: :children,
12
- optional: true
11
+ class_name: base_class.to_s,
12
+ foreign_key: _recursive_tree_config.parent_key,
13
+ inverse_of: :children,
14
+ optional: true
13
15
 
14
16
  has_many :children,
15
- class_name: self.base_class.to_s,
16
- foreign_key: self._recursive_tree_config.parent_key,
17
- inverse_of: :parent
17
+ class_name: base_class.to_s,
18
+ foreign_key: _recursive_tree_config.parent_key,
19
+ inverse_of: :parent
18
20
 
19
21
  has_many :self_and_siblings,
20
22
  through: :parent,
21
23
  source: :children,
22
- class_name: self.base_class.to_s
24
+ class_name: base_class.to_s
23
25
  end
24
26
  end
25
27
  end
@@ -1,14 +1,15 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module ActsAsRecursiveTree
2
4
  module Builders
3
5
  class Ancestors < RelationBuilder
4
- self.traversal_strategy = ActsAsRecursiveTree::Builders::Strategy::Ancestor
6
+ self.traversal_strategy = ActsAsRecursiveTree::Builders::Strategies::Ancestor
5
7
 
6
8
  def get_query_options(_)
7
9
  opts = super
8
10
  opts.ensure_ordering!
9
11
  opts
10
12
  end
11
-
12
13
  end
13
14
  end
14
15
  end
@@ -1,7 +1,9 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module ActsAsRecursiveTree
2
4
  module Builders
3
5
  class Descendants < RelationBuilder
4
- self.traversal_strategy = ActsAsRecursiveTree::Builders::Strategy::Descendant
6
+ self.traversal_strategy = ActsAsRecursiveTree::Builders::Strategies::Descendant
5
7
  end
6
8
  end
7
9
  end
@@ -1,26 +1,25 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module ActsAsRecursiveTree
2
4
  module Builders
3
5
  class Leaves < Descendants
4
-
5
6
  def create_select_manger(column = nil)
6
7
  select_manager = super
7
8
 
8
9
  select_manager.where(
9
- travers_loc_table[primary_key].not_in(
10
- travers_loc_table.where(
11
- travers_loc_table[parent_key].not_eq(nil)
12
- ).project(travers_loc_table[parent_key])
13
- )
10
+ travers_loc_table[primary_key].not_in(
11
+ travers_loc_table.where(
12
+ travers_loc_table[parent_key].not_eq(nil)
13
+ ).project(travers_loc_table[parent_key])
14
+ )
14
15
  )
15
16
  select_manager
16
-
17
17
  end
18
18
 
19
19
  def get_query_options(_)
20
20
  # do not allow any custom options
21
21
  ActsAsRecursiveTree::Options::QueryOptions.new
22
22
  end
23
-
24
23
  end
25
24
  end
26
25
  end
@@ -1,10 +1,11 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module ActsAsRecursiveTree
2
4
  module Builders
3
5
  #
4
6
  # Constructs the Arel necessary for recursion.
5
7
  #
6
8
  class RelationBuilder
7
-
8
9
  def self.build(klass, ids, exclude_ids: false, &block)
9
10
  new(klass, ids, exclude_ids: exclude_ids, &block).build
10
11
  end
@@ -12,6 +13,7 @@ module ActsAsRecursiveTree
12
13
  class_attribute :traversal_strategy, instance_writer: false
13
14
 
14
15
  attr_reader :klass, :ids, :recursive_temp_table, :travers_loc_table, :without_ids
16
+
15
17
  mattr_reader(:random) { Random.new }
16
18
 
17
19
  # Delegators for easier accessing config and query options
@@ -41,7 +43,7 @@ module ActsAsRecursiveTree
41
43
  def get_query_options(proc)
42
44
  opts = ActsAsRecursiveTree::Options::QueryOptions.new
43
45
 
44
- proc.call(opts) if proc
46
+ proc&.call(opts)
45
47
 
46
48
  opts
47
49
  end
@@ -51,14 +53,14 @@ module ActsAsRecursiveTree
51
53
  end
52
54
 
53
55
  def build
54
- relation = Strategy.for_query_options(@query_opts).build(self)
56
+ relation = Strategies.for_query_options(@query_opts).build(self)
55
57
 
56
- relation = apply_except_id(relation)
57
- relation
58
+ apply_except_id(relation)
58
59
  end
59
60
 
60
61
  def apply_except_id(relation)
61
62
  return relation unless without_ids
63
+
62
64
  relation.where(ids.apply_negated_to(base_table[primary_key]))
63
65
  end
64
66
 
@@ -70,10 +72,10 @@ module ActsAsRecursiveTree
70
72
 
71
73
  def create_select_manger(column = nil)
72
74
  projections = if column
73
- travers_loc_table[column]
74
- else
75
- Arel.star
76
- end
75
+ travers_loc_table[column]
76
+ else
77
+ Arel.star
78
+ end
77
79
 
78
80
  select_mgr = travers_loc_table.project(projections).with(:recursive, build_cte_table)
79
81
 
@@ -114,7 +116,8 @@ module ActsAsRecursiveTree
114
116
  end
115
117
 
116
118
  def apply_parent_type_column(arel_condition)
117
- return arel_condition unless parent_type_column.present?
119
+ return arel_condition if parent_type_column.blank?
120
+
118
121
  arel_condition.and(base_table[parent_type_column].eq(klass.base_class))
119
122
  end
120
123
 
@@ -131,6 +134,7 @@ module ActsAsRecursiveTree
131
134
  def apply_query_opts_condition(relation)
132
135
  # check with nil? and not #present?/#blank? which will execute the query
133
136
  return relation if condition.nil?
137
+
134
138
  relation.merge(condition)
135
139
  end
136
140
  end
@@ -1,6 +1,8 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module ActsAsRecursiveTree
2
4
  module Builders
3
- module Strategy
5
+ module Strategies
4
6
  #
5
7
  # Strategy for building ancestors relation
6
8
  #
@@ -1,6 +1,8 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module ActsAsRecursiveTree
2
4
  module Builders
3
- module Strategy
5
+ module Strategies
4
6
  #
5
7
  # Strategy for building descendants relation
6
8
  #
@@ -1,6 +1,8 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module ActsAsRecursiveTree
2
4
  module Builders
3
- module Strategy
5
+ module Strategies
4
6
  #
5
7
  # Build a relation using an INNER JOIN.
6
8
  #
@@ -19,12 +21,12 @@ module ActsAsRecursiveTree
19
21
 
20
22
  relation = builder.klass.joins(final_select_mgr.join_sources)
21
23
 
22
- relation = apply_order(builder, relation)
23
- relation
24
+ apply_order(builder, relation)
24
25
  end
25
26
 
26
27
  def self.apply_order(builder, relation)
27
28
  return relation unless builder.ensure_ordering
29
+
28
30
  relation.order(builder.recursive_temp_table[builder.depth_column].asc)
29
31
  end
30
32
  end
@@ -1,6 +1,8 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module ActsAsRecursiveTree
2
4
  module Builders
3
- module Strategy
5
+ module Strategies
4
6
  #
5
7
  # Strategy for building a relation using an WHERE ID IN(...).
6
8
  #
@@ -1,17 +1,11 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module ActsAsRecursiveTree
2
4
  module Builders
3
5
  #
4
6
  # Strategy module for different strategies of how to build the resulting query.
5
7
  #
6
- module Strategy
7
- extend ActiveSupport::Autoload
8
-
9
- autoload :Join
10
- autoload :Subselect
11
-
12
- autoload :Descendant
13
- autoload :Ancestor
14
-
8
+ module Strategies
15
9
  #
16
10
  # Returns a Strategy appropriate for query_opts
17
11
  #
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module ActsAsRecursiveTree
2
4
  #
3
5
  # Stores the configuration of one Model class
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module ActsAsRecursiveTree
2
4
  module Model
3
5
  extend ActiveSupport::Concern
@@ -40,7 +42,7 @@ module ActsAsRecursiveTree
40
42
  ##
41
43
  # Returns the root node of the tree.
42
44
  def root
43
- self_and_ancestors.where(self._recursive_tree_config.parent_key => nil).first
45
+ self_and_ancestors.where(_recursive_tree_config.parent_key => nil).first
44
46
  end
45
47
 
46
48
  ##
@@ -48,7 +50,7 @@ module ActsAsRecursiveTree
48
50
  #
49
51
  # subchild1.siblings # => [subchild2]
50
52
  def siblings
51
- self_and_siblings.where.not(id: self.id)
53
+ self_and_siblings.where.not(id: id)
52
54
  end
53
55
 
54
56
  ##
@@ -57,11 +59,11 @@ module ActsAsRecursiveTree
57
59
  # root.self_and_children # => [root, child1]
58
60
  def self_and_children
59
61
  table = self.class.arel_table
60
- id = self.attributes[self._recursive_tree_config.primary_key.to_s]
62
+ id = attributes[_recursive_tree_config.primary_key.to_s]
61
63
 
62
64
  base_class.where(
63
- table[self._recursive_tree_config.primary_key].eq(id).or(
64
- table[self._recursive_tree_config.parent_key].eq(id)
65
+ table[_recursive_tree_config.primary_key].eq(id).or(
66
+ table[_recursive_tree_config.parent_key].eq(id)
65
67
  )
66
68
  )
67
69
  end
@@ -73,13 +75,12 @@ module ActsAsRecursiveTree
73
75
  base_class.leaves_of(self)
74
76
  end
75
77
 
76
-
77
78
  # Returns true if node has no parent, false otherwise
78
79
  #
79
80
  # subchild1.root? # => false
80
81
  # root.root? # => true
81
82
  def root?
82
- self.attributes[self._recursive_tree_config.parent_key.to_s].blank?
83
+ attributes[_recursive_tree_config.parent_key.to_s].blank?
83
84
  end
84
85
 
85
86
  # Returns true if node has no children, false otherwise
@@ -87,7 +88,7 @@ module ActsAsRecursiveTree
87
88
  # subchild1.leaf? # => true
88
89
  # child1.leaf? # => false
89
90
  def leaf?
90
- !children.any?
91
+ children.none?
91
92
  end
92
93
 
93
94
  def base_class
@@ -1,7 +1,8 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module ActsAsRecursiveTree
2
4
  module Options
3
5
  class DepthCondition
4
-
5
6
  def ==(other)
6
7
  @value = Values.create(other)
7
8
  @operation = true
@@ -45,4 +46,4 @@ module ActsAsRecursiveTree
45
46
  end
46
47
  end
47
48
  end
48
- end
49
+ end
@@ -1,8 +1,9 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module ActsAsRecursiveTree
2
4
  module Options
3
5
  class QueryOptions
4
-
5
- STRATEGIES = %i[subselect, join].freeze
6
+ STRATEGIES = %i[subselect join].freeze
6
7
 
7
8
  attr_accessor :condition
8
9
  attr_reader :ensure_ordering, :query_strategy
@@ -21,6 +22,7 @@ module ActsAsRecursiveTree
21
22
 
22
23
  def query_strategy=(strategy)
23
24
  raise "invalid strategy #{strategy} - only #{STRATEGIES} are allowed" unless STRATEGIES.include?(strategy)
25
+
24
26
  @query_strategy = strategy
25
27
  end
26
28
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module ActsAsRecursiveTree
2
4
  module Options
3
5
  module Values
@@ -13,13 +15,9 @@ module ActsAsRecursiveTree
13
15
  value
14
16
  end
15
17
 
16
- def apply_to(attribute)
17
-
18
- end
19
-
20
- def apply_negated_to(attribute)
18
+ def apply_to(attribute); end
21
19
 
22
- end
20
+ def apply_negated_to(attribute); end
23
21
  end
24
22
 
25
23
  class SingleValue < Base
@@ -38,6 +36,16 @@ module ActsAsRecursiveTree
38
36
  end
39
37
  end
40
38
 
39
+ class RangeValue < Base
40
+ def apply_to(attribute)
41
+ attribute.between(prepared_value)
42
+ end
43
+
44
+ def apply_negated_to(attribute)
45
+ attribute.not_between(prepared_value)
46
+ end
47
+ end
48
+
41
49
  class MultiValue < Base
42
50
  def apply_to(attribute)
43
51
  attribute.in(prepared_value)
@@ -58,20 +66,22 @@ module ActsAsRecursiveTree
58
66
 
59
67
  def self.create(value, config = nil)
60
68
  klass = case value
61
- when ::Numeric, ::String
62
- SingleValue
63
- when ::ActiveRecord::Relation
64
- Relation
65
- when Enumerable
66
- MultiValue
67
- when ::ActiveRecord::Base
68
- ActiveRecord
69
- else
70
- raise "#{value.class} is not supported"
71
- end
69
+ when ::Numeric, ::String
70
+ SingleValue
71
+ when ::ActiveRecord::Relation
72
+ Relation
73
+ when Range
74
+ RangeValue
75
+ when Enumerable
76
+ MultiValue
77
+ when ::ActiveRecord::Base
78
+ ActiveRecord
79
+ else
80
+ raise "#{value.class} is not supported"
81
+ end
72
82
 
73
83
  klass.new(value, config)
74
84
  end
75
85
  end
76
86
  end
77
- end
87
+ end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module ActsAsRecursiveTree
2
4
  class Railtie < Rails::Railtie
3
5
  initializer 'acts_as_recursive_tree.active_record_initializer' do
@@ -1,13 +1,17 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module ActsAsRecursiveTree
2
4
  module Scopes
3
5
  extend ActiveSupport::Concern
4
6
 
5
7
  included do
6
- scope :roots, -> {
8
+ scope :roots, lambda {
7
9
  rel = where(_recursive_tree_config.parent_key => nil)
8
- rel = rel.or(
9
- where.not(_recursive_tree_config.parent_type_column => self.to_s)
10
- ) if _recursive_tree_config.parent_type_column
10
+ if _recursive_tree_config.parent_type_column
11
+ rel = rel.or(
12
+ where.not(_recursive_tree_config.parent_type_column => to_s)
13
+ )
14
+ end
11
15
 
12
16
  rel
13
17
  }
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module ActsAsRecursiveTree
2
- VERSION = '2.1.1'.freeze
4
+ VERSION = '3.1.0'
3
5
  end
@@ -1,15 +1,11 @@
1
- require 'active_support/all'
1
+ # frozen_string_literal: true
2
+
2
3
  require_relative 'acts_as_recursive_tree/railtie' if defined?(Rails)
4
+ require 'zeitwerk'
3
5
 
4
- module ActsAsRecursiveTree
5
- extend ActiveSupport::Autoload
6
+ loader = Zeitwerk::Loader.for_gem
7
+ loader.setup
6
8
 
7
- autoload :Config
8
- autoload :ActsMacro
9
- autoload :Model
10
- autoload :Associations
11
- autoload :Scopes
12
- autoload :Version
13
- autoload :Options
14
- autoload :Builders
9
+ module ActsAsRecursiveTree
10
+ # nothing special here
15
11
  end
@@ -1,13 +1,17 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'spec_helper'
2
4
 
3
5
  shared_context 'setup with enforced ordering' do
4
6
  let(:ordering) { false }
5
7
  include_context 'base_setup' do
6
- let(:proc) { -> (config) { config.ensure_ordering! } }
8
+ let(:proc) { ->(config) { config.ensure_ordering! } }
7
9
  end
8
10
  end
9
11
 
10
12
  shared_context 'base_setup' do
13
+ subject(:query) { builder.build.to_sql }
14
+
11
15
  let(:model_id) { 1 }
12
16
  let(:model_class) { Node }
13
17
  let(:exclude_ids) { false }
@@ -15,17 +19,20 @@ shared_context 'base_setup' do
15
19
  let(:builder) do
16
20
  described_class.new(model_class, model_id, exclude_ids: exclude_ids, &proc)
17
21
  end
18
- subject(:query) { builder.build.to_sql }
19
22
  end
20
23
 
21
24
  shared_examples 'basic recursive examples' do
22
25
  it { is_expected.to start_with "SELECT \"#{model_class.table_name}\".* FROM \"#{model_class.table_name}\"" }
23
- it { is_expected.to match /WHERE "#{model_class.table_name}"."#{model_class.primary_key}" = #{model_id}/ }
24
- it { is_expected.to match /WITH RECURSIVE "#{builder.travers_loc_table.name}" AS/ }
25
- it { is_expected.to match /SELECT "#{model_class.table_name}"."#{model_class.primary_key}", "#{model_class.table_name}"."#{model_class._recursive_tree_config.parent_key}", 0 AS recursive_depth FROM "#{model_class.table_name}"/ }
26
- it { is_expected.to match /SELECT "#{model_class.table_name}"."#{model_class.primary_key}", "#{model_class.table_name}"."#{model_class._recursive_tree_config.parent_key}", \("#{builder.travers_loc_table.name}"."recursive_depth" \+ 1\) AS recursive_depth FROM "#{model_class.table_name}"/ }
27
- it { is_expected.to match /#{Regexp.escape(builder.travers_loc_table.project(Arel.star).to_sql)}/ }
28
- it { is_expected.to match /"#{model_class.table_name}"."#{model_class.primary_key}" = "#{builder.recursive_temp_table.name}"."#{model_class.primary_key}"/ }
26
+
27
+ it { is_expected.to match(/WHERE "#{model_class.table_name}"."#{model_class.primary_key}" = #{model_id}/) }
28
+
29
+ it { is_expected.to match(/WITH RECURSIVE "#{builder.travers_loc_table.name}" AS/) }
30
+
31
+ it { is_expected.to match(/SELECT "#{model_class.table_name}"."#{model_class.primary_key}", "#{model_class.table_name}"."#{model_class._recursive_tree_config.parent_key}", 0 AS recursive_depth FROM "#{model_class.table_name}"/) }
32
+
33
+ it {
34
+ expect(subject).to match(/SELECT "#{model_class.table_name}"."#{model_class.primary_key}", "#{model_class.table_name}"."#{model_class._recursive_tree_config.parent_key}", \("#{builder.travers_loc_table.name}"."recursive_depth" \+ 1\) AS recursive_depth FROM "#{model_class.table_name}"/)
35
+ }
29
36
  end
30
37
 
31
38
  shared_examples 'build recursive query' do
@@ -63,13 +70,14 @@ end
63
70
  shared_examples 'ancestor query' do
64
71
  include_context 'base_setup'
65
72
 
66
- 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}"/ }
73
+ 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}"/) }
67
74
  end
68
75
 
69
76
  shared_examples 'descendant query' do
70
77
  include_context 'base_setup'
71
78
 
72
- 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}"/ }
79
+ 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
+ it { is_expected.to match(/#{Regexp.escape(builder.travers_loc_table.project(builder.travers_loc_table[model_class.primary_key]).to_sql)}/) }
73
81
  end
74
82
 
75
83
  shared_context 'context with ordering' do
@@ -85,11 +93,11 @@ shared_context 'context without ordering' do
85
93
  end
86
94
 
87
95
  shared_examples 'with ordering' do
88
- it { is_expected.to match /ORDER BY #{Regexp.escape(builder.recursive_temp_table[model_class._recursive_tree_config.depth_column].asc.to_sql)}/ }
96
+ it { is_expected.to match(/ORDER BY #{Regexp.escape(builder.recursive_temp_table[model_class._recursive_tree_config.depth_column].asc.to_sql)}/) }
89
97
  end
90
98
 
91
99
  shared_examples 'without ordering' do
92
- it { is_expected.to_not match /ORDER BY/ }
100
+ it { is_expected.not_to match(/ORDER BY/) }
93
101
  end
94
102
 
95
103
  describe ActsAsRecursiveTree::Builders::Descendants do
@@ -113,6 +121,7 @@ describe ActsAsRecursiveTree::Builders::Ancestors do
113
121
  it_behaves_like 'ancestor query'
114
122
  include_context 'context with ordering'
115
123
  end
124
+
116
125
  context 'with options' do
117
126
  include_context 'setup with enforced ordering' do
118
127
  it_behaves_like 'with ordering'