active_record_extended 2.2.0 → 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.
@@ -1,119 +1,121 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module ActiveRecordExtended
4
- module WhereChain
5
- # Finds Records that have an array column that contain any a set of values
6
- # User.where.overlap(tags: [1,2])
7
- # # SELECT * FROM users WHERE tags && {1,2}
8
- def overlaps(opts, *rest)
9
- substitute_comparisons(opts, rest, Arel::Nodes::Overlaps, "overlap")
10
- end
11
- alias overlap overlaps
12
-
13
- # Finds Records that contain an element in an array column
14
- # User.where.any(tags: 3)
15
- # # SELECT user.* FROM user WHERE 3 = ANY(user.tags)
16
- def any(opts, *rest)
17
- equality_to_function("ANY", opts, rest)
18
- end
4
+ module QueryMethods
5
+ module WhereChain
6
+ # Finds Records that have an array column that contain any a set of values
7
+ # User.where.overlap(tags: [1,2])
8
+ # # SELECT * FROM users WHERE tags && {1,2}
9
+ def overlaps(opts, *rest)
10
+ substitute_comparisons(opts, rest, Arel::Nodes::Overlaps, "overlap")
11
+ end
12
+ alias overlap overlaps
19
13
 
20
- # Finds Records that contain a single matchable array element
21
- # User.where.all(tags: 3)
22
- # # SELECT user.* FROM user WHERE 3 = ALL(user.tags)
23
- def all(opts, *rest)
24
- equality_to_function("ALL", opts, rest)
25
- end
14
+ # Finds Records that contain an element in an array column
15
+ # User.where.any(tags: 3)
16
+ # # SELECT user.* FROM user WHERE 3 = ANY(user.tags)
17
+ def any(opts, *rest)
18
+ equality_to_function("ANY", opts, rest)
19
+ end
26
20
 
27
- # Finds Records that contains a nested set elements
28
- #
29
- # Array Column Type:
30
- # User.where.contains(tags: [1, 3])
31
- # # SELECT user.* FROM user WHERE user.tags @> {1,3}
32
- #
33
- # HStore Column Type:
34
- # User.where.contains(data: { nickname: 'chainer' })
35
- # # SELECT user.* FROM user WHERE user.data @> 'nickname' => 'chainer'
36
- #
37
- # JSONB Column Type:
38
- # User.where.contains(data: { nickname: 'chainer' })
39
- # # SELECT user.* FROM user WHERE user.data @> {'nickname': 'chainer'}
40
- #
41
- # This can also be used along side joined tables
42
- #
43
- # JSONB Column Type Example:
44
- # Tag.joins(:user).where.contains(user: { data: { nickname: 'chainer' } })
45
- # # SELECT tags.* FROM tags INNER JOIN user on user.id = tags.user_id WHERE user.data @> { nickname: 'chainer' }
46
- #
47
- def contains(opts, *rest)
48
- if ActiveRecordExtended::AR_VERSION_GTE_6_1
49
- return substitute_comparisons(opts, rest, Arel::Nodes::Contains, "contains")
21
+ # Finds Records that contain a single matchable array element
22
+ # User.where.all(tags: 3)
23
+ # # SELECT user.* FROM user WHERE 3 = ALL(user.tags)
24
+ def all(opts, *rest)
25
+ equality_to_function("ALL", opts, rest)
50
26
  end
51
27
 
