ransack 2.4.0 → 2.4.2
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 +4 -4
- data/.github/FUNDING.yml +3 -0
- data/.github/SECURITY.md +12 -0
- data/.github/workflows/cronjob.yml +105 -0
- data/.github/workflows/rubocop.yml +20 -0
- data/.github/workflows/test.yml +154 -0
- data/.rubocop.yml +44 -0
- data/CHANGELOG.md +8 -3
- data/CONTRIBUTING.md +2 -5
- data/Gemfile +4 -2
- data/README.md +95 -25
- data/bug_report_templates/test-ransack-scope-and-column-same-name.rb +78 -0
- data/bug_report_templates/test-ransacker-arel-present-predicate.rb +71 -0
- data/docs/img/create_release.png +0 -0
- data/docs/release_process.md +20 -0
- data/lib/polyamorous/activerecord_6.2_ruby_2/join_association.rb +1 -0
- data/lib/polyamorous/activerecord_6.2_ruby_2/join_dependency.rb +1 -0
- data/lib/polyamorous/activerecord_6.2_ruby_2/reflection.rb +1 -0
- data/lib/polyamorous/polyamorous.rb +1 -1
- data/lib/ransack.rb +2 -2
- data/lib/ransack/adapters/active_record/base.rb +4 -0
- data/lib/ransack/adapters/active_record/context.rb +10 -3
- data/lib/ransack/adapters/active_record/ransack/constants.rb +1 -1
- data/lib/ransack/configuration.rb +17 -1
- data/lib/ransack/constants.rb +2 -3
- data/lib/ransack/helpers.rb +1 -1
- data/lib/ransack/helpers/form_builder.rb +3 -3
- data/lib/ransack/nodes/attribute.rb +1 -1
- data/lib/ransack/nodes/condition.rb +0 -2
- data/lib/ransack/nodes/sort.rb +1 -1
- data/lib/ransack/nodes/value.rb +1 -1
- data/lib/ransack/search.rb +2 -1
- data/lib/ransack/version.rb +1 -1
- data/ransack.gemspec +4 -3
- data/spec/blueprints/articles.rb +1 -1
- data/spec/blueprints/comments.rb +1 -1
- data/spec/blueprints/notes.rb +1 -1
- data/spec/blueprints/tags.rb +1 -1
- data/spec/console.rb +5 -5
- data/spec/helpers/ransack_helper.rb +1 -1
- data/spec/ransack/adapters/active_record/base_spec.rb +6 -3
- data/spec/ransack/adapters/active_record/context_spec.rb +1 -2
- data/spec/ransack/configuration_spec.rb +10 -0
- data/spec/ransack/helpers/form_helper_spec.rb +16 -16
- data/spec/ransack/nodes/grouping_spec.rb +2 -2
- data/spec/ransack/predicate_spec.rb +1 -1
- data/spec/ransack/search_spec.rb +49 -2
- data/spec/spec_helper.rb +7 -6
- data/spec/support/schema.rb +2 -2
- metadata +16 -4
- data/.travis.yml +0 -47
@@ -0,0 +1,78 @@
|
|
1
|
+
# test-ransack-scope-and-column-same-name.rb
|
2
|
+
|
3
|
+
# This is a stand-alone test case.
|
4
|
+
|
5
|
+
# Run it in your console with: `ruby test-ransack-scope-and-column-same-name.rb`
|
6
|
+
|
7
|
+
# If you change the gem dependencies, run it with:
|
8
|
+
# `rm gemfile* && ruby test-ransack-scope-and-column-same-name.rb`
|
9
|
+
|
10
|
+
unless File.exist?('Gemfile')
|
11
|
+
File.write('Gemfile', <<-GEMFILE)
|
12
|
+
source 'https://rubygems.org'
|
13
|
+
|
14
|
+
# Rails master
|
15
|
+
gem 'rails', github: 'rails/rails', branch: '6-1-stable'
|
16
|
+
|
17
|
+
# Rails last release
|
18
|
+
# gem 'rails'
|
19
|
+
|
20
|
+
gem 'sqlite3'
|
21
|
+
gem 'ransack', github: 'activerecord-hackery/ransack'
|
22
|
+
GEMFILE
|
23
|
+
|
24
|
+
system 'bundle install'
|
25
|
+
end
|
26
|
+
|
27
|
+
require 'bundler'
|
28
|
+
Bundler.setup(:default)
|
29
|
+
|
30
|
+
require 'active_record'
|
31
|
+
require 'minitest/autorun'
|
32
|
+
require 'logger'
|
33
|
+
require 'ransack'
|
34
|
+
|
35
|
+
# This connection will do for database-independent bug reports.
|
36
|
+
ActiveRecord::Base.establish_connection(adapter: 'sqlite3', database: ':memory:')
|
37
|
+
ActiveRecord::Base.logger = Logger.new(STDOUT)
|
38
|
+
|
39
|
+
# Display versions.
|
40
|
+
message = "Running test case with Ruby #{RUBY_VERSION}, Active Record #{
|
41
|
+
::ActiveRecord::VERSION::STRING}, Arel #{Arel::VERSION} and #{
|
42
|
+
::ActiveRecord::Base.connection.adapter_name}"
|
43
|
+
line = '=' * message.length
|
44
|
+
puts line, message, line
|
45
|
+
|
46
|
+
ActiveRecord::Schema.define do
|
47
|
+
create_table :users, force: true do |t|
|
48
|
+
t.boolean :active, null: false, default: true
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
class User < ActiveRecord::Base
|
53
|
+
scope :activated, -> (boolean = true) { where(active: boolean) }
|
54
|
+
|
55
|
+
private
|
56
|
+
|
57
|
+
def self.ransackable_scopes(auth_object = nil)
|
58
|
+
%i(activated)
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
class BugTest < Minitest::Test
|
63
|
+
def test_activated_scope_equals_true
|
64
|
+
sql = User.ransack({ activated: true }).result.to_sql
|
65
|
+
puts sql
|
66
|
+
assert_equal(
|
67
|
+
"SELECT \"users\".* FROM \"users\" WHERE \"users\".\"active\" = 1", sql
|
68
|
+
)
|
69
|
+
end
|
70
|
+
|
71
|
+
def test_activated_scope_equals_false
|
72
|
+
sql = User.ransack({ activated: false }).result.to_sql
|
73
|
+
puts sql
|
74
|
+
assert_equal(
|
75
|
+
"SELECT \"users\".* FROM \"users\"", sql
|
76
|
+
)
|
77
|
+
end
|
78
|
+
end
|
@@ -0,0 +1,71 @@
|
|
1
|
+
# test-ransacker-arel-present-predicate.rb
|
2
|
+
|
3
|
+
# Run it in your console with: `ruby test-ransacker-arel-present-predicate.rb`
|
4
|
+
|
5
|
+
# If you change the gem dependencies, run it with:
|
6
|
+
# `rm gemfile* && ruby test-ransacker-arel-present-predicate.rb`
|
7
|
+
|
8
|
+
unless File.exist?('Gemfile')
|
9
|
+
File.write('Gemfile', <<-GEMFILE)
|
10
|
+
source 'https://rubygems.org'
|
11
|
+
|
12
|
+
# Rails master
|
13
|
+
gem 'rails', github: 'rails/rails', branch: '6-1-stable'
|
14
|
+
|
15
|
+
# Rails last release
|
16
|
+
# gem 'rails'
|
17
|
+
|
18
|
+
gem 'sqlite3'
|
19
|
+
gem 'ransack', github: 'activerecord-hackery/ransack'
|
20
|
+
GEMFILE
|
21
|
+
|
22
|
+
system 'bundle install'
|
23
|
+
end
|
24
|
+
|
25
|
+
require 'bundler'
|
26
|
+
Bundler.setup(:default)
|
27
|
+
|
28
|
+
require 'active_record'
|
29
|
+
require 'minitest/autorun'
|
30
|
+
require 'logger'
|
31
|
+
require 'ransack'
|
32
|
+
|
33
|
+
# This connection will do for database-independent bug reports.
|
34
|
+
ActiveRecord::Base.establish_connection(adapter: 'sqlite3', database: ':memory:')
|
35
|
+
ActiveRecord::Base.logger = Logger.new(STDOUT)
|
36
|
+
|
37
|
+
# Display versions.
|
38
|
+
message = "Running test case with Ruby #{RUBY_VERSION}, Active Record #{
|
39
|
+
::ActiveRecord::VERSION::STRING}, Arel #{Arel::VERSION} and #{
|
40
|
+
::ActiveRecord::Base.connection.adapter_name}"
|
41
|
+
line = '=' * message.length
|
42
|
+
puts line, message, line
|
43
|
+
|
44
|
+
ActiveRecord::Schema.define do
|
45
|
+
create_table :projects, force: true do |t|
|
46
|
+
t.string :name
|
47
|
+
t.string :number
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
class Project < ActiveRecord::Base
|
52
|
+
ransacker :name do
|
53
|
+
Arel.sql('projects.name')
|
54
|
+
end
|
55
|
+
|
56
|
+
ransacker :number do |parent|
|
57
|
+
parent.table[:number]
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
class BugTest < Minitest::Test
|
62
|
+
def test_ransackers
|
63
|
+
sql = Project.ransack({ number_present: 1 }).result.to_sql
|
64
|
+
puts sql
|
65
|
+
assert_equal "SELECT \"projects\".* FROM \"projects\" WHERE (\"projects\".\"number\" IS NOT NULL AND \"projects\".\"number\" != '')", sql
|
66
|
+
|
67
|
+
sql = Project.ransack({ name_present: 1 }).result.to_sql
|
68
|
+
puts sql
|
69
|
+
assert_equal "SELECT \"projects\".* FROM \"projects\" WHERE (projects.name IS NOT NULL AND projects.name != '')", sql
|
70
|
+
end
|
71
|
+
end
|
Binary file
|
@@ -0,0 +1,20 @@
|
|
1
|
+
## Release Process
|
2
|
+
|
3
|
+
*For maintainers of Ransack.*
|
4
|
+
|
5
|
+
To release a new version of Ransack and publish it to RubyGems, take the following steps:
|
6
|
+
|
7
|
+
- Create a new release, marked `Prerelease`.
|
8
|
+
<<<<<<< Updated upstream
|
9
|
+
- Update the versions file to the new release, commit and push to `master`.
|
10
|
+
=======
|
11
|
+
- Update the [version.rb](../lib/ransack/version.rb) file to the new release, commit and push to `master`.
|
12
|
+
>>>>>>> Stashed changes
|
13
|
+
- From the terminal, run the following commands
|
14
|
+
|
15
|
+
```bash
|
16
|
+
rake build
|
17
|
+
rake release
|
18
|
+
```
|
19
|
+
|
20
|
+

