activerecord-like 7.0.0 → 7.0.1

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