ransack 5.0.2 → 6.0.0
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/README.md +13 -27
- data/lib/ransack/active_record/base.rb +154 -0
- data/lib/ransack/active_record/context.rb +504 -0
- data/lib/ransack/active_record/dialect.rb +83 -0
- data/lib/ransack/active_record/join.rb +75 -0
- data/lib/ransack/active_record/join_association.rb +104 -0
- data/lib/ransack/active_record/join_dependency.rb +123 -0
- data/lib/ransack/active_record/reflection.rb +18 -0
- data/lib/ransack/active_record/tree_node.rb +13 -0
- data/lib/ransack/active_record.rb +44 -9
- data/lib/ransack/configuration.rb +49 -1
- data/lib/ransack/constants.rb +52 -0
- data/lib/ransack/context.rb +159 -35
- data/lib/ransack/helpers/form_builder.rb +30 -25
- data/lib/ransack/nodes/bindable.rb +0 -1
- data/lib/ransack/nodes/condition.rb +215 -73
- data/lib/ransack/nodes/grouping.rb +33 -11
- data/lib/ransack/nodes/sort.rb +1 -1
- data/lib/ransack/nodes/value.rb +8 -1
- data/lib/ransack/predicate.rb +8 -1
- data/lib/ransack/search.rb +52 -9
- data/lib/ransack/version.rb +1 -1
- data/lib/ransack.rb +4 -1
- metadata +11 -13
- data/lib/polyamorous/activerecord/join_association.rb +0 -70
- data/lib/polyamorous/activerecord/join_association_7_2.rb +0 -55
- data/lib/polyamorous/activerecord/join_dependency.rb +0 -102
- data/lib/polyamorous/activerecord/reflection.rb +0 -11
- data/lib/polyamorous/join.rb +0 -70
- data/lib/polyamorous/polyamorous.rb +0 -27
- data/lib/polyamorous/swapping_reflection_class.rb +0 -11
- data/lib/polyamorous/tree_node.rb +0 -7
- data/lib/ransack/adapters/active_record/base.rb +0 -152
- data/lib/ransack/adapters/active_record/context.rb +0 -379
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: ab7bd0c932988849a454c8178e7676022783c3bddb36f8e8d951c11aaf24de7c
|
|
4
|
+
data.tar.gz: c076572a9ea5b4084fe9754bfc53cdcfa33667f8b2837ed1880fc11c1b855345
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 01de2b357a7c9f782d5e3ca9fb705ef4ccbd0b01a291fd90537903f2d514b4da3734fc6fba0425e9b908b78d2c073ba1cfde886c22f55432c68b739b14dc7336
|
|
7
|
+
data.tar.gz: e3f13fdd795a2bfd0b37a4d7788ea9437f445c05a25185bc22e1e85efa84e0bbe47d63613d09f9d7b3690a75e9ccf05bcec63944e3804436de97247c230b3834
|
data/README.md
CHANGED
|
@@ -1,10 +1,9 @@
|
|
|
1
|
-
# 
|
|
2
2
|
|
|
3
3
|
[](https://github.com/activerecord-hackery/ransack/actions)
|
|
4
4
|
[](http://badge.fury.io/rb/ransack)
|
|
5
5
|
[](https://deepwiki.com/activerecord-hackery/ransack)
|
|
6
6
|
[](https://codeclimate.com/github/activerecord-hackery/ransack)
|
|
7
|
-
[](#backers) [](#sponsors)
|
|
8
7
|
|
|
9
8
|
# Introduction
|
|
10
9
|
|
|
@@ -14,7 +13,7 @@ There are advanced searching solutions around, like ElasticSearch or Algolia. **
|
|
|
14
13
|
|
|
15
14
|
Ready to move beyond the basics? Use **advanced features** like i18n and extensive configuration options.
|
|
16
15
|
|
|
17
|
-
Ransack is supported for Rails 8.1, 8.0, 7.2 on Ruby 3.
|
|
16
|
+
Ransack is supported for Rails 8.1, 8.0, 7.2 on Ruby 3.2 and later.
|
|
18
17
|
|
|
19
18
|
## Installation
|
|
20
19
|
|
|
@@ -34,7 +33,7 @@ gem 'ransack', :github => 'activerecord-hackery/ransack', :branch => 'main'
|
|
|
34
33
|
|
|
35
34
|
### Documentation
|
|
36
35
|
|
|
37
|
-
There is [extensive documentation on Ransack](https://activerecord-hackery.github.io/ransack/),
|
|
36
|
+
There is [extensive documentation on Ransack](https://activerecord-hackery.github.io/ransack/), built with [Jekyll](https://jekyllrb.com/) and [Just the Docs](https://just-the-docs.com/) from the Markdown under `docs/` and published as a GitHub Pages site. Alternatively there is [AI Generated documentation](https://deepwiki.com/activerecord-hackery/ransack/1-overview) produced by [devin.ai](https://devin.ai/).
|
|
38
37
|
|
|
39
38
|
This [gist](https://gist.github.com/raghubetina/d5fc3df67ddbadcac271) has a quick-start cheatsheet, created by [@raghubetina](https://gist.github.com/raghubetina)
|
|
40
39
|
|
|
@@ -51,7 +50,6 @@ This [gist](https://gist.github.com/raghubetina/d5fc3df67ddbadcac271) has a quic
|
|
|
51
50
|
|
|
52
51
|
To support the project:
|
|
53
52
|
|
|
54
|
-
* Consider supporting us via [Open Collective](https://opencollective.com/ransack/backers/badge.svg)
|
|
55
53
|
* Use Ransack in your apps, and let us know if you encounter anything that's
|
|
56
54
|
broken or missing. A failing spec to demonstrate the issue is awesome. A pull
|
|
57
55
|
request with passing tests is even better!
|
|
@@ -63,6 +61,16 @@ directly related to bug reports, pull requests, or documentation improvements.
|
|
|
63
61
|
to you. The more people who are using the project, the quicker we can find and
|
|
64
62
|
fix bugs!
|
|
65
63
|
|
|
64
|
+
## Ransack for enterprise
|
|
65
|
+
|
|
66
|
+
Available as part of the [Tidelift Subscription](https://tidelift.com/subscription/pkg/rubygems-ransack?utm_source=rubygems-ransack&utm_medium=referral&utm_campaign=enterprise&utm_term=repo).
|
|
67
|
+
|
|
68
|
+
The maintainers of Ransack and thousands of other packages are working with Tidelift to deliver commercial support and maintenance for the open source dependencies you use to build your applications. Save time, reduce risk, and improve code health, while paying the maintainers of the exact dependencies you use. [Learn more.](https://tidelift.com/subscription/pkg/rubygems-ransack?utm_source=rubygems-ransack&utm_medium=referral&utm_campaign=enterprise&utm_term=repo)
|
|
69
|
+
|
|
70
|
+
## Security contact information
|
|
71
|
+
|
|
72
|
+
To report a security vulnerability, please use the [Tidelift security contact](https://tidelift.com/security). Tidelift will coordinate the fix and disclosure. See the [Security Policy](.github/SECURITY.md) for supported versions.
|
|
73
|
+
|
|
66
74
|
## Contributors
|
|
67
75
|
|
|
68
76
|
Ransack was created by [Ernie Miller](http://twitter.com/erniemiller) and is developed and maintained by:
|
|
@@ -78,25 +86,3 @@ Alumni Maintainers
|
|
|
78
86
|
|
|
79
87
|
This project exists thanks to all the people who contribute. <img src="https://opencollective.com/ransack/contributors.svg?width=890&button=false" />
|
|
80
88
|
|
|
81
|
-
|
|
82
|
-
## Backers
|
|
83
|
-
|
|
84
|
-
Thank you to all our backers! 🙏 [[Become a backer](https://opencollective.com/ransack#backer)]
|
|
85
|
-
|
|
86
|
-
<a href="https://opencollective.com/ransack#backers" target="_blank"><img src="https://opencollective.com/ransack/backers.svg?width=890" /></a>
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
## Sponsors
|
|
90
|
-
|
|
91
|
-
Support this project by becoming a sponsor. Your logo will show up here with a link to your website. [[Become a sponsor](https://opencollective.com/ransack#sponsor)]
|
|
92
|
-
|
|
93
|
-
<a href="https://opencollective.com/ransack/sponsor/0/website" target="_blank"><img src="https://opencollective.com/ransack/sponsor/0/avatar.svg" /></a>
|
|
94
|
-
<a href="https://opencollective.com/ransack/sponsor/1/website" target="_blank"><img src="https://opencollective.com/ransack/sponsor/1/avatar.svg" /></a>
|
|
95
|
-
<a href="https://opencollective.com/ransack/sponsor/2/website" target="_blank"><img src="https://opencollective.com/ransack/sponsor/2/avatar.svg" /></a>
|
|
96
|
-
<a href="https://opencollective.com/ransack/sponsor/3/website" target="_blank"><img src="https://opencollective.com/ransack/sponsor/3/avatar.svg" /></a>
|
|
97
|
-
<a href="https://opencollective.com/ransack/sponsor/4/website" target="_blank"><img src="https://opencollective.com/ransack/sponsor/4/avatar.svg" /></a>
|
|
98
|
-
<a href="https://opencollective.com/ransack/sponsor/5/website" target="_blank"><img src="https://opencollective.com/ransack/sponsor/5/avatar.svg" /></a>
|
|
99
|
-
<a href="https://opencollective.com/ransack/sponsor/6/website" target="_blank"><img src="https://opencollective.com/ransack/sponsor/6/avatar.svg" /></a>
|
|
100
|
-
<a href="https://opencollective.com/ransack/sponsor/7/website" target="_blank"><img src="https://opencollective.com/ransack/sponsor/7/avatar.svg" /></a>
|
|
101
|
-
<a href="https://opencollective.com/ransack/sponsor/8/website" target="_blank"><img src="https://opencollective.com/ransack/sponsor/8/avatar.svg" /></a>
|
|
102
|
-
<a href="https://opencollective.com/ransack/sponsor/9/website" target="_blank"><img src="https://opencollective.com/ransack/sponsor/9/avatar.svg" /></a>
|
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
module Ransack
|
|
2
|
+
module ActiveRecord
|
|
3
|
+
# Extended onto ActiveRecord::Base: the `ransack` entry point, the
|
|
4
|
+
# `ransacker` and `ransack_alias` declarations, and the allowlist methods
|
|
5
|
+
# every model must define before it can be searched.
|
|
6
|
+
module Base
|
|
7
|
+
|
|
8
|
+
def self.extended(base)
|
|
9
|
+
base.class_eval do
|
|
10
|
+
class_attribute :_ransackers
|
|
11
|
+
class_attribute :_ransack_aliases
|
|
12
|
+
self._ransackers ||= {}
|
|
13
|
+
self._ransack_aliases ||= {}
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def ransack(params = {}, options = {})
|
|
18
|
+
Search.new(self, params, options)
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def ransack!(params = {}, options = {})
|
|
22
|
+
ransack(params, options.merge(ignore_unknown_conditions: false))
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def ransacker(name, opts = {}, &block)
|
|
26
|
+
self._ransackers = _ransackers.merge name.to_s => Ransacker
|
|
27
|
+
.new(self, name, opts, &block)
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def ransack_alias(new_name, old_name)
|
|
31
|
+
self._ransack_aliases = _ransack_aliases.merge new_name.to_s =>
|
|
32
|
+
old_name.to_s
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
# Ransackable_attributes, by default, returns all column names
|
|
36
|
+
# and any defined ransackers as an array of strings.
|
|
37
|
+
# For overriding with a whitelist array of strings.
|
|
38
|
+
#
|
|
39
|
+
def ransackable_attributes(auth_object = nil)
|
|
40
|
+
@ransackable_attributes ||= deprecated_ransackable_list(:ransackable_attributes)
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
# Ransackable_associations, by default, returns the names
|
|
44
|
+
# of all associations as an array of strings.
|
|
45
|
+
# For overriding with a whitelist array of strings.
|
|
46
|
+
#
|
|
47
|
+
def ransackable_associations(auth_object = nil)
|
|
48
|
+
@ransackable_associations ||= deprecated_ransackable_list(:ransackable_associations)
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
# Ransortable_attributes, by default, returns the names
|
|
52
|
+
# of all attributes available for sorting as an array of strings.
|
|
53
|
+
# For overriding with a whitelist array of strings.
|
|
54
|
+
#
|
|
55
|
+
def ransortable_attributes(auth_object = nil)
|
|
56
|
+
ransackable_attributes(auth_object)
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
# Ransackable_scopes, by default, returns an empty array
|
|
60
|
+
# i.e. no class methods/scopes are authorized.
|
|
61
|
+
# For overriding with a whitelist array of *symbols*.
|
|
62
|
+
#
|
|
63
|
+
def ransackable_scopes(auth_object = nil)
|
|
64
|
+
[]
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
# ransack_scope_skip_sanitize_args, by default, returns an empty array.
|
|
68
|
+
# i.e. use the sanitize_scope_args setting to determine if args should be converted.
|
|
69
|
+
# For overriding with a list of scopes which should be passed the args as-is.
|
|
70
|
+
#
|
|
71
|
+
def ransackable_scopes_skip_sanitize_args
|
|
72
|
+
[]
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
# Bare list of all potentially searchable attributes. Searchable attributes
|
|
76
|
+
# need to be explicitly allowlisted through the `ransackable_attributes`
|
|
77
|
+
# method in each model, but if you're allowing almost everything to be
|
|
78
|
+
# searched, this list can be used as a base for exclusions.
|
|
79
|
+
#
|
|
80
|
+
def authorizable_ransackable_attributes
|
|
81
|
+
(column_names + _ransackers.keys + _ransack_aliases.keys +
|
|
82
|
+
attribute_aliases.keys).uniq
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
# Bare list of all potentially searchable associations. Searchable
|
|
86
|
+
# associations need to be explicitly allowlisted through the
|
|
87
|
+
# `ransackable_associations` method in each model, but if you're
|
|
88
|
+
# allowing almost everything to be searched, this list can be used as a
|
|
89
|
+
# base for exclusions.
|
|
90
|
+
#
|
|
91
|
+
def authorizable_ransackable_associations
|
|
92
|
+
reflect_on_all_associations.map { |a| a.name.to_s }
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
# Whether this model, or a superclass of it, defines `method` itself
|
|
96
|
+
# rather than inheriting Ransack's default. The search context asks
|
|
97
|
+
# before trusting permitted strong parameters: a model with a list of
|
|
98
|
+
# its own always applies it, and only a model without one lets the
|
|
99
|
+
# controller's permit list be the boundary (#1403).
|
|
100
|
+
def ransackable_list_defined?(method)
|
|
101
|
+
definer_ancestor = singleton_class.ancestors.find do |ancestor|
|
|
102
|
+
ancestor.instance_methods(false).include?(method)
|
|
103
|
+
end
|
|
104
|
+
|
|
105
|
+
definer_ancestor != Ransack::ActiveRecord::Base
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
private
|
|
109
|
+
|
|
110
|
+
def deprecated_ransackable_list(method)
|
|
111
|
+
list_type = method.to_s.delete_prefix("ransackable_")
|
|
112
|
+
|
|
113
|
+
if ransackable_list_defined?(method)
|
|
114
|
+
warn_deprecated <<~ERROR
|
|
115
|
+
Ransack's builtin `#{method}` method is deprecated and will result
|
|
116
|
+
in an error in the future. If you want to authorize the full list
|
|
117
|
+
of searchable #{list_type} for this model, use
|
|
118
|
+
`authorizable_#{method}` instead of delegating to `super`.
|
|
119
|
+
ERROR
|
|
120
|
+
|
|
121
|
+
public_send("authorizable_#{method}")
|
|
122
|
+
else
|
|
123
|
+
raise <<~MESSAGE
|
|
124
|
+
Ransack needs #{name} #{list_type} explicitly allowlisted as
|
|
125
|
+
searchable. Define a `#{method}` class method in your `#{name}`
|
|
126
|
+
model, watching out for items you DON'T want searchable (for
|
|
127
|
+
example, `encrypted_password`, `password_reset_token`, `owner` or
|
|
128
|
+
other sensitive information). You can use the following as a base:
|
|
129
|
+
|
|
130
|
+
```ruby
|
|
131
|
+
class #{name} < ApplicationRecord
|
|
132
|
+
|
|
133
|
+
# ...
|
|
134
|
+
|
|
135
|
+
def self.#{method}(auth_object = nil)
|
|
136
|
+
#{public_send("authorizable_#{method}").sort.inspect}
|
|
137
|
+
end
|
|
138
|
+
|
|
139
|
+
# ...
|
|
140
|
+
|
|
141
|
+
end
|
|
142
|
+
```
|
|
143
|
+
MESSAGE
|
|
144
|
+
end
|
|
145
|
+
end
|
|
146
|
+
|
|
147
|
+
def warn_deprecated(message)
|
|
148
|
+
caller_location = caller_locations.find { |location| !location.path.start_with?(File.expand_path("../..", __dir__)) }
|
|
149
|
+
|
|
150
|
+
warn "DEPRECATION WARNING: #{message.squish} (called at #{caller_location.path}:#{caller_location.lineno})"
|
|
151
|
+
end
|
|
152
|
+
end
|
|
153
|
+
end
|
|
154
|
+
end
|