52
- build_where_chain(opts, rest) do |arel|
53
- case arel
54
- when Arel::Nodes::In, Arel::Nodes::Equality
55
- column = left_column(arel) || column_from_association(arel)
28
+ # Finds Records that contains a nested set elements
29
+ #
30
+ # Array Column Type:
31
+ # User.where.contains(tags: [1, 3])
32
+ # # SELECT user.* FROM user WHERE user.tags @> {1,3}
33
+ #
34
+ # HStore Column Type:
35
+ # User.where.contains(data: { nickname: 'chainer' })
36
+ # # SELECT user.* FROM user WHERE user.data @> 'nickname' => 'chainer'
37
+ #
38
+ # JSONB Column Type:
39
+ # User.where.contains(data: { nickname: 'chainer' })
40
+ # # SELECT user.* FROM user WHERE user.data @> {'nickname': 'chainer'}
41
+ #
42
+ # This can also be used along side joined tables
43
+ #
44
+ # JSONB Column Type Example:
45
+ # Tag.joins(:user).where.contains(user: { data: { nickname: 'chainer' } })
46
+ # # SELECT tags.* FROM tags INNER JOIN user on user.id = tags.user_id WHERE user.data @> { nickname: 'chainer' }
47
+ #
48
+ def contains(opts, *rest)
49
+ if ActiveRecordExtended::AR_VERSION_GTE_6_1
50
+ return substitute_comparisons(opts, rest, Arel::Nodes::Contains, "contains")
51
+ end
56
52
 
57
- if [:hstore, :jsonb].include?(column.type)
58
- Arel::Nodes::ContainsHStore.new(arel.left, arel.right)
59
- elsif column.try(:array)
60
- Arel::Nodes::ContainsArray.new(arel.left, arel.right)
53
+ build_where_chain(opts, rest) do |arel|
54
+ case arel
55
+ when Arel::Nodes::In, Arel::Nodes::Equality
56
+ column = left_column(arel) || column_from_association(arel)
57
+
58
+ if [:hstore, :jsonb].include?(column.type)
59
+ Arel::Nodes::ContainsHStore.new(arel.left, arel.right)
60
+ elsif column.try(:array)
61
+ Arel::Nodes::ContainsArray.new(arel.left, arel.right)
62
+ else
63
+ raise ArgumentError.new("Invalid argument for .where.contains(), got #{arel.class}")
64
+ end
61
65
  else
62
66
  raise ArgumentError.new("Invalid argument for .where.contains(), got #{arel.class}")
63
67
  end
64
- else
65
- raise ArgumentError.new("Invalid argument for .where.contains(), got #{arel.class}")
66
68
  end
67
69
  end
68
- end
69
70
 
70
- private
71
+ private
71
72
 
72
- def matchable_column?(col, arel)
73
- col.name == arel.left.name.to_s || col.name == arel.left.relation.name.to_s
74
- end
73
+ def matchable_column?(col, arel)
74
+ col.name == arel.left.name.to_s || col.name == arel.left.relation.name.to_s
75
+ end
75
76
 
76
- def column_from_association(arel)
77
- assoc = assoc_from_related_table(arel)
78
- assoc.klass.columns.detect { |col| matchable_column?(col, arel) } if assoc
79
- end
77
+ def column_from_association(arel)
78
+ assoc = assoc_from_related_table(arel)
79
+ assoc.klass.columns.detect { |col| matchable_column?(col, arel) } if assoc
80
+ end
80
81
 
81
- def assoc_from_related_table(arel)
82
- @scope.klass.reflect_on_association(arel.left.relation.name.to_sym) ||
83
- @scope.klass.reflect_on_association(arel.left.relation.name.singularize.to_sym)
84
- end
82
+ def assoc_from_related_table(arel)
83
+ @scope.klass.reflect_on_association(arel.left.relation.name.to_sym) ||
84
+ @scope.klass.reflect_on_association(arel.left.relation.name.singularize.to_sym)
85
+ end
85
86
 
86
- def left_column(arel)
87
- @scope.klass.columns_hash[arel.left.name] || @scope.klass.columns_hash[arel.left.relation.name]
88
- end
87
+ def left_column(arel)
88
+ @scope.klass.columns_hash[arel.left.name] || @scope.klass.columns_hash[arel.left.relation.name]
89
+ end
89
90
 
