giga-pure-kit 0.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 +7 -0
- data/giga-pure-kit.gemspec +12 -0
- data/ransack-4.4.1/LICENSE +20 -0
- data/ransack-4.4.1/README.md +101 -0
- data/ransack-4.4.1/lib/polyamorous/activerecord/join_association.rb +218 -0
- data/ransack-4.4.1/lib/polyamorous/activerecord/join_association_7_2.rb +55 -0
- data/ransack-4.4.1/lib/polyamorous/activerecord/join_dependency.rb +102 -0
- data/ransack-4.4.1/lib/polyamorous/activerecord/reflection.rb +11 -0
- data/ransack-4.4.1/lib/polyamorous/join.rb +70 -0
- data/ransack-4.4.1/lib/polyamorous/polyamorous.rb +27 -0
- data/ransack-4.4.1/lib/polyamorous/swapping_reflection_class.rb +11 -0
- data/ransack-4.4.1/lib/polyamorous/tree_node.rb +7 -0
- data/ransack-4.4.1/lib/ransack/active_record.rb +14 -0
- data/ransack-4.4.1/lib/ransack/adapters/active_record/base.rb +152 -0
- data/ransack-4.4.1/lib/ransack/adapters/active_record/context.rb +373 -0
- data/ransack-4.4.1/lib/ransack/configuration.rb +209 -0
- data/ransack-4.4.1/lib/ransack/constants.rb +176 -0
- data/ransack-4.4.1/lib/ransack/context.rb +190 -0
- data/ransack-4.4.1/lib/ransack/helpers/form_builder.rb +277 -0
- data/ransack-4.4.1/lib/ransack/helpers/form_helper.rb +311 -0
- data/ransack-4.4.1/lib/ransack/helpers.rb +2 -0
- data/ransack-4.4.1/lib/ransack/invalid_search_error.rb +3 -0
- data/ransack-4.4.1/lib/ransack/locale/ar.yml +70 -0
- data/ransack-4.4.1/lib/ransack/locale/az.yml +70 -0
- data/ransack-4.4.1/lib/ransack/locale/bg.yml +70 -0
- data/ransack-4.4.1/lib/ransack/locale/ca.yml +70 -0
- data/ransack-4.4.1/lib/ransack/locale/cs.yml +70 -0
- data/ransack-4.4.1/lib/ransack/locale/da.yml +70 -0
- data/ransack-4.4.1/lib/ransack/locale/de.yml +70 -0
- data/ransack-4.4.1/lib/ransack/locale/el.yml +70 -0
- data/ransack-4.4.1/lib/ransack/locale/en.yml +70 -0
- data/ransack-4.4.1/lib/ransack/locale/es.yml +70 -0
- data/ransack-4.4.1/lib/ransack/locale/fa.yml +70 -0
- data/ransack-4.4.1/lib/ransack/locale/fi.yml +71 -0
- data/ransack-4.4.1/lib/ransack/locale/fr.yml +70 -0
- data/ransack-4.4.1/lib/ransack/locale/hu.yml +70 -0
- data/ransack-4.4.1/lib/ransack/locale/id.yml +70 -0
- data/ransack-4.4.1/lib/ransack/locale/it.yml +70 -0
- data/ransack-4.4.1/lib/ransack/locale/ja.yml +70 -0
- data/ransack-4.4.1/lib/ransack/locale/ko.yml +70 -0
- data/ransack-4.4.1/lib/ransack/locale/nl.yml +70 -0
- data/ransack-4.4.1/lib/ransack/locale/pt-BR.yml +70 -0
- data/ransack-4.4.1/lib/ransack/locale/ro.yml +70 -0
- data/ransack-4.4.1/lib/ransack/locale/ru.yml +70 -0
- data/ransack-4.4.1/lib/ransack/locale/sk.yml +70 -0
- data/ransack-4.4.1/lib/ransack/locale/sv.yml +70 -0
- data/ransack-4.4.1/lib/ransack/locale/tr.yml +70 -0
- data/ransack-4.4.1/lib/ransack/locale/uk.yml +72 -0
- data/ransack-4.4.1/lib/ransack/locale/zh-CN.yml +70 -0
- data/ransack-4.4.1/lib/ransack/locale/zh-TW.yml +70 -0
- data/ransack-4.4.1/lib/ransack/naming.rb +58 -0
- data/ransack-4.4.1/lib/ransack/nodes/attribute.rb +59 -0
- data/ransack-4.4.1/lib/ransack/nodes/bindable.rb +52 -0
- data/ransack-4.4.1/lib/ransack/nodes/condition.rb +399 -0
- data/ransack-4.4.1/lib/ransack/nodes/grouping.rb +206 -0
- data/ransack-4.4.1/lib/ransack/nodes/node.rb +34 -0
- data/ransack-4.4.1/lib/ransack/nodes/sort.rb +54 -0
- data/ransack-4.4.1/lib/ransack/nodes/value.rb +115 -0
- data/ransack-4.4.1/lib/ransack/predicate.rb +75 -0
- data/ransack-4.4.1/lib/ransack/ransacker.rb +24 -0
- data/ransack-4.4.1/lib/ransack/search.rb +195 -0
- data/ransack-4.4.1/lib/ransack/translate.rb +156 -0
- data/ransack-4.4.1/lib/ransack/version.rb +3 -0
- data/ransack-4.4.1/lib/ransack/visitor.rb +87 -0
- data/ransack-4.4.1/lib/ransack.rb +33 -0
- data/ransack-4.4.1/spec/console.rb +13 -0
- data/ransack-4.4.1/spec/factories/articles.rb +7 -0
- data/ransack-4.4.1/spec/factories/comments.rb +7 -0
- data/ransack-4.4.1/spec/factories/notes.rb +13 -0
- data/ransack-4.4.1/spec/factories/people.rb +10 -0
- data/ransack-4.4.1/spec/factories/tags.rb +5 -0
- data/ransack-4.4.1/spec/helpers/polyamorous_helper.rb +13 -0
- data/ransack-4.4.1/spec/helpers/ransack_helper.rb +9 -0
- data/ransack-4.4.1/spec/polyamorous/activerecord_compatibility_spec.rb +15 -0
- data/ransack-4.4.1/spec/polyamorous/join_association_spec.rb +29 -0
- data/ransack-4.4.1/spec/polyamorous/join_dependency_spec.rb +80 -0
- data/ransack-4.4.1/spec/polyamorous/join_spec.rb +19 -0
- data/ransack-4.4.1/spec/ransack/adapters/active_record/base_spec.rb +943 -0
- data/ransack-4.4.1/spec/ransack/adapters/active_record/context_spec.rb +219 -0
- data/ransack-4.4.1/spec/ransack/configuration_spec.rb +201 -0
- data/ransack-4.4.1/spec/ransack/helpers/form_builder_spec.rb +169 -0
- data/ransack-4.4.1/spec/ransack/helpers/form_helper_spec.rb +1075 -0
- data/ransack-4.4.1/spec/ransack/invalid_search_error_spec.rb +27 -0
- data/ransack-4.4.1/spec/ransack/nodes/condition_spec.rb +333 -0
- data/ransack-4.4.1/spec/ransack/nodes/grouping_spec.rb +111 -0
- data/ransack-4.4.1/spec/ransack/nodes/value_spec.rb +126 -0
- data/ransack-4.4.1/spec/ransack/predicate_spec.rb +504 -0
- data/ransack-4.4.1/spec/ransack/ransacker_spec.rb +69 -0
- data/ransack-4.4.1/spec/ransack/search_spec.rb +821 -0
- data/ransack-4.4.1/spec/ransack/translate_spec.rb +16 -0
- data/ransack-4.4.1/spec/spec_helper.rb +52 -0
- data/ransack-4.4.1/spec/support/en.yml +18 -0
- data/ransack-4.4.1/spec/support/schema.rb +419 -0
- metadata +133 -0
|
@@ -0,0 +1,209 @@
|
|
|
1
|
+
require 'ransack/constants'
|
|
2
|
+
require 'ransack/predicate'
|
|
3
|
+
|
|
4
|
+
module Ransack
|
|
5
|
+
module Configuration
|
|
6
|
+
|
|
7
|
+
mattr_accessor :predicates, :options
|
|
8
|
+
|
|
9
|
+
class PredicateCollection
|
|
10
|
+
attr_reader :sorted_names_with_underscores
|
|
11
|
+
|
|
12
|
+
def initialize
|
|
13
|
+
@collection = {}
|
|
14
|
+
@sorted_names_with_underscores = []
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
delegate :[], :keys, :has_key?, to: :@collection
|
|
18
|
+
|
|
19
|
+
def []=(key, value)
|
|
20
|
+
@sorted_names_with_underscores << [key, '_' + key]
|
|
21
|
+
@sorted_names_with_underscores.sort! { |(a, _), (b, _)| b.length <=> a.length }
|
|
22
|
+
|
|
23
|
+
@collection[key] = value
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
self.predicates = PredicateCollection.new
|
|
28
|
+
|
|
29
|
+
self.options = {
|
|
30
|
+
search_key: :q,
|
|
31
|
+
ignore_unknown_conditions: true,
|
|
32
|
+
hide_sort_order_indicators: false,
|
|
33
|
+
up_arrow: '▼'.freeze,
|
|
34
|
+
down_arrow: '▲'.freeze,
|
|
35
|
+
default_arrow: nil,
|
|
36
|
+
sanitize_scope_args: true,
|
|
37
|
+
postgres_fields_sort_option: nil,
|
|
38
|
+
strip_whitespace: true
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
def configure
|
|
42
|
+
yield self
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
def add_predicate(name, opts = {})
|
|
46
|
+
name = name.to_s
|
|
47
|
+
opts[:name] = name
|
|
48
|
+
compounds = opts.delete(:compounds)
|
|
49
|
+
compounds = true if compounds.nil?
|
|
50
|
+
compounds = false if opts[:wants_array]
|
|
51
|
+
|
|
52
|
+
self.predicates[name] = Predicate.new(opts)
|
|
53
|
+
|
|
54
|
+
Constants::SUFFIXES.each do |suffix|
|
|
55
|
+
compound_name = name + suffix
|
|
56
|
+
self.predicates[compound_name] = Predicate.new(
|
|
57
|
+
opts.merge(
|
|
58
|
+
name: compound_name,
|
|
59
|
+
arel_predicate: arel_predicate_with_suffix(
|
|
60
|
+
opts[:arel_predicate], suffix
|
|
61
|
+
),
|
|
62
|
+
compound: true
|
|
63
|
+
)
|
|
64
|
+
)
|
|
65
|
+
end if compounds
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
# The default `search_key` name is `:q`. The default key may be overridden
|
|
69
|
+
# in an initializer file like `config/initializers/ransack.rb` as follows:
|
|
70
|
+
#
|
|
71
|
+
# Ransack.configure do |config|
|
|
72
|
+
# # Name the search_key `:query` instead of the default `:q`
|
|
73
|
+
# config.search_key = :query
|
|
74
|
+
# end
|
|
75
|
+
#
|
|
76
|
+
# Sometimes there are situations when the default search parameter name
|
|
77
|
+
# cannot be used, for instance if there were two searches on one page.
|
|
78
|
+
# Another name can be set using the `search_key` option with Ransack
|
|
79
|
+
# `ransack`, `search` and `@search_form_for` methods in controllers & views.
|
|
80
|
+
#
|
|
81
|
+
# In the controller:
|
|
82
|
+
# @search = Log.ransack(params[:log_search], search_key: :log_search)
|
|
83
|
+
#
|
|
84
|
+
# In the view:
|
|
85
|
+
# <%= f.search_form_for @search, as: :log_search %>
|
|
86
|
+
#
|
|
87
|
+
def search_key=(name)
|
|
88
|
+
self.options[:search_key] = name
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
# By default Ransack ignores errors if an unknown predicate, condition or
|
|
92
|
+
# attribute is passed into a search. The default may be overridden in an
|
|
93
|
+
# initializer file like `config/initializers/ransack.rb` as follows:
|
|
94
|
+
#
|
|
95
|
+
# Ransack.configure do |config|
|
|
96
|
+
# # Raise if an unknown predicate, condition or attribute is passed
|
|
97
|
+
# config.ignore_unknown_conditions = false
|
|
98
|
+
# end
|
|
99
|
+
#
|
|
100
|
+
def ignore_unknown_conditions=(boolean)
|
|
101
|
+
self.options[:ignore_unknown_conditions] = boolean
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
# By default Ransack ignores empty predicates. Ransack can also fallback to
|
|
105
|
+
# a default predicate by setting it in an initializer file
|
|
106
|
+
# like `config/initializers/ransack.rb` as follows:
|
|
107
|
+
#
|
|
108
|
+
# Ransack.configure do |config|
|
|
109
|
+
# # Use the 'eq' predicate if an unknown predicate is passed
|
|
110
|
+
# config.default_predicate = 'eq'
|
|
111
|
+
# end
|
|
112
|
+
#
|
|
113
|
+
def default_predicate=(name)
|
|
114
|
+
self.options[:default_predicate] = name
|
|
115
|
+
end
|
|
116
|
+
|
|
117
|
+
# By default, Ransack displays sort order indicator arrows with HTML codes:
|
|
118
|
+
#
|
|
119
|
+
# up_arrow: '▼'
|
|
120
|
+
# down_arrow: '▲'
|
|
121
|
+
#
|
|
122
|
+
# There is also a default arrow which is displayed if a column is not sorted.
|
|
123
|
+
# By default this is nil so nothing will be displayed.
|
|
124
|
+
#
|
|
125
|
+
# Any of the defaults may be globally overridden in an initializer file
|
|
126
|
+
# like `config/initializers/ransack.rb` as follows:
|
|
127
|
+
#
|
|
128
|
+
# Ransack.configure do |config|
|
|
129
|
+
# # Globally set the up arrow to an icon, and the down and default arrows to unicode.
|
|
130
|
+
# config.custom_arrows = {
|
|
131
|
+
# up_arrow: '<i class="fa fa-long-arrow-up"></i>',
|
|
132
|
+
# down_arrow: 'U+02193',
|
|
133
|
+
# default_arrow: 'U+11047'
|
|
134
|
+
# }
|
|
135
|
+
# end
|
|
136
|
+
#
|
|
137
|
+
def custom_arrows=(opts = {})
|
|
138
|
+
self.options[:up_arrow] = opts[:up_arrow].freeze if opts[:up_arrow]
|
|
139
|
+
self.options[:down_arrow] = opts[:down_arrow].freeze if opts[:down_arrow]
|
|
140
|
+
self.options[:default_arrow] = opts[:default_arrow].freeze if opts[:default_arrow]
|
|
141
|
+
end
|
|
142
|
+
|
|
143
|
+
# Ransack sanitizes many values in your custom scopes into booleans.
|
|
144
|
+
# [1, '1', 't', 'T', 'true', 'TRUE'] all evaluate to true.
|
|
145
|
+
# [0, '0', 'f', 'F', 'false', 'FALSE'] all evaluate to false.
|
|
146
|
+
#
|
|
147
|
+
# This default may be globally overridden in an initializer file like
|
|
148
|
+
# `config/initializers/ransack.rb` as follows:
|
|
149
|
+
#
|
|
150
|
+
# Ransack.configure do |config|
|
|
151
|
+
# # Accept my custom scope values as what they are.
|
|
152
|
+
# config.sanitize_custom_scope_booleans = false
|
|
153
|
+
# end
|
|
154
|
+
#
|
|
155
|
+
def sanitize_custom_scope_booleans=(boolean)
|
|
156
|
+
self.options[:sanitize_scope_args] = boolean
|
|
157
|
+
end
|
|
158
|
+
|
|
159
|
+
# The `NULLS FIRST` and `NULLS LAST` options can be used to determine
|
|
160
|
+
# whether nulls appear before or after non-null values in the sort ordering.
|
|
161
|
+
#
|
|
162
|
+
# User may want to configure it like this:
|
|
163
|
+
#
|
|
164
|
+
# Ransack.configure do |c|
|
|
165
|
+
# c.postgres_fields_sort_option = :nulls_first # or e.g. :nulls_always_last
|
|
166
|
+
# end
|
|
167
|
+
#
|
|
168
|
+
# See this feature: https://www.postgresql.org/docs/13/queries-order.html
|
|
169
|
+
#
|
|
170
|
+
def postgres_fields_sort_option=(setting)
|
|
171
|
+
self.options[:postgres_fields_sort_option] = setting
|
|
172
|
+
end
|
|
173
|
+
|
|
174
|
+
# By default, Ransack displays sort order indicator arrows in sort links.
|
|
175
|
+
# The default may be globally overridden in an initializer file like
|
|
176
|
+
# `config/initializers/ransack.rb` as follows:
|
|
177
|
+
#
|
|
178
|
+
# Ransack.configure do |config|
|
|
179
|
+
# # Hide sort link order indicators globally across the application
|
|
180
|
+
# config.hide_sort_order_indicators = true
|
|
181
|
+
# end
|
|
182
|
+
#
|
|
183
|
+
def hide_sort_order_indicators=(boolean)
|
|
184
|
+
self.options[:hide_sort_order_indicators] = boolean
|
|
185
|
+
end
|
|
186
|
+
|
|
187
|
+
# By default, Ransack displays strips all whitespace when searching for a string.
|
|
188
|
+
# The default may be globally changed in an initializer file like
|
|
189
|
+
# `config/initializers/ransack.rb` as follows:
|
|
190
|
+
#
|
|
191
|
+
# Ransack.configure do |config|
|
|
192
|
+
# # Enable whitespace stripping for string searches
|
|
193
|
+
# config.strip_whitespace = true
|
|
194
|
+
# end
|
|
195
|
+
#
|
|
196
|
+
def strip_whitespace=(boolean)
|
|
197
|
+
self.options[:strip_whitespace] = boolean
|
|
198
|
+
end
|
|
199
|
+
|
|
200
|
+
def arel_predicate_with_suffix(arel_predicate, suffix)
|
|
201
|
+
if arel_predicate === Proc
|
|
202
|
+
proc { |v| "#{arel_predicate.call(v)}#{suffix}" }
|
|
203
|
+
else
|
|
204
|
+
"#{arel_predicate}#{suffix}"
|
|
205
|
+
end
|
|
206
|
+
end
|
|
207
|
+
|
|
208
|
+
end
|
|
209
|
+
end
|
|
@@ -0,0 +1,176 @@
|
|
|
1
|
+
module Ransack
|
|
2
|
+
module Constants
|
|
3
|
+
OR = 'or'.freeze
|
|
4
|
+
AND = 'and'.freeze
|
|
5
|
+
|
|
6
|
+
CAP_SEARCH = 'Search'.freeze
|
|
7
|
+
SEARCH = 'search'.freeze
|
|
8
|
+
SEARCHES = 'searches'.freeze
|
|
9
|
+
|
|
10
|
+
ATTRIBUTE = 'attribute'.freeze
|
|
11
|
+
ATTRIBUTES = 'attributes'.freeze
|
|
12
|
+
COMBINATOR = 'combinator'.freeze
|
|
13
|
+
|
|
14
|
+
TWO_COLONS = '::'.freeze
|
|
15
|
+
UNDERSCORE = '_'.freeze
|
|
16
|
+
LEFT_PARENTHESIS = '('.freeze
|
|
17
|
+
Q = 'q'.freeze
|
|
18
|
+
I = 'i'.freeze
|
|
19
|
+
DOT_ASTERIX = '.*'.freeze
|
|
20
|
+
|
|
21
|
+
STRING_JOIN = 'string_join'.freeze
|
|
22
|
+
ASSOCIATION_JOIN = 'association_join'.freeze
|
|
23
|
+
STASHED_JOIN = 'stashed_join'.freeze
|
|
24
|
+
JOIN_NODE = 'join_node'.freeze
|
|
25
|
+
|
|
26
|
+
TRUE_VALUES = [true, 1, '1', 't', 'T', 'true', 'TRUE'].to_set
|
|
27
|
+
FALSE_VALUES = [false, 0, '0', 'f', 'F', 'false', 'FALSE'].to_set
|
|
28
|
+
BOOLEAN_VALUES = (TRUE_VALUES + FALSE_VALUES).freeze
|
|
29
|
+
|
|
30
|
+
AND_OR = ['and'.freeze, 'or'.freeze].freeze
|
|
31
|
+
IN_NOT_IN = ['in'.freeze, 'not_in'.freeze].freeze
|
|
32
|
+
SUFFIXES = ['_any'.freeze, '_all'.freeze].freeze
|
|
33
|
+
AREL_PREDICATES = [
|
|
34
|
+
'eq'.freeze, 'not_eq'.freeze,
|
|
35
|
+
'matches'.freeze, 'does_not_match'.freeze,
|
|
36
|
+
'lt'.freeze, 'lteq'.freeze,
|
|
37
|
+
'gt'.freeze, 'gteq'.freeze,
|
|
38
|
+
'in'.freeze, 'not_in'.freeze
|
|
39
|
+
].freeze
|
|
40
|
+
A_S_I = ['a'.freeze, 's'.freeze, 'i'.freeze].freeze
|
|
41
|
+
|
|
42
|
+
EQ = 'eq'.freeze
|
|
43
|
+
NOT_EQ = 'not_eq'.freeze
|
|
44
|
+
EQ_ANY = 'eq_any'.freeze
|
|
45
|
+
NOT_EQ_ALL = 'not_eq_all'.freeze
|
|
46
|
+
CONT = 'cont'.freeze
|
|
47
|
+
|
|
48
|
+
RANSACK_SLASH_SEARCHES = 'ransack/searches'.freeze
|
|
49
|
+
RANSACK_SLASH_SEARCHES_SLASH_SEARCH = 'ransack/searches/search'.freeze
|
|
50
|
+
|
|
51
|
+
DISTINCT = 'DISTINCT '.freeze
|
|
52
|
+
|
|
53
|
+
DERIVED_PREDICATES = [
|
|
54
|
+
[CONT, {
|
|
55
|
+
arel_predicate: 'matches'.freeze,
|
|
56
|
+
formatter: proc { |v| "%#{escape_wildcards(v)}%" }
|
|
57
|
+
}
|
|
58
|
+
],
|
|
59
|
+
['not_cont'.freeze, {
|
|
60
|
+
arel_predicate: 'does_not_match'.freeze,
|
|
61
|
+
formatter: proc { |v| "%#{escape_wildcards(v)}%" }
|
|
62
|
+
}
|
|
63
|
+
],
|
|
64
|
+
['i_cont'.freeze, {
|
|
65
|
+
arel_predicate: 'matches'.freeze,
|
|
66
|
+
formatter: proc { |v| "%#{escape_wildcards(v.downcase)}%" },
|
|
67
|
+
case_insensitive: true
|
|
68
|
+
}
|
|
69
|
+
],
|
|
70
|
+
['not_i_cont'.freeze, {
|
|
71
|
+
arel_predicate: 'does_not_match'.freeze,
|
|
72
|
+
formatter: proc { |v| "%#{escape_wildcards(v.downcase)}%" },
|
|
73
|
+
case_insensitive: true
|
|
74
|
+
}
|
|
75
|
+
],
|
|
76
|
+
['start'.freeze, {
|
|
77
|
+
arel_predicate: 'matches'.freeze,
|
|
78
|
+
formatter: proc { |v| "#{escape_wildcards(v)}%" }
|
|
79
|
+
}
|
|
80
|
+
],
|
|
81
|
+
['not_start'.freeze, {
|
|
82
|
+
arel_predicate: 'does_not_match'.freeze,
|
|
83
|
+
formatter: proc { |v| "#{escape_wildcards(v)}%" }
|
|
84
|
+
}
|
|
85
|
+
],
|
|
86
|
+
['end'.freeze, {
|
|
87
|
+
arel_predicate: 'matches'.freeze,
|
|
88
|
+
formatter: proc { |v| "%#{escape_wildcards(v)}" }
|
|
89
|
+
}
|
|
90
|
+
],
|
|
91
|
+
['not_end'.freeze, {
|
|
92
|
+
arel_predicate: 'does_not_match'.freeze,
|
|
93
|
+
formatter: proc { |v| "%#{escape_wildcards(v)}" }
|
|
94
|
+
}
|
|
95
|
+
],
|
|
96
|
+
['true'.freeze, {
|
|
97
|
+
arel_predicate: proc { |v| v ? EQ : NOT_EQ },
|
|
98
|
+
compounds: false,
|
|
99
|
+
type: :boolean,
|
|
100
|
+
validator: proc { |v| BOOLEAN_VALUES.include?(v) },
|
|
101
|
+
formatter: proc { |v| true }
|
|
102
|
+
}
|
|
103
|
+
],
|
|
104
|
+
['not_true'.freeze, {
|
|
105
|
+
arel_predicate: proc { |v| v ? NOT_EQ : EQ },
|
|
106
|
+
compounds: false,
|
|
107
|
+
type: :boolean,
|
|
108
|
+
validator: proc { |v| BOOLEAN_VALUES.include?(v) },
|
|
109
|
+
formatter: proc { |v| true }
|
|
110
|
+
}
|
|
111
|
+
],
|
|
112
|
+
['false'.freeze, {
|
|
113
|
+
arel_predicate: proc { |v| v ? EQ : NOT_EQ },
|
|
114
|
+
compounds: false,
|
|
115
|
+
type: :boolean,
|
|
116
|
+
validator: proc { |v| BOOLEAN_VALUES.include?(v) },
|
|
117
|
+
formatter: proc { |v| false }
|
|
118
|
+
}
|
|
119
|
+
],
|
|
120
|
+
['not_false'.freeze, {
|
|
121
|
+
arel_predicate: proc { |v| v ? NOT_EQ : EQ },
|
|
122
|
+
compounds: false,
|
|
123
|
+
type: :boolean,
|
|
124
|
+
validator: proc { |v| BOOLEAN_VALUES.include?(v) },
|
|
125
|
+
formatter: proc { |v| false }
|
|
126
|
+
}
|
|
127
|
+
],
|
|
128
|
+
['present'.freeze, {
|
|
129
|
+
arel_predicate: proc { |v| v ? NOT_EQ_ALL : EQ_ANY },
|
|
130
|
+
compounds: false,
|
|
131
|
+
type: :boolean,
|
|
132
|
+
validator: proc { |v| BOOLEAN_VALUES.include?(v) },
|
|
133
|
+
formatter: proc { |v| [nil, ''.freeze].freeze }
|
|
134
|
+
}
|
|
135
|
+
],
|
|
136
|
+
['blank'.freeze, {
|
|
137
|
+
arel_predicate: proc { |v| v ? EQ_ANY : NOT_EQ_ALL },
|
|
138
|
+
compounds: false,
|
|
139
|
+
type: :boolean,
|
|
140
|
+
validator: proc { |v| BOOLEAN_VALUES.include?(v) },
|
|
141
|
+
formatter: proc { |v| [nil, ''.freeze].freeze }
|
|
142
|
+
}
|
|
143
|
+
],
|
|
144
|
+
['null'.freeze, {
|
|
145
|
+
arel_predicate: proc { |v| v ? EQ : NOT_EQ },
|
|
146
|
+
compounds: false,
|
|
147
|
+
type: :boolean,
|
|
148
|
+
validator: proc { |v| BOOLEAN_VALUES.include?(v) },
|
|
149
|
+
formatter: proc { |v| nil }
|
|
150
|
+
}
|
|
151
|
+
],
|
|
152
|
+
['not_null'.freeze, {
|
|
153
|
+
arel_predicate: proc { |v| v ? NOT_EQ : EQ },
|
|
154
|
+
compounds: false,
|
|
155
|
+
type: :boolean,
|
|
156
|
+
validator: proc { |v| BOOLEAN_VALUES.include?(v) },
|
|
157
|
+
formatter: proc { |v| nil } }
|
|
158
|
+
]
|
|
159
|
+
].freeze
|
|
160
|
+
|
|
161
|
+
module_function
|
|
162
|
+
# replace % \ to \% \\
|
|
163
|
+
def escape_wildcards(unescaped)
|
|
164
|
+
case ActiveRecord::Base.connection.adapter_name
|
|
165
|
+
when "Mysql2".freeze
|
|
166
|
+
# Necessary for MySQL
|
|
167
|
+
unescaped.to_s.gsub(/([\\%_])/, '\\\\\\1')
|
|
168
|
+
when "PostGIS".freeze, "PostgreSQL".freeze
|
|
169
|
+
# Necessary for PostgreSQL
|
|
170
|
+
unescaped.to_s.gsub(/([\\%_.])/, '\\\\\\1')
|
|
171
|
+
else
|
|
172
|
+
unescaped
|
|
173
|
+
end
|
|
174
|
+
end
|
|
175
|
+
end
|
|
176
|
+
end
|
|
@@ -0,0 +1,190 @@
|
|
|
1
|
+
require 'ransack/visitor'
|
|
2
|
+
|
|
3
|
+
module Ransack
|
|
4
|
+
class Context
|
|
5
|
+
attr_reader :search, :object, :klass, :base, :engine, :arel_visitor
|
|
6
|
+
attr_accessor :auth_object, :search_key
|
|
7
|
+
attr_reader :arel_visitor
|
|
8
|
+
|
|
9
|
+
class << self
|
|
10
|
+
|
|
11
|
+
def for_class(klass, options = {})
|
|
12
|
+
if klass < ActiveRecord::Base
|
|
13
|
+
Adapters::ActiveRecord::Context.new(klass, options)
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def for_object(object, options = {})
|
|
18
|
+
case object
|
|
19
|
+
when ActiveRecord::Relation
|
|
20
|
+
Adapters::ActiveRecord::Context.new(object.klass, options)
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def for(object, options = {})
|
|
25
|
+
context =
|
|
26
|
+
if Class === object
|
|
27
|
+
for_class(object, options)
|
|
28
|
+
else
|
|
29
|
+
for_object(object, options)
|
|
30
|
+
end
|
|
31
|
+
context or raise ArgumentError,
|
|
32
|
+
"Don't know what context to use for #{object}"
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
end # << self
|
|
36
|
+
|
|
37
|
+
def initialize(object, options = {})
|
|
38
|
+
@object = relation_for(object)
|
|
39
|
+
@klass = @object.klass
|
|
40
|
+
@join_dependency = join_dependency(@object)
|
|
41
|
+
@join_type = options[:join_type] || Polyamorous::OuterJoin
|
|
42
|
+
@search_key = options[:search_key] || Ransack.options[:search_key]
|
|
43
|
+
@associations_pot = {}
|
|
44
|
+
@tables_pot = {}
|
|
45
|
+
@lock_associations = []
|
|
46
|
+
|
|
47
|
+
@base = @join_dependency.instance_variable_get(:@join_root)
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
def bind_pair_for(key)
|
|
51
|
+
@bind_pairs ||= {}
|
|
52
|
+
|
|
53
|
+
@bind_pairs[key] ||= begin
|
|
54
|
+
parent, attr_name = get_parent_and_attribute_name(key.to_s)
|
|
55
|
+
[parent, attr_name] if parent && attr_name
|
|
56
|
+
end
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
def klassify(obj)
|
|
60
|
+
if Class === obj && ::ActiveRecord::Base > obj
|
|
61
|
+
obj
|
|
62
|
+
elsif obj.respond_to? :klass
|
|
63
|
+
obj.klass
|
|
64
|
+
else
|
|
65
|
+
raise ArgumentError, "Don't know how to klassify #{obj.inspect}"
|
|
66
|
+
end
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
# Convert a string representing a chain of associations and an attribute
|
|
70
|
+
# into the attribute itself
|
|
71
|
+
def contextualize(str)
|
|
72
|
+
parent, attr_name = bind_pair_for(str)
|
|
73
|
+
table_for(parent)[attr_name]
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
def chain_scope(scope, args)
|
|
77
|
+
return unless @klass.method(scope) && args != false
|
|
78
|
+
@object = if scope_arity(scope) < 1 && args == true
|
|
79
|
+
@object.public_send(scope)
|
|
80
|
+
elsif scope_arity(scope) == 1 && args.is_a?(Array)
|
|
81
|
+
# For scopes with arity 1, pass the array as a single argument instead of splatting
|
|
82
|
+
@object.public_send(scope, args)
|
|
83
|
+
else
|
|
84
|
+
@object.public_send(scope, *args)
|
|
85
|
+
end
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
def scope_arity(scope)
|
|
89
|
+
@klass.method(scope).arity
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
def bind(object, str)
|
|
93
|
+
return nil unless str
|
|
94
|
+
object.parent, object.attr_name = bind_pair_for(str)
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
def traverse(str, base = @base)
|
|
98
|
+
str ||= ''.freeze
|
|
99
|
+
segments = str.split(Constants::UNDERSCORE)
|
|
100
|
+
unless segments.empty?
|
|
101
|
+
remainder = []
|
|
102
|
+
found_assoc = nil
|
|
103
|
+
until found_assoc || segments.empty?
|
|
104
|
+
# Strip the _of_Model_type text from the association name, but hold
|
|
105
|
+
# onto it in klass, for use as the next base
|
|
106
|
+
assoc, klass = unpolymorphize_association(
|
|
107
|
+
segments.join(Constants::UNDERSCORE)
|
|
108
|
+
)
|
|
109
|
+
if found_assoc = get_association(assoc, base)
|
|
110
|
+
base = traverse(
|
|
111
|
+
remainder.join(Constants::UNDERSCORE), klass || found_assoc.klass
|
|
112
|
+
)
|
|
113
|
+
end
|
|
114
|
+
|
|
115
|
+
remainder.unshift segments.pop
|
|
116
|
+
end
|
|
117
|
+
unless found_assoc
|
|
118
|
+
raise(UntraversableAssociationError,
|
|
119
|
+
"No association matches #{str}")
|
|
120
|
+
end
|
|
121
|
+
end
|
|
122
|
+
|
|
123
|
+
klassify(base)
|
|
124
|
+
end
|
|
125
|
+
|
|
126
|
+
def association_path(str, base = @base)
|
|
127
|
+
base = klassify(base)
|
|
128
|
+
str ||= ''.freeze
|
|
129
|
+
path = []
|
|
130
|
+
segments = str.split(Constants::UNDERSCORE)
|
|
131
|
+
association_parts = []
|
|
132
|
+
unless segments.empty?
|
|
133
|
+
while !segments.empty? &&
|
|
134
|
+
!base.columns_hash[segments.join(Constants::UNDERSCORE)] &&
|
|
135
|
+
association_parts << segments.shift
|
|
136
|
+
assoc, klass = unpolymorphize_association(
|
|
137
|
+
association_parts.join(Constants::UNDERSCORE)
|
|
138
|
+
)
|
|
139
|
+
next unless found_assoc = get_association(assoc, base)
|
|
140
|
+
path += association_parts
|
|
141
|
+
association_parts = []
|
|
142
|
+
base = klassify(klass || found_assoc)
|
|
143
|
+
end
|
|
144
|
+
end
|
|
145
|
+
|
|
146
|
+
path.join(Constants::UNDERSCORE)
|
|
147
|
+
end
|
|
148
|
+
|
|
149
|
+
def unpolymorphize_association(str)
|
|
150
|
+
if (match = str.match(/_of_([^_]+?)_type$/))
|
|
151
|
+
[match.pre_match, Kernel.const_get(match.captures.first)]
|
|
152
|
+
else
|
|
153
|
+
[str, nil]
|
|
154
|
+
end
|
|
155
|
+
end
|
|
156
|
+
|
|
157
|
+
def ransackable_alias(str)
|
|
158
|
+
klass._ransack_aliases.fetch(str, klass._ransack_aliases.fetch(str.to_sym, str))
|
|
159
|
+
end
|
|
160
|
+
|
|
161
|
+
def ransackable_attribute?(str, klass)
|
|
162
|
+
klass.ransackable_attributes(auth_object).any? { |s| s.to_sym == str.to_sym } ||
|
|
163
|
+
klass.ransortable_attributes(auth_object).any? { |s| s.to_sym == str.to_sym }
|
|
164
|
+
end
|
|
165
|
+
|
|
166
|
+
def ransackable_association?(str, klass)
|
|
167
|
+
klass.ransackable_associations(auth_object).any? { |s| s.to_sym == str.to_sym }
|
|
168
|
+
end
|
|
169
|
+
|
|
170
|
+
def ransackable_scope?(str, klass)
|
|
171
|
+
klass.ransackable_scopes(auth_object).any? { |s| s.to_sym == str.to_sym }
|
|
172
|
+
end
|
|
173
|
+
|
|
174
|
+
def ransackable_scope_skip_sanitize_args?(str, klass)
|
|
175
|
+
klass.ransackable_scopes_skip_sanitize_args.any? { |s| s.to_sym == str.to_sym }
|
|
176
|
+
end
|
|
177
|
+
|
|
178
|
+
def searchable_attributes(str = ''.freeze)
|
|
179
|
+
traverse(str).ransackable_attributes(auth_object)
|
|
180
|
+
end
|
|
181
|
+
|
|
182
|
+
def sortable_attributes(str = ''.freeze)
|
|
183
|
+
traverse(str).ransortable_attributes(auth_object)
|
|
184
|
+
end
|
|
185
|
+
|
|
186
|
+
def searchable_associations(str = ''.freeze)
|
|
187
|
+
traverse(str).ransackable_associations(auth_object)
|
|
188
|
+
end
|
|
189
|
+
end
|
|
190
|
+
end
|