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.
Files changed (35) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +13 -27
  3. data/lib/ransack/active_record/base.rb +154 -0
  4. data/lib/ransack/active_record/context.rb +504 -0
  5. data/lib/ransack/active_record/dialect.rb +83 -0
  6. data/lib/ransack/active_record/join.rb +75 -0
  7. data/lib/ransack/active_record/join_association.rb +104 -0
  8. data/lib/ransack/active_record/join_dependency.rb +123 -0
  9. data/lib/ransack/active_record/reflection.rb +18 -0
  10. data/lib/ransack/active_record/tree_node.rb +13 -0
  11. data/lib/ransack/active_record.rb +44 -9
  12. data/lib/ransack/configuration.rb +49 -1
  13. data/lib/ransack/constants.rb +52 -0
  14. data/lib/ransack/context.rb +159 -35
  15. data/lib/ransack/helpers/form_builder.rb +30 -25
  16. data/lib/ransack/nodes/bindable.rb +0 -1
  17. data/lib/ransack/nodes/condition.rb +215 -73
  18. data/lib/ransack/nodes/grouping.rb +33 -11
  19. data/lib/ransack/nodes/sort.rb +1 -1
  20. data/lib/ransack/nodes/value.rb +8 -1
  21. data/lib/ransack/predicate.rb +8 -1
  22. data/lib/ransack/search.rb +52 -9
  23. data/lib/ransack/version.rb +1 -1
  24. data/lib/ransack.rb +4 -1
  25. metadata +11 -13
  26. data/lib/polyamorous/activerecord/join_association.rb +0 -70
  27. data/lib/polyamorous/activerecord/join_association_7_2.rb +0 -55
  28. data/lib/polyamorous/activerecord/join_dependency.rb +0 -102
  29. data/lib/polyamorous/activerecord/reflection.rb +0 -11
  30. data/lib/polyamorous/join.rb +0 -70
  31. data/lib/polyamorous/polyamorous.rb +0 -27
  32. data/lib/polyamorous/swapping_reflection_class.rb +0 -11
  33. data/lib/polyamorous/tree_node.rb +0 -7
  34. data/lib/ransack/adapters/active_record/base.rb +0 -152
  35. 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: e1da5ebd35a1352f55541bdc21342c512b6209e385546e8e217c38c4dea79ad5
4
- data.tar.gz: 61525c16d6c5e02c57575e72edd28eb9b6376a53bf791e1fda60b2581a95049d
3
+ metadata.gz: ab7bd0c932988849a454c8178e7676022783c3bddb36f8e8d951c11aaf24de7c
4
+ data.tar.gz: c076572a9ea5b4084fe9754bfc53cdcfa33667f8b2837ed1880fc11c1b855345
5
5
  SHA512:
6
- metadata.gz: 0bcdd2aeda080a80a469e591a27b5a4dfa5dadf36b3de1e62a037de661c01e3d8092d4f60d5d458097cace0a1ce87434590a9914651dfd74f899f7d03a144367
7
- data.tar.gz: 7aea600100c4ea0001ffed5c84729e950ecb7ccc5421fb853886031585c1a3486377c15facef12c43796a9c5072069972303aa74c868daf24ebfc235e7a49900
6
+ metadata.gz: 01de2b357a7c9f782d5e3ca9fb705ef4ccbd0b01a291fd90537903f2d514b4da3734fc6fba0425e9b908b78d2c073ba1cfde886c22f55432c68b739b14dc7336
7
+ data.tar.gz: e3f13fdd795a2bfd0b37a4d7788ea9437f445c05a25185bc22e1e85efa84e0bbe47d63613d09f9d7b3690a75e9ccf05bcec63944e3804436de97247c230b3834
data/README.md CHANGED
@@ -1,10 +1,9 @@
1
- # ![Ransack](./docs/static/logo/ransack-h.png "Ransack")
1
+ # ![Ransack](./docs/assets/logo/ransack-h.png "Ransack")
2
2
 
3
3
  [![Build Status](https://github.com/activerecord-hackery/ransack/workflows/test/badge.svg)](https://github.com/activerecord-hackery/ransack/actions)
4
4
  [![Gem Version](https://badge.fury.io/rb/ransack.svg)](http://badge.fury.io/rb/ransack)
5
5
  [![Ask DeepWiki](https://deepwiki.com/badge.svg)](https://deepwiki.com/activerecord-hackery/ransack)
6
6
  [![Code Climate](https://codeclimate.com/github/activerecord-hackery/ransack/badges/gpa.svg)](https://codeclimate.com/github/activerecord-hackery/ransack)
7
- [![Backers on Open Collective](https://opencollective.com/ransack/backers/badge.svg)](#backers) [![Sponsors on Open Collective](https://opencollective.com/ransack/sponsors/badge.svg)](#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.1 and later.
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/), which is a [Docusaurus](https://docusaurus.io/) project and run 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/).
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