90
- def equality_to_function(function_name, opts, rest)
91
- build_where_chain(opts, rest) do |arel|
92
- case arel
93
- when Arel::Nodes::Equality
94
- Arel::Nodes::Equality.new(arel.right, Arel::Nodes::NamedFunction.new(function_name, [arel.left]))
95
- else
96
- raise ArgumentError.new("Invalid argument for .where.#{function_name.downcase}(), got #{arel.class}")
91
+ def equality_to_function(function_name, opts, rest)
92
+ build_where_chain(opts, rest) do |arel|
93
+ case arel
94
+ when Arel::Nodes::Equality
95
+ Arel::Nodes::Equality.new(arel.right, Arel::Nodes::NamedFunction.new(function_name, [arel.left]))
96
+ else
97
+ raise ArgumentError.new("Invalid argument for .where.#{function_name.downcase}(), got #{arel.class}")
98
+ end
97
99
  end
98
100
  end
99
- end
100
101
 
101
- def substitute_comparisons(opts, rest, arel_node_class, method)
102
- build_where_chain(opts, rest) do |arel|
103
- case arel
104
- when Arel::Nodes::In, Arel::Nodes::Equality
105
- arel_node_class.new(arel.left, arel.right)
106
- else
107
- raise ArgumentError.new("Invalid argument for .where.#{method}(), got #{arel.class}")
102
+ def substitute_comparisons(opts, rest, arel_node_class, method)
103
+ build_where_chain(opts, rest) do |arel|
104
+ case arel
105
+ when Arel::Nodes::In, Arel::Nodes::Equality
106
+ arel_node_class.new(arel.left, arel.right)
107
+ else
108
+ raise ArgumentError.new("Invalid argument for .where.#{method}(), got #{arel.class}")
109
+ end
108
110
  end
109
111
  end
110
- end
111
112
 
112
- def build_where_clause_for(scope, opts, rest)
113
- if ActiveRecordExtended::AR_VERSION_GTE_6_1
114
- scope.send(:build_where_clause, opts, rest)
115
- else
116
- scope.send(:where_clause_factory).build(opts, rest)
113
+ def build_where_clause_for(scope, opts, rest)
114
+ if ActiveRecordExtended::AR_VERSION_GTE_6_1
115
+ scope.send(:build_where_clause, opts, rest)
116
+ else
117
+ scope.send(:where_clause_factory).build(opts, rest)
118
+ end
117
119
  end
118
120
  end
119
121
  end
@@ -122,7 +124,7 @@ end
122
124
  module ActiveRecord
123
125
  module QueryMethods
124
126
  class WhereChain
125
- prepend ActiveRecordExtended::WhereChain
127
+ prepend ActiveRecordExtended::QueryMethods::WhereChain
126
128
 
127
129
  def build_where_chain(opts, rest, &block)
128
130
  where_clause = build_where_clause_for(@scope, opts, rest)
@@ -4,8 +4,8 @@ module ActiveRecordExtended
4
4
  module QueryMethods
5
5
  module Window
6
6
  class DefineWindowChain
7
- include ::ActiveRecordExtended::Utilities::Support
8
- include ::ActiveRecordExtended::Utilities::OrderBy
7
+ include ActiveRecordExtended::Utilities::Support
8
+ include ActiveRecordExtended::Utilities::OrderBy
9
9
 
10
10
  def initialize(scope, window_name)
11
11
  @scope = scope
@@ -24,7 +24,7 @@ module ActiveRecordExtended
24
24
  end
25
25
 
26
26
  class WindowSelectBuilder
27
- include ::ActiveRecordExtended::Utilities::Support
27
+ include ActiveRecordExtended::Utilities::Support
28
28
 
29
29
  def initialize(window_function, args, window_name)
30
30
  @window_function = window_function
@@ -4,12 +4,12 @@ module ActiveRecordExtended
4
4
  module QueryMethods
5
5
  module WithCTE
6
6
  class WithCTE
7
- include ::ActiveRecordExtended::Utilities::Support
7
+ include ActiveRecordExtended::Utilities::Support
8
8
  include Enumerable
9
9
  extend Forwardable
10
10
 
11
11
  def_delegators :@with_values, :empty?, :blank?, :present?