|
@@ -0,0 +1 @@
|
|
1
|
+
require 'polyamorous/activerecord_6.1_ruby_2/join_association'
|
@@ -0,0 +1 @@
|
|
1
|
+
require 'polyamorous/activerecord_6.1_ruby_2/join_dependency'
|
@@ -0,0 +1 @@
|
|
1
|
+
require 'polyamorous/activerecord_6.1_ruby_2/reflection'
|
@@ -11,7 +11,7 @@ if defined?(::ActiveRecord)
|
|
11
11
|
require 'polyamorous/join'
|
12
12
|
require 'polyamorous/swapping_reflection_class'
|
13
13
|
|
14
|
-
ar_version = ::ActiveRecord::VERSION::STRING[0,3]
|
14
|
+
ar_version = ::ActiveRecord::VERSION::STRING[0, 3]
|
15
15
|
%w(join_association join_dependency reflection).each do |file|
|
16
16
|
require "polyamorous/activerecord_#{ar_version}_ruby_2/#{file}"
|
17
17
|
end
|
data/lib/ransack.rb
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
require 'active_support/core_ext'
|
2
2
|
require 'ransack/configuration'
|
3
3
|
require 'ransack/adapters'
|
4
|
-
require 'polyamorous/polyamorous
|
4
|
+
require 'polyamorous/polyamorous'
|
5
5
|
|
6
6
|
Ransack::Adapters.object_mapper.require_constants
|
7
7
|
|
8
8
|
module Ransack
|
9
9
|
extend Configuration
|
10
|
-
class UntraversableAssociationError < StandardError; end
|
10
|
+
class UntraversableAssociationError < StandardError; end
|
11
11
|
end
|
12
12
|
|
13
13
|
Ransack.configure do |config|
|
@@ -18,6 +18,10 @@ module Ransack
|
|
18
18
|
Search.new(self, params, options)
|
19
19
|
end
|
20
20
|
|
21
|
+
def ransack!(params = {}, options = {})
|
22
|
+
ransack(params, options.merge(ignore_unknown_conditions: false))
|
23
|
+
end
|
24
|
+
|
21
25
|
def ransacker(name, opts = {}, &block)
|
22
26
|
self._ransackers = _ransackers.merge name.to_s => Ransacker
|
23
27
|
.new(self, name, opts, &block)
|
@@ -42,6 +42,13 @@ module Ransack
|
|
42
42
|
if scope_or_sort.is_a?(Symbol)
|
43
43
|
relation = relation.send(scope_or_sort)
|
44
44
|
else
|
45
|
+
case Ransack.options[:postgres_fields_sort_option]
|
46
|
+
when :nulls_first
|
47
|
+
scope_or_sort = scope_or_sort.direction == :asc ? "#{scope_or_sort.to_sql} NULLS FIRST" : "#{scope_or_sort.to_sql} NULLS LAST"
|
48
|
+
when :nulls_last
|
49
|
+
scope_or_sort = scope_or_sort.direction == :asc ? "#{scope_or_sort.to_sql} NULLS LAST" : "#{scope_or_sort.to_sql} NULLS FIRST"
|
50
|
+
end
|
51
|
+
|
45
52
|
relation = relation.order(scope_or_sort)
|
46
53
|
end
|
47
54
|
end
|
@@ -99,7 +106,7 @@ module Ransack
|
|
99
106
|
def join_sources
|
100
107
|
base, joins = begin
|
101
108
|
alias_tracker = ::ActiveRecord::Associations::AliasTracker.create(self.klass.connection, @object.table.name, [])
|
102
|
-
constraints = if ::Gem::Version.new(::ActiveRecord::VERSION::STRING) >= ::Gem::Version.new(Constants::
|
109
|
+
constraints = if ::Gem::Version.new(::ActiveRecord::VERSION::STRING) >= ::Gem::Version.new(Constants::RAILS_6_1)
|
103
110
|
@join_dependency.join_constraints(@object.joins_values, alias_tracker, @object.references_values)
|
104
111
|
elsif ::Gem::Version.new(::ActiveRecord::VERSION::STRING) >= ::Gem::Version.new(Constants::RAILS_6_0)
|
105
112
|
@join_dependency.join_constraints(@object.joins_values, alias_tracker)
|
@@ -327,7 +334,7 @@ module Ransack
|
|
327
334
|
@join_dependency.instance_variable_get(:@join_root).children.push found_association
|
328
335
|
|
329
336
|
# Builds the arel nodes properly for this association
|
330
|
-
if ::Gem::Version.new(::ActiveRecord::VERSION::STRING) >= ::Gem::Version.new(Constants::
|
337
|
+
if ::Gem::Version.new(::ActiveRecord::VERSION::STRING) >= ::Gem::Version.new(Constants::RAILS_6_1)
|
331
338
|
@tables_pot[found_association] = @join_dependency.construct_tables_for_association!(jd.instance_variable_get(:@join_root), found_association)
|
332
339
|
else
|
333
340
|
@join_dependency.send(:construct_tables!, jd.instance_variable_get(:@join_root))
|
@@ -341,7 +348,7 @@ module Ransack
|
|
341
348
|
def extract_joins(association)
|
342
349
|
parent = @join_dependency.instance_variable_get(:@join_root)
|
343
350
|
reflection = association.reflection
|
344
|
-
join_constraints = if ::Gem::Version.new(::ActiveRecord::VERSION::STRING) >= ::Gem::Version.new(Constants::
|
351
|
+
join_constraints = if ::Gem::Version.new(::ActiveRecord::VERSION::STRING) >= ::Gem::Version.new(Constants::RAILS_6_1)
|
345
352
|
association.join_constraints_with_tables(
|
346
353
|
parent.table,
|
347
354
|
parent.base_klass,
|
@@ -97,7 +97,7 @@ module Ransack
|
|
97
97
|
arel_predicate: proc { |v| v ? EQ : NOT_EQ },
|
98
98
|
compounds: false,
|
99
99
|
type: :boolean,
|
100
|
-
validator: proc { |v| BOOLEAN_VALUES.include?(v)},
|
100
|
+
validator: proc { |v| BOOLEAN_VALUES.include?(v) },
|
101
101
|
formatter: proc { |v| nil }
|
102
102
|
}
|
103
103
|
],
|
@@ -33,7 +33,8 @@ module Ransack
|
|
33
33
|
:up_arrow => '▼'.freeze,
|
34
34
|
:down_arrow => '▲'.freeze,
|
35
35
|
:default_arrow => nil,
|
36
|
-
:sanitize_scope_args => true
|
36
|
+
:sanitize_scope_args => true,
|
37
|
+
:postgres_fields_sort_option => nil
|
37
38
|
}
|
38
39
|
|
39
40
|
def configure
|
@@ -141,6 +142,21 @@ module Ransack
|
|
141
142
|
self.options[:sanitize_scope_args] = boolean
|
142
143
|
end
|
143
144
|
|
145
|
+
# The `NULLS FIRST` and `NULLS LAST` options can be used to determine
|
146
|
+
# whether nulls appear before or after non-null values in the sort ordering.
|
147
|
+
#
|
148
|
+
# User may want to configure it like this:
|
149
|
+
#
|
150
|
+
# Ransack.configure do |c|
|
151
|
+
# c.postgres_fields_sort_option = :nulls_first # or :nulls_last
|
152
|
+
# end
|
153
|
+
#
|
154
|
+
# See this feature: https://www.postgresql.org/docs/13/queries-order.html
|
155
|
+
#
|
156
|
+
def postgres_fields_sort_option=(setting)
|
157
|
+
self.options[:postgres_fields_sort_option] = setting
|
158
|
+
end
|
159
|
+
|
144
160
|
# By default, Ransack displays sort order indicator arrows in sort links.
|
145
161
|
# The default may be globally overridden in an initializer file like
|
146
162
|
# `config/initializers/ransack.rb` as follows:
|
data/lib/ransack/constants.rb
CHANGED
@@ -36,7 +36,7 @@ module Ransack
|
|
36
36
|
'lt'.freeze, 'lteq'.freeze,
|
37
37
|
'gt'.freeze, 'gteq'.freeze,
|
38
38
|
'in'.freeze, 'not_in'.freeze
|
39
|
-
|
39
|
+
].freeze
|
40
40
|
A_S_I = ['a'.freeze, 's'.freeze, 'i'.freeze].freeze
|
41
41
|
|
42
42
|
EQ = 'eq'.freeze
|
@@ -46,10 +46,9 @@ module Ransack
|
|
46
46
|
CONT = 'cont'.freeze
|
47
47
|
|
48
48
|
RAILS_6_0 = '6.0.0'.freeze
|
49
|
-
|
49
|
+
RAILS_6_1 = '6.1.0'.freeze
|
50
50
|
|
51
51
|
RANSACK_SLASH_SEARCHES = 'ransack/searches'.freeze
|
52
52
|
RANSACK_SLASH_SEARCHES_SLASH_SEARCH = 'ransack/searches/search'.freeze
|
53
53
|
end
|
54
54
|
end
|
55
|
-
|
data/lib/ransack/helpers.rb
CHANGED
@@ -1,2 +1,2 @@
|
|
1
1
|
require 'ransack/helpers/form_builder'
|
2
|
-
require 'ransack/helpers/form_helper'
|
2
|
+
require 'ransack/helpers/form_helper'
|
@@ -45,9 +45,9 @@ module Ransack
|
|
45
45
|
end
|
46
46
|
|
47
47
|
def attribute_select(options = nil, html_options = nil, action = nil)
|
48
|
-
options
|
49
|
-
html_options
|
50
|
-
action
|
48
|
+
options ||= {}
|
49
|
+
html_options ||= {}
|
50
|
+
action ||= Constants::SEARCH
|
51
51
|
default = options.delete(:default)
|
52
52
|
raise ArgumentError, formbuilder_error_message(
|
53
53
|
"#{action}_select") unless object.respond_to?(:context)
|
@@ -127,7 +127,6 @@ module Ransack
|
|
127
127
|
alias :m= :combinator=
|
128
128
|
alias :m :combinator
|
129
129
|
|
130
|
-
|
131
130
|
# == build_attribute
|
132
131
|
#
|
133
132
|
# This method was originally called from Nodes::Grouping#new_condition
|
@@ -263,7 +262,6 @@ module Ransack
|
|
263
262
|
attr.attr
|
264
263
|
end
|
265
264
|
|
266
|
-
|
267
265
|
def default_type
|
268
266
|
predicate.type || (attributes.first && attributes.first.type)
|
269
267
|
end
|
data/lib/ransack/nodes/sort.rb
CHANGED
data/lib/ransack/nodes/value.rb
CHANGED
data/lib/ransack/search.rb
CHANGED
@@ -30,6 +30,7 @@ module Ransack
|
|
30
30
|
)
|
31
31
|
@scope_args = {}
|
32
32
|
@sorts ||= []
|
33
|
+
@ignore_unknown_conditions = options[:ignore_unknown_conditions] == false ? false : true
|
33
34
|
build(params.with_indifferent_access)
|
34
35
|
end
|
35
36
|
|
@@ -45,7 +46,7 @@ module Ransack
|
|
45
46
|
base.send("#{key}=", value)
|
46
47
|
elsif @context.ransackable_scope?(key, @context.object)
|
47
48
|
add_scope(key, value)
|
48
|
-
elsif !Ransack.options[:ignore_unknown_conditions]
|
49
|
+
elsif !Ransack.options[:ignore_unknown_conditions] || !@ignore_unknown_conditions
|
49
50
|
raise ArgumentError, "Invalid search term #{key}"
|
50
51
|
end
|
51
52
|
end
|
data/lib/ransack/version.rb
CHANGED
data/ransack.gemspec
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
# -*- encoding: utf-8 -*-
|
2
|
+
|
2
3
|
$:.push File.expand_path("../lib", __FILE__)
|
3
4
|
require "ransack/version"
|
4
5
|
|
@@ -6,12 +7,12 @@ Gem::Specification.new do |s|
|
|
6
7
|
s.name = "ransack"
|
7
8
|
s.version = Ransack::VERSION
|
8
9
|
s.platform = Gem::Platform::RUBY
|
9
|
-
s.authors = ["Ernie Miller", "Ryan Bigg", "Jon Atack","Sean Carroll"]
|
10
|
-
s.email = ["ernie@erniemiller.org", "radarlistener@gmail.com", "jonnyatack@gmail.com","sfcarroll@gmail.com"]
|
10
|
+
s.authors = ["Ernie Miller", "Ryan Bigg", "Jon Atack", "Sean Carroll"]
|
11
|
+
s.email = ["ernie@erniemiller.org", "radarlistener@gmail.com", "jonnyatack@gmail.com", "sfcarroll@gmail.com"]
|
11
12
|
s.homepage = "https://github.com/activerecord-hackery/ransack"
|
12
13
|
s.summary = %q{Object-based searching for Active Record and Mongoid (currently).}
|
13
14
|
s.description = %q{Ransack is the successor to the MetaSearch gem. It improves and expands upon MetaSearch's functionality, but does not have a 100%-compatible API.}
|
14
|
-
s.required_ruby_version = '>= 2.
|
15
|
+
s.required_ruby_version = '>= 2.6'
|
15
16
|
s.license = 'MIT'
|
16
17
|
|
17
18
|
s.add_dependency 'activerecord', '>= 5.2.4'
|
data/spec/blueprints/articles.rb
CHANGED