|
1 | 1 | require "active_record" |
| 2 | +require_relative "like/scope_spawner" |
2 | 3 |
|
3 | 4 | module ActiveRecord |
4 | 5 | module Like |
5 | 6 | module WhereChainExtensions |
6 | 7 | def like(opts, *rest) |
7 | | - opts.each do |k,v| |
8 | | - if v.is_a?(Array) && v.empty? |
9 | | - opts[k] = '' |
10 | | - end |
11 | | - end |
12 | | - |
13 | | - chain_node(Arel::Nodes::Matches, opts, *rest) do |nodes| |
14 | | - nodes.inject { |memo, node| Arel::Nodes::Or.new(memo, node) } |
15 | | - end |
| 8 | + ActiveRecord::Like::ScopeSpawners::LikeScopeSpawners.spawn(@scope, opts, rest) |
16 | 9 | end |
17 | 10 |
|
18 | 11 | def not_like(opts, *rest) |
19 | | - opts = opts.reject { |_, v| v.is_a?(Array) && v.empty? } |
20 | | - chain_node(Arel::Nodes::DoesNotMatch, opts, *rest) do |nodes| |
21 | | - Arel::Nodes::And.new(nodes) |
22 | | - end |
23 | | - end |
24 | | - |
25 | | - private |
26 | | - |
27 | | - def chain_node(node_type, opts, *rest, &block) |
28 | | - @scope.tap do |s| |
29 | | - # Assuming `opts` to be `Hash` |
30 | | - opts.each_pair do |key, value| |
31 | | - # 1. Build a where clause to generate "predicates" & "binds" |
32 | | - # 2. Convert "predicates" into the one that matches `node_type` (like/not like) |
33 | | - # 3. Re-use binding values to create new where clause |
34 | | - equal_where_clause = if s.respond_to?(:where_clause_factory, true) |
35 | | - # ActiveRecord 5.0 to 6.0 |
36 | | - s.send(:where_clause_factory).build({key => value}, rest) |
37 | | - else |
38 | | - # ActiveRecord 6.1, maybe higher |
39 | | - s.send(:build_where_clause, {key => value}, rest) |
40 | | - end |
41 | | - equal_where_clause_predicate = equal_where_clause.send(:predicates).first |
42 | | - |
43 | | - new_predicate = if equal_where_clause_predicate.right.is_a?(Array) |
44 | | - nodes = equal_where_clause_predicate.right.map do |expr| |
45 | | - node_type.new(equal_where_clause_predicate.left, expr) |
46 | | - end |
47 | | - Arel::Nodes::Grouping.new block.call(nodes) |
48 | | - else |
49 | | - node_type.new(equal_where_clause_predicate.left, equal_where_clause_predicate.right) |
50 | | - end |
51 | | - |
52 | | - # Passing `Arel::Nodes::Node` into `where_clause_factory` |
53 | | - # Will lose the binding values since 5.1 |
54 | | - # due to this PR |
55 | | - # https://github.com/rails/rails/pull/26073 |
56 | | - new_where_clause = if equal_where_clause.respond_to?(:binds) |
57 | | - Relation::WhereClause.new([new_predicate], equal_where_clause.binds) |
58 | | - else |
59 | | - Relation::WhereClause.new([new_predicate]) |
60 | | - end |
61 | | - |
62 | | - s.where_clause += new_where_clause |
63 | | - end |
64 | | - end |
| 12 | + ActiveRecord::Like::ScopeSpawners::NotLikeScopeSpawners.spawn(@scope, opts, rest) |
65 | 13 | end |
66 | 14 | end |
67 | 15 | end |
|
0 commit comments