12
- attr_reader :with_values, :with_keys
12
+ attr_reader :with_values, :with_keys, :materialized_keys, :not_materialized_keys
13
13
 
14
14
  # @param [ActiveRecord::Relation] scope
15
15
  def initialize(scope)
@@ -33,6 +33,16 @@ module ActiveRecordExtended
33
33
  pipe_cte_with!(value)
34
34
  end
35
35
 
36
+ # @return [Boolean]
37
+ def materialized_key?(key)
38
+ materialized_keys.include?(key.to_sym)
39
+ end
40
+
41
+ # @return [Boolean]
42
+ def not_materialized_key?(key)
43
+ not_materialized_keys.include?(key.to_sym)
44
+ end
45
+
36
46
  # @param [Hash, WithCTE] value
37
47
  def pipe_cte_with!(value)
38
48
  return if value.nil? || value.empty?
@@ -44,6 +54,10 @@ module ActiveRecordExtended
44
54
  # Ensure we follow FIFO pattern.
45
55
  # If the parent has similar CTE alias keys, we want to favor the parent's expressions over its children's.
46
56
  if expression.is_a?(ActiveRecord::Relation) && expression.with_values?
57
+ # Add child's materialized keys to the parent
58
+ @materialized_keys += expression.cte.materialized_keys
59
+ @not_materialized_keys += expression.cte.not_materialized_keys
60
+
47
61
  pipe_cte_with!(expression.cte)
48
62
  expression.cte.reset!
49
63
  end
@@ -58,6 +72,8 @@ module ActiveRecordExtended
58
72
  def reset!
59
73
  @with_keys = []
60
74
  @with_values = {}
75
+ @materialized_keys = Set.new
76
+ @not_materialized_keys = Set.new
61
77
  end
62
78
  end
63
79
 
@@ -75,6 +91,32 @@ module ActiveRecordExtended
75
91
  scope.cte.pipe_cte_with!(args)
76
92
  end
77
93
  end
94
+
95
+ # @param [Hash, WithCTE] args
96
+ def materialized(args)
97
+ @scope.tap do |scope|
98
+ args.each_pair do |name, _expression|
99
+ sym_name = name.to_sym
100
+ raise ArgumentError.new("CTE already set as not_materialized") if scope.cte.not_materialized_key?(sym_name)
101
+
102
+ scope.cte.materialized_keys << sym_name
103
+ end
104
+ scope.cte.pipe_cte_with!(args)
105
+ end
106
+ end
107
+
108
+ # @param [Hash, WithCTE] args
109
+ def not_materialized(args)
110
+ @scope.tap do |scope|
111
+ args.each_pair do |name, _expression|
112
+ sym_name = name.to_sym
113
+ raise ArgumentError.new("CTE already set as materialized") if scope.cte.materialized_key?(sym_name)
114
+
115
+ scope.cte.not_materialized_keys << sym_name
116
+ end
117
+ scope.cte.pipe_cte_with!(args)
118
+ end
119
+ end
78
120
  end
79
121
 
80
122
  # @return [WithCTE]
@@ -134,6 +176,9 @@ module ActiveRecordExtended
134
176
  cte_statements = cte.map do |name, expression|
135
177
  grouped_expression = cte.generate_grouping(expression)
136
178
  cte_name = cte.to_arel_sql(cte.double_quote(name.to_s))
179
+
180
+ grouped_expression = add_materialized_modifier(grouped_expression, cte, name)
181
+
137
182
  Arel::Nodes::As.new(cte_name, grouped_expression)
138
183
  end
139
184
 
@@ -143,6 +188,18 @@ module ActiveRecordExtended
143
188
  arel.with(cte_statements)
144
189
  end
145
190
  end
