activerecord-like 7.0.0 → 7.0.1

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: e147475c1e6b4b462af02ab761e093c7ec9badb99037db674d447e8e6a95ce30
4
- data.tar.gz: c4788468aafee3e28d1d0b7054ff3764f1bd792c114aeaf6cb7099822b59b8a1
3
+ metadata.gz: '008bc02548b55ab1abdfb2b5309a6b3550d9d53035c537d84fc7ad6898fb9db2'
4
+ data.tar.gz: 751e85650c858261f054dad65480b671bc6922eba3a2d63e0919f45f28eef82b
5
5
  SHA512:
6
- metadata.gz: 00a8bd5af414f203038d61ff3363a99d5179843ba974f307e2dc3154a39f2a7a8ddc67711e4851f60aff14b4c4bf013e8ad6ed58880b9ba2f454daf8d8f30264
7
- data.tar.gz: 06adf3e3a2b855bff6d70a2b5d82902f45b435a42bf031abe0498664c55dc05f4e232d53abb32d219ba8b5b1a216385756891cff229748c886734b13f8073c02
6
+ metadata.gz: 4b08f0b31952192ad43da9e43fd59d7fe2902c391f1676ba44e4bf10c5d34b71e20c2083d7086f7c5df2ce6c137deb9102b432871cf1efc350b52e5ccea51813
7
+ data.tar.gz: 6acff383cca259d967df98c9e3db82d42ccb5151bd3509a2262bd80b6a53e170447a81ffb8ff72f87b662ec1a120f9661cc27199664e2a40a25f5c9ab9c46101
@@ -0,0 +1,66 @@
1
+ name: Coverage
2
+
3
+ on:
4
+ pull_request:
5
+ branches:
6
+ - development
7
+ paths-ignore:
8
+ - 'README.md'
9
+ - 'CHANGELOG.md'
10
+ push:
11
+ branches:
12
+ - development
13
+ paths-ignore:
14
+ - 'README.md'
15
+ - 'CHANGELOG.md'
16
+
17
+ jobs:
18
+ coverage:
19
+ name: Coverage
20
+ # Homemade support for [ci skip] no longer needed
21
+ # https://github.blog/changelog/2021-02-08-github-actions-skip-pull-request-and-push-workflows-with-skip-ci/
22
+ # if: "contains(github.event.commits[0].message, '[ci skip]') == false"
23
+ strategy:
24
+ fail-fast: false
25
+ matrix:
26
+ ruby:
27
+ - "3.3"
28
+ gemfile:
29
+ - gemfiles/rails_7_0.gemfile
30
+ - gemfiles/rails_7_1.gemfile
31
+ - gemfiles/rails_7_2.gemfile
32
+ - gemfiles/rails_8_0.gemfile
33
+ env:
34
+ BUNDLE_GEMFILE: ${{ matrix.gemfile }}
35
+ COVERALLS: true
36
+ runs-on: ubuntu-latest
37
+ steps:
38
+ - name: Checkout
39
+ uses: actions/checkout@v4
40
+
41
+ - name: Setup Ruby
42
+ uses: ruby/setup-ruby@v1
43
+ with:
44
+ ruby-version: ${{ matrix.ruby }}
45
+ bundler-cache: true
46
+
47
+ - name: Collect coverage info
48
+ run: bundle exec rake test
49
+
50
+ - name: Coveralls Parallel
51
+ uses: coverallsapp/github-action@master
52
+ continue-on-error: true
53
+ with:
54
+ github-token: ${{ secrets.GITHUB_TOKEN }}
55
+ flag-name: run-${{ matrix.ruby }}-${{ matrix.gemfile }}
56
+ parallel: true
57
+
58
+ finish:
59
+ needs: coverage
60
+ runs-on: ubuntu-latest
61
+ steps:
62
+ - name: Send to Coveralls
63
+ uses: coverallsapp/github-action@master
64
+ with:
65
+ github-token: ${{ secrets.GITHUB_TOKEN }}
66
+ parallel-finished: true
@@ -0,0 +1,56 @@
1
+ name: Tests
2
+
3
+ on:
4
+ pull_request:
5
+ branches:
6
+ - development
7
+ paths-ignore:
8
+ - 'README.md'
9
+ push:
10
+ branches:
11
+ - development
12
+ paths-ignore:
13
+ - 'README.md'
14
+
15
+ jobs:
16
+ unit_tests:
17
+ name: Unit Tests
18
+ # Homemade support for [ci skip] no longer needed
19
+ # https://github.blog/changelog/2021-02-08-github-actions-skip-pull-request-and-push-workflows-with-skip-ci/
20
+ # if: "contains(github.event.commits[0].message, '[ci skip]') == false"
21
+ strategy:
22
+ fail-fast: false
23
+ matrix:
24
+ ruby:
25
+ - "3.1"
26
+ - "3.2"
27
+ - "3.3"
28
+ gemfile:
29
+ - gemfiles/rails_7_0.gemfile
30
+ - gemfiles/rails_7_1.gemfile
31
+ - gemfiles/rails_7_2.gemfile
32
+ - gemfiles/rails_8_0.gemfile
33
+ allow_failures:
34
+ - false
35
+ exclude:
36
+ - ruby: "3.1"
37
+ gemfile: gemfiles/rails_8_0.gemfile
38
+ include:
39
+ - ruby: ruby-head
40
+ gemfile: gemfiles/rails_8_0.gemfile
41
+ allow_failures: true
42
+ env:
43
+ BUNDLE_GEMFILE: "${{ matrix.gemfile }}"
44
+ ALLOW_FAILURES: "${{ matrix.allow_failures }}"
45
+ runs-on: ubuntu-latest
46
+ continue-on-error: ${{ endsWith(matrix.ruby, 'head') || matrix.ruby == 'debug' }}
47
+ steps:
48
+ - name: Checkout
49
+ uses: actions/checkout@v4
50
+ - name: Setup Ruby
51
+ uses: ruby/setup-ruby@v1
52
+ with:
53
+ ruby-version: ${{ matrix.ruby }}
54
+ bundler-cache: true
55
+ - name: Test
56
+ run: bundle exec rake test || $ALLOW_FAILURES
data/Appraisals CHANGED
@@ -1,5 +1,8 @@
1
- ("7.0".."7.0").each do |version|
1
+ [("7.0".."7.2"), ("8.0".."8.0")].flat_map(&:to_a).each do |version|
2
2
  appraise "rails_#{version.tr('.', '_')}" do
