active_record_extended 2.2.0 → 3.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -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)