191
+
192
+ private
193
+
194
+ def add_materialized_modifier(expression, cte, name)
195
+ if cte.materialized_key?(name)
196
+ Arel::Nodes::SqlLiteral.new("MATERIALIZED #{expression.to_sql}")
197
+ elsif cte.not_materialized_key?(name)
198
+ Arel::Nodes::SqlLiteral.new("NOT MATERIALIZED #{expression.to_sql}")
199
+ else
200
+ expression
201
+ end
202
+ end
146
203
  end
147
204
  end
148
205
  end
@@ -49,7 +49,7 @@ module ActiveRecordExtended
49
49
  obj.each_pair do |o_key, o_value|
50
50
  new_hash["#{tbl_or_col}.#{o_key}"] = o_value
51
51
  end
52
- elsif ::ActiveRecord::QueryMethods::VALID_DIRECTIONS.include?(obj)
52
+ elsif ActiveRecord::QueryMethods::VALID_DIRECTIONS.include?(obj)
53
53
  new_hash[tbl_or_col] = obj
54
54
  elsif obj.nil?
55
55
  new_hash[tbl_or_col.to_s] = :asc
@@ -113,7 +113,7 @@ module ActiveRecordExtended
113
113
  case value.to_s
114
114
  # Ignore keys that contain double quotes or a Arel.star (*)[all columns]
115
115
  # or if a table has already been explicitly declared (ex: users.id)
116
- when "*", /((^".+"$)|(^[[:alpha:]]+\.[[:alnum:]]+))/
116
+ when "*", /((^".+"$)|(^[[:alpha:]]+\.[[:alnum:]]+)|\(.+\))/
117
117
  value
118
118
  else
119
119
  PG::Connection.quote_ident(value.to_s)
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module ActiveRecordExtended
4
- VERSION = "2.2.0"
4
+ VERSION = "3.1.0"
5
5
  end
@@ -1,10 +1,61 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require "active_record_extended/version"
4
- require "active_record_extended/utilities/support"
5
- require "active_record_extended/utilities/order_by"
6
- require "active_record_extended/active_record"
7
- require "active_record_extended/arel"
4
+
5
+ require "active_record"
6
+ require "active_record/relation"
7
+ require "active_record/relation/merger"
8
+ require "active_record/relation/query_methods"
8
9
 
9
10
  module ActiveRecordExtended
11
+ extend ActiveSupport::Autoload
12
+
13
+ AR_VERSION_GTE_6_1 = Gem::Requirement.new(">= 6.1").satisfied_by?(ActiveRecord.gem_version)
14
+
15
+ module Utilities
16
+ extend ActiveSupport::Autoload
17
+
18
+ eager_autoload do
19
+ autoload :OrderBy
20
+ autoload :Support
21
+ end
22
+ end
23
+
24
+ module Patch
25
+ extend ActiveSupport::Autoload
26
+
27
+ eager_autoload do
28
+ autoload :ArrayHandlerPatch
29
+ autoload :RelationPatch
30
+ autoload :WhereClausePatch
31
+ end
32
+ end
33
+
34
+ module QueryMethods
35
+ extend ActiveSupport::Autoload
36
+
37
+ eager_autoload do
38
+ autoload :AnyOf
39
+ autoload :Either
40
+ autoload :FosterSelect
41
+ autoload :Inet
42
+ autoload :Json
43
+ autoload :Unionize
44
+ autoload :WhereChain
45
+ autoload :Window
46
+ autoload :WithCTE
47
+ end
48
+ end
49
+
50
+ def self.eager_load!
51
+ super
52
+ ActiveRecordExtended::Utilities.eager_load!
53
+ ActiveRecordExtended::Patch.eager_load!
54
+ ActiveRecordExtended::QueryMethods.eager_load!
55
+ end
56
+ end
57
+
58
+ ActiveSupport.on_load(:active_record) do
59
+ require "active_record_extended/arel"
60
+ ActiveRecordExtended.eager_load!
10
61
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: active_record_extended
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.2.0
4
+ version: 3.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - George Protacio-Karaszi
@@ -10,7 +10,7 @@ authors:
10
10
  autorequire:
11
11
  bindir: bin
12
12
  cert_chain: []