3
3
  gem "activerecord", "~> #{version}.0"
4
+ if version < "7.2"
5
+ gem "sqlite3", "~> 1.3"
6
+ end
4
7
  end
5
8
  end
data/CHANGELOG.md ADDED
@@ -0,0 +1,36 @@
1
+ # Change Log
2
+ All notable changes to this project will be documented in this file.
3
+ This project adheres to [Semantic Versioning](http://semver.org/).
4
+
5
+
6
+ ## [Unreleased]
7
+
8
+ ### Added
9
+
10
+ - Nothing
11
+
12
+ ### Changed
13
+
14
+ - Nothing
15
+
16
+ ### Fixed
17
+
18
+ - Nothing
19
+
20
+
21
+ ## [7.0.1] - 2024-12-17
22
+
23
+ ### Added
24
+
25
+ - Support Rails 8.x
26
+
27
+
28
+ ## 7.0.0 - 2022-01-20
29
+
30
+ ### Added
31
+
32
+ - Support Rails 7.x
33
+
34
+
35
+ [Unreleased]: https://github.com/PikachuEXE/where_lower/compare/v7.0.1...HEAD
36
+ [7.0.1]: https://github.com/PikachuEXE/where_lower/compare/v7.0.0...v7.0.1
data/README.md CHANGED
@@ -1,16 +1,23 @@
1
1
  # ActiveRecord::Like
2
2
 
3
- [![Build Status](https://travis-ci.org/ReneB/activerecord-like.png?branch=master)](https://travis-ci.org/ReneB/activerecord-like)
4
- [![Code Climate](https://codeclimate.com/github/ReneB/activerecord-like.png)](https://codeclimate.com/github/ReneB/activerecord-like)
5
- [![Dependency Status](https://gemnasium.com/ReneB/activerecord-like.png)](https://gemnasium.com/ReneB/activerecord-like)
6
- [![Gem Version](https://badge.fury.io/rb/activerecord-like.png)](http://badge.fury.io/rb/activerecord-like)
3
+ [![GitHub Build Status](https://img.shields.io/github/actions/workflow/status/PikachuEXE/activerecord-like/tests.yaml?branch=development&style=flat-square)](https://github.com/PikachuEXE/activerecord-like/actions/workflows/tests.yaml)
7
4
 
8
- [activerecord-like on Github](https://github.com/ReneB/activerecord-like)
5
+ [![Gem Version](http://img.shields.io/gem/v/activerecord-like.svg?style=flat-square)](http://badge.fury.io/rb/activerecord-like)
6
+ [![License](https://img.shields.io/github/license/PikachuEXE/activerecord-like.svg?style=flat-square)](http://badge.fury.io/rb/activerecord-like)
7
+
8
+ [![Coverage Status](http://img.shields.io/coveralls/PikachuEXE/activerecord-like.svg?style=flat-square)](https://coveralls.io/r/PikachuEXE/activerecord-like)
9
+ [![Code Climate](https://img.shields.io/codeclimate/maintainability/PikachuEXE/activerecord-like.svg?style=flat-square)](https://codeclimate.com/github/PikachuEXE/activerecord-like)
10
+
11
+ [activerecord-like on Github](https://github.com/PikachuEXE/activerecord-like)
9
12
 
10
13
  An Active Record Plugin that allows chaining a more DSL-style 'like' or 'not-like' query to an ActiveRecord::Base#where. Requires Rails 5 or higher.
11
14
 
12
- This plugin has been salvaged from the stellar work done by @amatsuda and @claudiob, updated to ActiveRecord 5 by @PikachuEXE and 5.2 by @robotdana and then to ActiveRecord 6.1 by @nrw505. Most of the code was previously in Active Record master, but was subsequently removed due to, amongst other, scope creep (see discussion [here](https://github.com/rails/rails/commit/8d02afeaee8993bd0fde69687fdd9bf30921e805)).
13
- Array parameter handling was added by @rzane - thanks!
15
+ ## History and credits
16
+
17
+ This plugin was originally salvaged from the stellar work done by @amatsuda and @claudiob.
18
+ * Most of the code was previously in Active Record master, but was subsequently removed due to, amongst other, scope creep (see discussion [here](https://github.com/rails/rails/commit/8d02afeaee8993bd0fde69687fdd9bf30921e805)).
19
+ * It was updated to ActiveRecord 5 by @PikachuEXE, then to ActiveRecord 5.2 by @robotdana and to ActiveRecord 6.1 by @nrw505.
20
+ * Array parameter handling was added by @rzane - thanks!
14
21
 
15
22
  ## Installation
16
23
 
@@ -1,21 +1,27 @@
1
1
  # -*- encoding: utf-8 -*-
2
2
  require File.expand_path('../lib/active_record/like/version', __FILE__)
3
3
 
4
+ main_author_name = "PikachuEXE"
5
+ gem_name = "activerecord-like"
6
+
4
7
  Gem::Specification.new do |gem|
5
- gem.name = "activerecord-like"
8
+ gem.name = gem_name
6
9
  gem.version = ActiveRecord::Like::VERSION
7
- gem.authors = ["René van den Berg"]
8
- gem.email = ["rene.vandenberg@ogd.nl"]
10
+ gem.authors = [
11
+ "René van den Berg",
12
+ main_author_name,
13
+ ]
14
+ gem.email = %w[rene.vandenberg@ogd.nl git@pikachuexe.net]
9
15
  gem.description = %q{An ActiveRecord plugin providing a higher-level abstraction for SQL 'LIKE' queries}
10
16
  gem.summary = %q{ActiveRecord::Like provides ActiveRecord::Base with where.like(attribute: string)-style extensions. This functionality was, at one point, included in Rails-master, but subsequently removed. Since the feature seemed to be in some demand, I thought I'd try my hand at building an ActiveRecord plugin}
11
- gem.homepage = "http://github.com/ReneB/activerecord-like"
17
+ gem.homepage = "http://github.com/#{main_author_name}/#{gem_name}"
12
18
 
13
19
  gem.files = `git ls-files`.split($/)
14
20
  gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
15
21
  gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
16
22
  gem.require_paths = ["lib"]
17
23
 
18
- gem.add_dependency "activerecord", "~> 7.0", ">= 7.0.0"
24
+ gem.add_dependency "activerecord", ">= 7.0.0", "< 9.0"
19
25
 
20
26
  # Required for Travis build to pass
21
27
  gem.add_development_dependency "pg"
@@ -27,4 +33,9 @@ Gem::Specification.new do |gem|
27
33
  gem.add_development_dependency "minitest", ">= 3"
28
34
 
29
35
  gem.add_development_dependency "appraisal", "~> 2.0"
36
+
37
+ gem.add_development_dependency "simplecov", ">= 0.22"
38
+ gem.add_development_dependency "simplecov-lcov", ">= 0.8"
39
+
40
+ gem.add_development_dependency "gem-release", ">= 2.0"
30
41
  end
@@ -3,5 +3,6 @@
3
3
  source "https://rubygems.org"
4
4
 
5
5
  gem "activerecord", "~> 7.0.0"
6
+ gem "sqlite3", "~> 1.3"
6
7
 
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.1.0"
6
+ gem "sqlite3", "~> 1.3"
7
+
8
+ gemspec path: "../"
@@ -0,0 +1,7 @@
1
+ # This file was generated by Appraisal
2
+
3
+ source "https://rubygems.org"
4
+
5
+ gem "activerecord", "~> 7.2.0"
6
+
7
+ gemspec path: "../"
@@ -0,0 +1,7 @@
1
+ # This file was generated by Appraisal
2
+
3
+ source "https://rubygems.org"
4
+
5
+ gem "activerecord", "~> 8.0.0"
6
+
7
+ gemspec path: "../"
@@ -0,0 +1,227 @@
1
+ module ActiveRecord
2
+ module Like
3
+ module ScopeSpawners
4
+ module Shared
5
+ module Rails7AndBelowSpawner
6
+ private
7
+
8
+ def chain_node(node_type, &block)
9
+ @scope.tap do |s|
10
+ # Assuming `opts` to be `Hash`
11
+ opts.each_pair do |key, value|
12
+ # 1. Build a where clause to generate "predicates" & "binds"
13
+ # 2. Convert "predicates" into the one that matches `node_type` (like/not like)
14
+ # 3. Re-use binding values to create new where clause
15
+ equal_where_clause = if s.respond_to?(:where_clause_factory, true)
16
+ # ActiveRecord 5.0 to 6.0
17
+ s.send(:where_clause_factory).build({key => value}, rest)
18
+ else
19
+ # ActiveRecord 6.1, maybe higher
20
+ s.send(:build_where_clause, {key => value}, rest)
21
+ end
22
+ equal_where_clause_predicate = equal_where_clause.send(:predicates).first
23
+
24
+ new_predicate = if equal_where_clause_predicate.right.is_a?(Array)
25
+ nodes = equal_where_clause_predicate.right.map do |expr|
26
+ node_type.new(equal_where_clause_predicate.left, expr)
27
+ end
28
+ Arel::Nodes::Grouping.new block.call(nodes)
29
+ else
30
+ node_type.new(equal_where_clause_predicate.left, equal_where_clause_predicate.right)
31
+ end
32
+
33
+ # Passing `Arel::Nodes::Node` into `where_clause_factory`
34
+ # Will lose the binding values since 5.1
35
+ # due to this PR
36
+ # https://github.com/rails/rails/pull/26073
37
+ new_where_clause = if equal_where_clause.respond_to?(:binds)
38
+ Relation::WhereClause.new([new_predicate], equal_where_clause.binds)
39
+ else
40
+ Relation::WhereClause.new([new_predicate])
41
+ end
42
+
43
+ s.where_clause += new_where_clause
44
+ end
45
+ end
46
+ end
47
+ end
48
+ end
49
+ private_constant :Shared
50
+
51
+ module LikeScopeSpawners
52
+ # Spawn different scopes based on value
53
+ # Data conversion and query string generation are handled by different spanwer classes
54
+ #
55
+ # @return [ActiveRecord::Relation] Relation or collection proxy or some AR classs
56
+ def self.spawn(*args)
57
+ RAILS_VERSION_TO_SPAWNER_CLASS_MAPPINGS.fetch(ActiveRecord.version.to_s[0..2]).
58
+ spawn(*args)
59
+ end
60
+
61
+
62
+ # :nodoc:
63
+ class AbstractSpawner
64
+ # :nodoc:
65
+ attr_reader :scope, :opts, :rest
66
+
67
+ # Spawn different scopes based on value
68
+ # Just delegates to new though
69
+ #
70
+ # @param args [Array] arguments that are passed to #initialize
71
+ #
72
+ # @see #initialize
73
+ def self.spawn(*args)
74
+ new(*args).spawn
75
+ end
76
+
77
+ # Assign ivar only
78
+ # Actual operation is in #spawn
79
+ #
80
+ # @param scope [ActiveRecord::Relation]
81
+ # Relation or collection proxy or some AR classes
82
+ # @param opts [Hash]
83
+ # Column value pairs
84
+ # @param rest [Array]
85
+ # Rest of arguments
86
+ #
87
+ # @see #spawn
88
+ def initialize(scope, opts, *rest)
89
+ @scope = scope
90
+ @opts = opts
91
+ @rest = rest
92
+ end
93
+
94
+ # Spawn different scopes based on value
95
+ # Data conversion and query string generation are handled by different spanwer classes
96
+ #
97
+ # @return [ActiveRecord::Relation] Relation or collection proxy or some AR classs
98
+ def spawn
99
+ raise NotImplementedError
100
+ end
101
+ end
102
+
103
+ # :nodoc:
104
+ class Rails71AndBelowSpawner < AbstractSpawner
105
+ include Shared::Rails7AndBelowSpawner
106
+
107
+ # :nodoc:
108
+ def spawn
109
+ opts.each do |k,v|
110
+ if v.is_a?(Array) && v.empty?
111
+ opts[k] = ''
112
+ end
113
+ end
114
+
115
+ chain_node(Arel::Nodes::Matches) do |nodes|
116
+ nodes.inject { |memo, node| Arel::Nodes::Or.new(memo, node) }
117
+ end
118
+ end
119
+ end
120
+
121
+ # :nodoc:
122
+ class Rails72Spawner < AbstractSpawner
123
+ include Shared::Rails7AndBelowSpawner
124
+
125
+ # :nodoc:
126
+ def spawn
127
+ opts.each do |k,v|
128
+ if v.is_a?(Array) && v.empty?
129
+ opts[k] = ''
130
+ end
131
+ end
132
+
133
+ chain_node(Arel::Nodes::Matches) do |nodes|
134
+ Arel::Nodes::Or.new(nodes)
135
+ end
136
+ end
137
+ end
138
+
139
+ RAILS_VERSION_TO_SPAWNER_CLASS_MAPPINGS = {
140
+ "7.0" => Rails71AndBelowSpawner,
141
+ "7.1" => Rails71AndBelowSpawner,
142
+ "7.2" => Rails72Spawner,
143
+ "8.0" => Rails72Spawner,
144
+ "8.1" => Rails72Spawner,
145
+ "8.2" => Rails72Spawner,
146
+ }.freeze
147
+ private_constant :RAILS_VERSION_TO_SPAWNER_CLASS_MAPPINGS
148
+ end
149
+
150
+ module NotLikeScopeSpawners
151
+ # Spawn different scopes based on value
152
+ # Data conversion and query string generation are handled by different spanwer classes
153
+ #
154
+ # @return [ActiveRecord::Relation] Relation or collection proxy or some AR classs
155
+ def self.spawn(*args)
156
+ RAILS_VERSION_TO_SPAWNER_CLASS_MAPPINGS.fetch(ActiveRecord.version.to_s[0..2]).
157
+ spawn(*args)
158
+ end
159
+
160
+ # :nodoc:
161
+ class AbstractSpawner
162
+ # :nodoc:
163
+ attr_reader :scope, :opts, :rest
164
+
165
+ # Spawn different scopes based on value
166
+ # Just delegates to new though
167
+ #
168
+ # @param args [Array] arguments that are passed to #initialize
169
+ #
170
+ # @see #initialize
171
+ def self.spawn(*args)
172
+ new(*args).spawn
173
+ end
174
+
175
+ # Assign ivar only
176
+ # Actual operation is in #spawn
177
+ #
178
+ # @param scope [ActiveRecord::Relation]
179
+ # Relation or collection proxy or some AR classes
180
+ # @param opts [Hash]
181
+ # Column value pairs
182
+ # @param rest [Array]
183
+ # Rest of arguments
184
+ #
185
+ # @see #spawn
186
+ def initialize(scope, opts, *rest)
187
+ @scope = scope
188
+ @opts = opts
189
+ @rest = rest
190
+ end
191
+
192
+ # Spawn different scopes based on value
193
+ # Data conversion and query string generation are handled by different spanwer classes
194
+ #
195
+ # @return [ActiveRecord::Relation] Relation or collection proxy or some AR classs
196
+ def spawn
197
+ raise NotImplementedError
198
+ end
199
+ end
200
+
201
+ # :nodoc:
202
+ class Rails71AndBelowSpawner < AbstractSpawner
203
+ include Shared::Rails7AndBelowSpawner
204
+
205
+ # :nodoc:
206
+ def spawn
207
+ @opts = opts.reject { |_, v| v.is_a?(Array) && v.empty? }
208
+ chain_node(Arel::Nodes::DoesNotMatch) do |nodes|
209
+ Arel::Nodes::And.new(nodes)
210
+ end
211
+ end
212
+ end
213
+
214
+ RAILS_VERSION_TO_SPAWNER_CLASS_MAPPINGS = {
215
+ "7.0" => Rails71AndBelowSpawner,
216
+ "7.1" => Rails71AndBelowSpawner,
217
+ "7.2" => Rails71AndBelowSpawner,
218
+ "8.0" => Rails71AndBelowSpawner,
219
+ "8.1" => Rails71AndBelowSpawner,
220
+ "8.2" => Rails71AndBelowSpawner,
221
+ }.freeze
222
+ private_constant :RAILS_VERSION_TO_SPAWNER_CLASS_MAPPINGS
223
+ end
224
+ end
225
+
226
+ end
227
+ end
@@ -1,5 +1,7 @@
1
- module ActiveRecord
2
- module Like
3
- VERSION = "7.0.0"
4
- end
5
- end
1
+ # frozen_string_literal: true
2
+
3
+ module ActiveRecord
4
+ module Like
5
+ VERSION = "7.0.1"
6
+ end
7
+ end
@@ -1,67 +1,15 @@
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
data/test/helper.rb CHANGED
@@ -1,4 +1,23 @@
1
1
  require 'bundler/setup'
2
+
3
+ if ENV["COVERALLS"]
4
+ require "simplecov"
5
+ require "simplecov-lcov"
6
+
7
+ SimpleCov::Formatter::LcovFormatter.config do |c|
8
+ c.report_with_single_file = true
9
+ c.single_report_path = "coverage/lcov.info"
10
+ end
11
+
12
+ SimpleCov.formatters = SimpleCov::Formatter::MultiFormatter.new(
13
+ [SimpleCov::Formatter::HTMLFormatter, SimpleCov::Formatter::LcovFormatter]
14
+ )
15
+
16
+ SimpleCov.start do
17
+ add_filter "test/"
18
+ end
19
+ end
20
+
2
21
  require 'minitest/autorun'
3
22
  require 'minitest/spec'
4
23
  require 'active_record/like'
@@ -12,7 +12,7 @@ describe ActiveRecord::QueryMethods::WhereChain do
12
12
  end
13
13
 
14
14
  it "finds records with attributes matching the criteria" do
15
- Post.where.like(title: '%there?').map(&:id).must_include 2
15
+ _(Post.where.like(title: '%there?').map(&:id)).must_include 2
16
16
  end
17
17
 
18
18
  it "is case-insensitive" do
@@ -21,30 +21,30 @@ describe ActiveRecord::QueryMethods::WhereChain do
21
21
  lowercase_posts = Post.where.like(title: search_term)
22
22
  uppercase_posts = Post.where.like(title: search_term.upcase)
23
23
 
24
- lowercase_posts.map(&:id).must_equal(uppercase_posts.map(&:id))
24
+ _(lowercase_posts.map(&:id)).must_equal(uppercase_posts.map(&:id))
25
25
  end
26
26
 
27
27
  it "is chainable" do
28
28
  Post.where.like(title: '%there?').order(:title).update_all(title: 'some title')
29
29
 
30
- Post.find(2).title.must_equal('some title')
30
+ _(Post.find(2).title).must_equal('some title')
31
31
  end
32
32
 
33
33
  it "does not find records with attributes not matching the criteria" do
34
- Post.where.like(title: '%this title is not used anywhere%').map(&:id).wont_include 2
34
+ _(Post.where.like(title: '%this title is not used anywhere%').map(&:id)).wont_include 2
35
35
  end
36
36
 
37
37
  describe "array behavior" do
38
38
  it "finds records with attributes matching multiple criteria" do
39
- Post.where.like(title: ['%DSLs%', 'We need some%']).map(&:id).must_equal [1, 2]
39
+ _(Post.where.like(title: ['%DSLs%', 'We need some%']).map(&:id)).must_equal [1, 2]
40
40
  end
41
41
 
42
42
  it "finds records with attributes matching one criterion" do
43
- Post.where.like(title: ['%there?']).map(&:id).must_equal [2]
43
+ _(Post.where.like(title: ['%there?']).map(&:id)).must_equal [2]
44
44
  end
45
45
 
46
46
  it "does not find any records with an empty array" do
47
- Post.where.like(title: []).must_be_empty
47
+ _(Post.where.like(title: [])).must_be_empty
48
48
  end
49
49
  end
50
50
 
@@ -57,15 +57,15 @@ describe ActiveRecord::QueryMethods::WhereChain do
57
57
  # Interpolating input strings into LIKE queries is an all-too-common
58
58
  # mistake that is prevented by the syntax this plugin provides
59
59
  it "is possible to inject SQL into literal query strings" do
60
- Post.where("title LIKE '%#{@user_input}%'").count.must_equal(2)
60
+ _(Post.where("title LIKE '%#{@user_input}%'").count).must_equal(2)
61
61
  end
62
62
 
63
63
  it "prevents SQL injection" do
64
- Post.where.like(title: @user_input).count.must_equal(0)
64
+ _(Post.where.like(title: @user_input).count).must_equal(0)
65
65
  end
66
66
 
67
67
  it "prevents SQL injection when provided an array" do
68
- Post.where.like(title: [@user_input]).count.must_equal(0)
68
+ _(Post.where.like(title: [@user_input]).count).must_equal(0)
69
69
  end
70
70
  end
71
71
  end
@@ -12,7 +12,7 @@ describe ActiveRecord::QueryMethods::WhereChain do
12
12
  end
13
13
 
14
14
  it "finds records with attributes not matching the criteria" do
15
- Post.where.not_like(title: '%there?').map(&:id).wont_include 2
15
+ _(Post.where.not_like(title: '%there?').map(&:id)).wont_include 2
16
16
  end
17
17
 
18
18
  it "is case-insensitive" do
@@ -21,30 +21,30 @@ describe ActiveRecord::QueryMethods::WhereChain do
21
21
  lowercase_posts = Post.where.not_like(title: search_term)
22
22
  uppercase_posts = Post.where.not_like(title: search_term.upcase)
23
23
 
24
- lowercase_posts.map(&:id).must_equal(uppercase_posts.map(&:id))
24
+ _(lowercase_posts.map(&:id)).must_equal(uppercase_posts.map(&:id))
25
25
  end
26
26
 
27
27
  it "is chainable" do
28
28
  Post.where.not_like(title: '%there?').order(:title).update_all(title: 'some title')
29
29
 
30
- Post.find(1).title.must_equal('some title')
30
+ _(Post.find(1).title).must_equal('some title')
31
31
  end
32
32
 
33
33
  it "does not find records with attributes matching the criteria" do
34
- Post.where.not_like(title: '%this title is not used anywhere%').map(&:id).must_include 2
34
+ _(Post.where.not_like(title: '%this title is not used anywhere%').map(&:id)).must_include 2
35
35
  end
36
36
 
37
37
  describe "array behavior" do
38
38
  it "finds records with attributes not matching multiple criteria" do
39
- Post.where.not_like(title: ['%DSLs%', 'We need some%']).map(&:id).must_be_empty
39
+ _(Post.where.not_like(title: ['%DSLs%', 'We need some%']).map(&:id)).must_be_empty
40
40
  end
41
41
 
42
42
  it "finds records with attributes not matching one criterion" do
43
- Post.where.not_like(title: ['%there?']).map(&:id).must_equal [1]
43
+ _(Post.where.not_like(title: ['%there?']).map(&:id)).must_equal [1]
44
44
  end
45
45
 
46
46
  it "finds all records with an empty array" do
47
- Post.where.not_like(title: []).count.must_equal 2
47
+ _(Post.where.not_like(title: []).count).must_equal 2
48
48
  end
49
49
  end
50
50
 
@@ -57,15 +57,15 @@ describe ActiveRecord::QueryMethods::WhereChain do
57
57
  # Interpolating input strings into LIKE queries is an all-too-common
58
58
  # mistake that is prevented by the syntax this plugin provides
59
59
  it "is possible to inject SQL into literal query strings" do
60
- Post.where("title NOT LIKE '%#{@user_input}%'").count.must_equal(2)
60
+ _(Post.where("title NOT LIKE '%#{@user_input}%'").count).must_equal(2)
61
61
  end
62
62
 
63
63
  it "prevents SQL injection" do
64
- Post.where.not_like(title: @user_input).count.must_equal(2)
64
+ _(Post.where.not_like(title: @user_input).count).must_equal(2)
65
65
  end
66
66
 
67
67
  it "prevents SQL injection when provided an array" do
68
- Post.where.not_like(title: [@user_input]).count.must_equal(2)
68
+ _(Post.where.not_like(title: [@user_input]).count).must_equal(2)
69
69
  end
70
70
  end
71
71
  end
@@ -5,7 +5,7 @@ describe ActiveRecord::QueryMethods::WhereChain do
5
5
  it "creates an Arel Matches node in the relation" do
6
6
  relation = Post.where.like(title: '')
7
7
 
8
- relation.where_clause.send(:predicates).first.must_be_instance_of(Arel::Nodes::Matches)
8
+ _(relation.where_clause.send(:predicates).first).must_be_instance_of(Arel::Nodes::Matches)
9
9
  end
10
10
 
11
11
  describe "the Arel Node" do
@@ -18,19 +18,22 @@ describe ActiveRecord::QueryMethods::WhereChain do
18
18
  end
19
19
 
20
20
  it "has the attribute as the left operand" do
21
- @first_predicate.left.name.must_equal @attribute
21
+ _(@first_predicate.left.name).must_equal @attribute
22
22
  end
23
23
 
24
24
  it "has the value as the right operand" do
25
25
  # Rails 5.0 & 5.1
26
26
  first_bind = if @relation.where_clause.respond_to?(:binds)
27
27
  @relation.where_clause.send(:binds).first
28
+ elsif @first_predicate.right.value.is_a?(String)
29
+ # Rails 7.0+
30
+ @first_predicate.right
28
31
  else
29
32
  # Rails 5.2
30
33
  @first_predicate.right.value
31
34
  end
32
35
 
33
- first_bind.value.must_equal @value
36
+ _(first_bind.value).must_equal @value
34
37
  end
35
38
  end
36
39
  end
@@ -5,7 +5,7 @@ describe ActiveRecord::QueryMethods::WhereChain do
5
5
  it "creates an Arel DoesNotMatch node in the relation" do
6
6
  relation = Post.where.not_like(title: '')
7
7
 
8
- relation.where_clause.send(:predicates).first.must_be_instance_of(Arel::Nodes::DoesNotMatch)
8
+ _(relation.where_clause.send(:predicates).first).must_be_instance_of(Arel::Nodes::DoesNotMatch)
9
9
  end
10
10
 
11
11
  describe "the Arel Node" do
@@ -18,19 +18,22 @@ describe ActiveRecord::QueryMethods::WhereChain do
18
18
  end
19
19
 
20
20
  it "has the attribute as the left operand" do
21
- @first_predicate.left.name.must_equal @attribute
21
+ _(@first_predicate.left.name).must_equal @attribute
22
22
  end
23
23
 
24
24
  it "has the value as the right operand" do
25
25
  # Rails 5.0 & 5.1
26
26
  first_bind = if @relation.where_clause.respond_to?(:binds)
27
27
  @relation.where_clause.send(:binds).first
28
+ elsif @first_predicate.right.value.is_a?(String)
29
+ # Rails 7.0+
30
+ @first_predicate.right
28
31
  else
29
32
  # Rails 5.2
30
33
  @first_predicate.right.value
31
34
  end
32
35
 
33
- first_bind.value.must_equal @value
36
+ _(first_bind.value).must_equal @value
34
37
  end
35
38
  end
36
39
  end
metadata CHANGED
@@ -1,35 +1,36 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: activerecord-like
3
3
  version: !ruby/object:Gem::Version
4
- version: 7.0.0
4
+ version: 7.0.1
5
5
  platform: ruby
6
+ original_platform: ''
6
7
  authors:
7
8
  - René van den Berg
8
- autorequire:
9
+ - PikachuEXE
9
10
  bindir: bin
10
11
  cert_chain: []
11
- date: 2022-10-17 00:00:00.000000000 Z
12
+ date: 2024-12-17 00:00:00.000000000 Z
12
13
  dependencies:
13
14
  - !ruby/object:Gem::Dependency
14
15
  name: activerecord
15
16
  requirement: !ruby/object:Gem::Requirement
16
17
  requirements:
17
- - - "~>"
18
- - !ruby/object:Gem::Version
19
- version: '7.0'
20
18
  - - ">="
21
19
  - !ruby/object:Gem::Version
22
20
  version: 7.0.0
21
+ - - "<"
22
+ - !ruby/object:Gem::Version
23
+ version: '9.0'
23
24
  type: :runtime
24
25
  prerelease: false
25
26
  version_requirements: !ruby/object:Gem::Requirement
26
27
  requirements:
27
- - - "~>"
28
- - !ruby/object:Gem::Version
29
- version: '7.0'
30
28
  - - ">="
31
29
  - !ruby/object:Gem::Version
32
30
  version: 7.0.0
31
+ - - "<"
32
+ - !ruby/object:Gem::Version
33
+ version: '9.0'
33
34
  - !ruby/object:Gem::Dependency
34
35
  name: pg
35
36
  requirement: !ruby/object:Gem::Requirement
@@ -114,24 +115,73 @@ dependencies:
114
115
  - - "~>"
115
116
  - !ruby/object:Gem::Version
116
117
  version: '2.0'
118
+ - !ruby/object:Gem::Dependency
119
+ name: simplecov
120
+ requirement: !ruby/object:Gem::Requirement
121
+ requirements:
122
+ - - ">="
123
+ - !ruby/object:Gem::Version
124
+ version: '0.22'
125
+ type: :development
126
+ prerelease: false
127
+ version_requirements: !ruby/object:Gem::Requirement
128
+ requirements:
129
+ - - ">="
130
+ - !ruby/object:Gem::Version
131
+ version: '0.22'
132
+ - !ruby/object:Gem::Dependency
133
+ name: simplecov-lcov
134
+ requirement: !ruby/object:Gem::Requirement
135
+ requirements:
136
+ - - ">="
137
+ - !ruby/object:Gem::Version
138
+ version: '0.8'
139
+ type: :development
140
+ prerelease: false
141
+ version_requirements: !ruby/object:Gem::Requirement
142
+ requirements:
143
+ - - ">="
144
+ - !ruby/object:Gem::Version
145
+ version: '0.8'
146
+ - !ruby/object:Gem::Dependency
147
+ name: gem-release
148
+ requirement: !ruby/object:Gem::Requirement
149
+ requirements:
150
+ - - ">="
151
+ - !ruby/object:Gem::Version
152
+ version: '2.0'
153
+ type: :development
154
+ prerelease: false
155
+ version_requirements: !ruby/object:Gem::Requirement
156
+ requirements:
157
+ - - ">="
158
+ - !ruby/object:Gem::Version
159
+ version: '2.0'
117
160
  description: An ActiveRecord plugin providing a higher-level abstraction for SQL 'LIKE'
118
161
  queries
119
162
  email:
120
163
  - rene.vandenberg@ogd.nl
164
+ - git@pikachuexe.net
121
165
  executables: []
122
166
  extensions: []
123
167
  extra_rdoc_files: []
124
168
  files:
169
+ - ".github/workflows/coverage.yml"
170
+ - ".github/workflows/tests.yaml"
125
171
  - ".gitignore"
126
- - ".travis.yml"
127
172
  - Appraisals
173
+ - CHANGELOG.md
128
174
  - Gemfile
129
175
  - LICENSE.txt
130
176
  - README.md
131
177
  - Rakefile
132
178
  - activerecord-like.gemspec
133
179
  - gemfiles/rails_7_0.gemfile
180
+ - gemfiles/rails_7_1.gemfile
181
+ - gemfiles/rails_7_2.gemfile
182
+ - gemfiles/rails_8_0.gemfile
134
183
  - lib/active_record/like.rb
184
+ - lib/active_record/like/scope_spawner.rb
135
185
  - lib/active_record/like/version.rb
136
186
  - lib/activerecord-like.rb
137
187
  - test/helper.rb
@@ -139,10 +189,9 @@ files:
139
189
  - test/integration/not_like_test.rb
140
190
  - test/unit/like_test.rb
141
191
  - test/unit/not_like_test.rb
142
- homepage: http://github.com/ReneB/activerecord-like
192
+ homepage: http://github.com/PikachuEXE/activerecord-like
143
193
  licenses: []
144
194
  metadata: {}
145
- post_install_message:
146
195
  rdoc_options: []
147
196
  require_paths:
148
197
  - lib
@@ -157,8 +206,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
157
206
  - !ruby/object:Gem::Version
158
207
  version: '0'
159
208
  requirements: []
160
- rubygems_version: 3.2.3
161
- signing_key:
209
+ rubygems_version: 3.6.0
162
210
  specification_version: 4
163
211
  summary: 'ActiveRecord::Like provides ActiveRecord::Base with where.like(attribute:
164
212
  string)-style extensions. This functionality was, at one point, included in Rails-master,
data/.travis.yml DELETED
@@ -1,22 +0,0 @@
1
- # Send builds to container-based infrastructure
2
- # http://docs.travis-ci.com/user/workers/container-based-infrastructure/
3
- sudo: false
4
- language: ruby
5
- cache: bundler
6
- services:
7
- - postgresql
8
- - mysql
9
- rvm:
10
- - 2.7.5
11
- - 3.0.3
12
- - ruby-head
13
- env:
14
- - DB=pg
15
- - DB=sqlite3
16
- - DB=mysql
17
- gemfile:
18
- - gemfiles/rails_7_0.gemfile
19
- matrix:
20
- fast_finish: true
21
- allow_failures:
22
- - rvm: ruby-head