13
- date: 2022-07-28 00:00:00.000000000 Z
13
+ date: 2022-12-01 00:00:00.000000000 Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: activerecord
@@ -32,20 +32,6 @@ dependencies:
32
32
  - - "<"
33
33
  - !ruby/object:Gem::Version
34
34
  version: 7.1.0
35
- - !ruby/object:Gem::Dependency
36
- name: ar_outer_joins
37
- requirement: !ruby/object:Gem::Requirement
38
- requirements:
39
- - - "~>"
40
- - !ruby/object:Gem::Version
41
- version: '0.2'
42
- type: :runtime
43
- prerelease: false
44
- version_requirements: !ruby/object:Gem::Requirement
45
- requirements:
46
- - - "~>"
47
- - !ruby/object:Gem::Version
48
- version: '0.2'
49
35
  - !ruby/object:Gem::Dependency
50
36
  name: pg
51
37
  requirement: !ruby/object:Gem::Requirement
@@ -66,7 +52,7 @@ dependencies:
66
52
  requirements:
67
53
  - - ">="
68
54
  - !ruby/object:Gem::Version
69
- version: '1.16'
55
+ version: '2.2'
70
56
  - - "<"
71
57
  - !ruby/object:Gem::Version
72
58
  version: '3.0'
@@ -76,7 +62,7 @@ dependencies:
76
62
  requirements:
77
63
  - - ">="
78
64
  - !ruby/object:Gem::Version
79
- version: '1.16'
65
+ version: '2.2'
80
66
  - - "<"
81
67
  - !ruby/object:Gem::Version
82
68
  version: '3.0'
@@ -86,14 +72,14 @@ dependencies:
86
72
  requirements:
87
73
  - - "~>"
88
74
  - !ruby/object:Gem::Version
89
- version: '1.6'
75
+ version: '2.0'
90
76
  type: :development
91
77
  prerelease: false
92
78
  version_requirements: !ruby/object:Gem::Requirement
93
79
  requirements:
94
80
  - - "~>"
95
81
  - !ruby/object:Gem::Version
96
- version: '1.6'
82
+ version: '2.0'
97
83
  - !ruby/object:Gem::Dependency
98
84
  name: rake
99
85
  requirement: !ruby/object:Gem::Requirement
@@ -147,21 +133,20 @@ extra_rdoc_files: []
147
133
  files:
148
134
  - README.md
149
135
  - lib/active_record_extended.rb
150
- - lib/active_record_extended/active_record.rb
151
- - lib/active_record_extended/active_record/relation_patch.rb
152
136
  - lib/active_record_extended/arel.rb
153
137
  - lib/active_record_extended/arel/aggregate_function_name.rb
154
138
  - lib/active_record_extended/arel/nodes.rb
155
139
  - lib/active_record_extended/arel/predications.rb
156
- - lib/active_record_extended/arel/sql_literal.rb
140
+ - lib/active_record_extended/arel/sql_literal_patch.rb
157
141
  - lib/active_record_extended/arel/visitors/postgresql_decorator.rb
158
- - lib/active_record_extended/patch/5_2/where_clause.rb
159
- - lib/active_record_extended/predicate_builder/array_handler_decorator.rb
142
+ - lib/active_record_extended/patch/array_handler_patch.rb
143
+ - lib/active_record_extended/patch/relation_patch.rb
144
+ - lib/active_record_extended/patch/where_clause_patch.rb
160
145
  - lib/active_record_extended/query_methods/any_of.rb
161
146
  - lib/active_record_extended/query_methods/either.rb
147
+ - lib/active_record_extended/query_methods/foster_select.rb
162
148
  - lib/active_record_extended/query_methods/inet.rb
163
149
  - lib/active_record_extended/query_methods/json.rb
164
- - lib/active_record_extended/query_methods/select.rb
165
150
  - lib/active_record_extended/query_methods/unionize.rb
166
151
  - lib/active_record_extended/query_methods/where_chain.rb
167
152
  - lib/active_record_extended/query_methods/window.rb
@@ -189,7 +174,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
189
174
  - !ruby/object:Gem::Version
190
175
  version: '0'
191
176
  requirements: []
192
- rubygems_version: 3.2.15
177
+ rubygems_version: 3.3.19
193
178
  signing_key:
194
179
  specification_version: 4
195
180
  summary: Adds extended functionality to Activerecord Postgres implementation
@@ -1,62 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require "active_record_extended/query_methods/window"
4
- require "active_record_extended/query_methods/unionize"
5
- require "active_record_extended/query_methods/json"
6
-
7
- module ActiveRecordExtended
8
- module RelationPatch
9
- module QueryDelegation
10
- delegate :with, :define_window, :select_window, :foster_select, to: :all
11
- delegate(*::ActiveRecordExtended::QueryMethods::Unionize::UNIONIZE_METHODS, to: :all)
12
- delegate(*::ActiveRecordExtended::QueryMethods::Json::JSON_QUERY_METHODS, to: :all)
13
- end
14
-
15
- module Merger
16
- def merge
17
- merge_ctes!
18
- merge_union!
19
- merge_windows!
20
- super
21
- end
22
-
23
- def merge_union!
24
- return if other.unionize_storage.empty?
25
-
26
- relation.union_values += other.union_values
27
- relation.union_operations += other.union_operations
28
- relation.union_ordering_values += other.union_ordering_values
29
- end
30
-
31
- def merge_windows!
32
- return unless other.window_values?
33
-
34
- relation.window_values |= other.window_values
35
- end
36
-
37
- def merge_ctes!
38
- return unless other.with_values?
39
-
40
- if other.recursive_value? && !relation.recursive_value?
41
- relation.with!(:chain).recursive(other.cte)
42
- else
43
- relation.with!(other.cte)
44
- end
45
- end
46
- end
47
-
48
- module ArelBuildPatch
49
- def build_arel(*aliases)
50
- super.tap do |arel|
51
- build_windows(arel) if window_values?
52
- build_unions(arel) if union_values?
53
- build_with(arel) if with_values?
54
- end
55
- end
56
- end
57
- end
58
- end
59
-
60
- ActiveRecord::Relation.prepend(ActiveRecordExtended::RelationPatch::ArelBuildPatch)
61
- ActiveRecord::Relation::Merger.prepend(ActiveRecordExtended::RelationPatch::Merger)
62
- ActiveRecord::Querying.prepend(ActiveRecordExtended::RelationPatch::QueryDelegation)
@@ -1,25 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require "active_record"
4
- require "active_record/relation"
5
- require "active_record/relation/merger"
6
- require "active_record/relation/query_methods"
7
-
8
- module ActiveRecordExtended
9
- # TODO: Deprecate <= AR 6.0 methods & routines
10
- AR_VERSION_GTE_6_1 = Gem::Requirement.new(">= 6.1").satisfied_by?(ActiveRecord.gem_version)
11
- end
12
-
13
- require "active_record_extended/predicate_builder/array_handler_decorator"
14
-
15
- require "active_record_extended/active_record/relation_patch"
16
-
17
- require "active_record_extended/query_methods/where_chain"
18
- require "active_record_extended/query_methods/with_cte"
19
- require "active_record_extended/query_methods/unionize"
20
- require "active_record_extended/query_methods/any_of"
21
- require "active_record_extended/query_methods/either"
22
- require "active_record_extended/query_methods/inet"
23
- require "active_record_extended/query_methods/json"
24
- require "active_record_extended/query_methods/select"
25
- require "active_record_extended/patch/5_2/where_clause"
@@ -1,11 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module ActiveRecordExtended
4
- module WhereClause
5
- def modified_predicates(&block)
6
- ::ActiveRecord::Relation::WhereClause.new(predicates.map(&block))
7
- end
8
- end
9
- end
10
-
11
- ActiveRecord::Relation::WhereClause.prepend(ActiveRecordExtended::WhereClause)