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,277 @@
|
|
|
1
|
+
require 'action_view'
|
|
2
|
+
|
|
3
|
+
module ActionView::Helpers::Tags
|
|
4
|
+
# TODO: Find a better way to solve this issue!
|
|
5
|
+
# This patch is needed since this Rails commit:
|
|
6
|
+
# https://github.com/rails/rails/commit/c1a118a
|
|
7
|
+
class Base
|
|
8
|
+
private
|
|
9
|
+
|
|
10
|
+
def value
|
|
11
|
+
if @allow_method_names_outside_object
|
|
12
|
+
object.send @method_name if object && object.respond_to?(@method_name, true)
|
|
13
|
+
else
|
|
14
|
+
object.send @method_name if object
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
RANSACK_FORM_BUILDER = 'RANSACK_FORM_BUILDER'.freeze
|
|
21
|
+
|
|
22
|
+
require 'simple_form' if
|
|
23
|
+
(ENV[RANSACK_FORM_BUILDER] || ''.freeze).match('SimpleForm'.freeze)
|
|
24
|
+
|
|
25
|
+
module Ransack
|
|
26
|
+
module Helpers
|
|
27
|
+
class FormBuilder < (ENV[RANSACK_FORM_BUILDER].try(:constantize) ||
|
|
28
|
+
ActionView::Helpers::FormBuilder)
|
|
29
|
+
|
|
30
|
+
def label(method, *args, &block)
|
|
31
|
+
options = args.extract_options!
|
|
32
|
+
text = args.first
|
|
33
|
+
i18n = options[:i18n] || {}
|
|
34
|
+
text ||= object.translate(
|
|
35
|
+
method, i18n.reverse_merge(include_associations: true)
|
|
36
|
+
) if object.respond_to? :translate
|
|
37
|
+
super(method, text, options, &block)
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
def submit(value = nil, options = {})
|
|
41
|
+
value, options = nil, value if value.is_a?(Hash)
|
|
42
|
+
value ||= Translate.word(:search).titleize
|
|
43
|
+
super(value, options)
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
def attribute_select(options = nil, html_options = nil, action = nil)
|
|
47
|
+
options ||= {}
|
|
48
|
+
html_options ||= {}
|
|
49
|
+
action ||= Constants::SEARCH
|
|
50
|
+
default = options.delete(:default)
|
|
51
|
+
raise ArgumentError, formbuilder_error_message(
|
|
52
|
+
"#{action}_select") unless object.respond_to?(:context)
|
|
53
|
+
options[:include_blank] = true unless options.has_key?(:include_blank)
|
|
54
|
+
bases = [''.freeze].freeze + association_array(options[:associations])
|
|
55
|
+
if bases.size > 1
|
|
56
|
+
collection = attribute_collection_for_bases(action, bases)
|
|
57
|
+
object.name ||= default if can_use_default?(
|
|
58
|
+
default, :name, mapped_values(collection.flatten(2))
|
|
59
|
+
)
|
|
60
|
+
template_grouped_collection_select(collection, options, html_options)
|
|
61
|
+
else
|
|
62
|
+
collection = collection_for_base(action, bases.first)
|
|
63
|
+
object.name ||= default if can_use_default?(
|
|
64
|
+
default, :name, mapped_values(collection)
|
|
65
|
+
)
|
|
66
|
+
template_collection_select(:name, collection, options, html_options)
|
|
67
|
+
end
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
def sort_direction_select(options = {}, html_options = {})
|
|
71
|
+
unless object.respond_to?(:context)
|
|
72
|
+
raise ArgumentError,
|
|
73
|
+
formbuilder_error_message('sort_direction'.freeze)
|
|
74
|
+
end
|
|
75
|
+
template_collection_select(:dir, sort_array, options, html_options)
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
def sort_select(options = {}, html_options = {})
|
|
79
|
+
attribute_select(options, html_options, 'sort'.freeze) +
|
|
80
|
+
sort_direction_select(options, html_options)
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
def sort_fields(*args, &block)
|
|
84
|
+
search_fields(:s, args, block)
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
def sort_link(attribute, *args)
|
|
88
|
+
@template.sort_link @object, attribute, *args
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
def sort_url(attribute, *args)
|
|
92
|
+
@template.sort_url @object, attribute, *args
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
def condition_fields(*args, &block)
|
|
96
|
+
search_fields(:c, args, block)
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
def grouping_fields(*args, &block)
|
|
100
|
+
search_fields(:g, args, block)
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
def attribute_fields(*args, &block)
|
|
104
|
+
search_fields(:a, args, block)
|
|
105
|
+
end
|
|
106
|
+
|
|
107
|
+
def predicate_fields(*args, &block)
|
|
108
|
+
search_fields(:p, args, block)
|
|
109
|
+
end
|
|
110
|
+
|
|
111
|
+
def value_fields(*args, &block)
|
|
112
|
+
search_fields(:v, args, block)
|
|
113
|
+
end
|
|
114
|
+
|
|
115
|
+
def search_fields(name, args, block)
|
|
116
|
+
args << {} unless args.last.is_a?(Hash)
|
|
117
|
+
args.last[:builder] ||= options[:builder]
|
|
118
|
+
args.last[:parent_builder] = self
|
|
119
|
+
options = args.extract_options!
|
|
120
|
+
objects = args.shift
|
|
121
|
+
objects ||= @object.send(name)
|
|
122
|
+
objects = [objects] unless Array === objects
|
|
123
|
+
name = "#{options[:object_name] || object_name}[#{name}]"
|
|
124
|
+
objects.inject(ActiveSupport::SafeBuffer.new) do |output, child|
|
|
125
|
+
output << @template.fields_for("#{name}[#{options[:child_index] ||
|
|
126
|
+
nested_child_index(name)}]", child, options, &block)
|
|
127
|
+
end
|
|
128
|
+
end
|
|
129
|
+
|
|
130
|
+
def predicate_select(options = {}, html_options = {})
|
|
131
|
+
options[:compounds] = true if options[:compounds].nil?
|
|
132
|
+
default = options.delete(:default) || Constants::CONT
|
|
133
|
+
|
|
134
|
+
keys =
|
|
135
|
+
if options[:compounds]
|
|
136
|
+
Predicate.names
|
|
137
|
+
else
|
|
138
|
+
Predicate.names.reject { |k| k.match(/_(any|all)$/) }
|
|
139
|
+
end
|
|
140
|
+
if only = options[:only]
|
|
141
|
+
if only.respond_to? :call
|
|
142
|
+
keys = keys.select { |k| only.call(k) }
|
|
143
|
+
else
|
|
144
|
+
only = Array.wrap(only).map(&:to_s)
|
|
145
|
+
keys = keys.select {
|
|
146
|
+
|k| only.include? k.sub(/_(any|all)$/, ''.freeze)
|
|
147
|
+
}
|
|
148
|
+
end
|
|
149
|
+
end
|
|
150
|
+
collection = keys.map { |k| [k, Translate.predicate(k)] }
|
|
151
|
+
object.predicate ||= Predicate.named(default) if
|
|
152
|
+
can_use_default?(default, :predicate, keys)
|
|
153
|
+
template_collection_select(:p, collection, options, html_options)
|
|
154
|
+
end
|
|
155
|
+
|
|
156
|
+
def combinator_select(options = {}, html_options = {})
|
|
157
|
+
template_collection_select(
|
|
158
|
+
:m, combinator_choices, options, html_options)
|
|
159
|
+
end
|
|
160
|
+
|
|
161
|
+
private
|
|
162
|
+
|
|
163
|
+
def template_grouped_collection_select(collection, options, html_options)
|
|
164
|
+
@template.grouped_collection_select(
|
|
165
|
+
@object_name, :name, collection, :last, :first, :first, :last,
|
|
166
|
+
objectify_options(options), @default_options.merge(html_options)
|
|
167
|
+
)
|
|
168
|
+
end
|
|
169
|
+
|
|
170
|
+
def template_collection_select(name, collection, options, html_options)
|
|
171
|
+
@template.collection_select(
|
|
172
|
+
@object_name, name, collection, :first, :last,
|
|
173
|
+
objectify_options(options), @default_options.merge(html_options)
|
|
174
|
+
)
|
|
175
|
+
end
|
|
176
|
+
|
|
177
|
+
def can_use_default?(default, attribute, values)
|
|
178
|
+
object.respond_to?("#{attribute}=") && default &&
|
|
179
|
+
values.include?(default.to_s)
|
|
180
|
+
end
|
|
181
|
+
|
|
182
|
+
def mapped_values(values)
|
|
183
|
+
values.map { |v| v.is_a?(Array) ? v.first : nil }.compact
|
|
184
|
+
end
|
|
185
|
+
|
|
186
|
+
def sort_array
|
|
187
|
+
[
|
|
188
|
+
['asc'.freeze, object.translate('asc'.freeze)].freeze,
|
|
189
|
+
['desc'.freeze, object.translate('desc'.freeze)].freeze
|
|
190
|
+
].freeze
|
|
191
|
+
end
|
|
192
|
+
|
|
193
|
+
def combinator_choices
|
|
194
|
+
if Nodes::Condition === object
|
|
195
|
+
[
|
|
196
|
+
[Constants::OR, Translate.word(:any)],
|
|
197
|
+
[Constants::AND, Translate.word(:all)]
|
|
198
|
+
]
|
|
199
|
+
else
|
|
200
|
+
[
|
|
201
|
+
[Constants::AND, Translate.word(:all)],
|
|
202
|
+
[Constants::OR, Translate.word(:any)]
|
|
203
|
+
]
|
|
204
|
+
end
|
|
205
|
+
end
|
|
206
|
+
|
|
207
|
+
def association_array(obj, prefix = nil)
|
|
208
|
+
([prefix] + association_object(obj))
|
|
209
|
+
.compact
|
|
210
|
+
.flat_map { |v| [prefix, v].compact.join(Constants::UNDERSCORE) }
|
|
211
|
+
end
|
|
212
|
+
|
|
213
|
+
def association_object(obj)
|
|
214
|
+
case obj
|
|
215
|
+
when Array
|
|
216
|
+
obj
|
|
217
|
+
when Hash
|
|
218
|
+
association_hash(obj)
|
|
219
|
+
else
|
|
220
|
+
[obj]
|
|
221
|
+
end
|
|
222
|
+
end
|
|
223
|
+
|
|
224
|
+
def association_hash(obj)
|
|
225
|
+
obj.map do |key, value|
|
|
226
|
+
case value
|
|
227
|
+
when Array, Hash
|
|
228
|
+
association_array(value, key.to_s)
|
|
229
|
+
else
|
|
230
|
+
[key.to_s, [key, value].join(Constants::UNDERSCORE)]
|
|
231
|
+
end
|
|
232
|
+
end
|
|
233
|
+
end
|
|
234
|
+
|
|
235
|
+
def attribute_collection_for_bases(action, bases)
|
|
236
|
+
bases.map { |base| get_attribute_element(action, base) }.compact
|
|
237
|
+
end
|
|
238
|
+
|
|
239
|
+
def get_attribute_element(action, base)
|
|
240
|
+
begin
|
|
241
|
+
[
|
|
242
|
+
Translate.association(base, context: object.context),
|
|
243
|
+
collection_for_base(action, base)
|
|
244
|
+
]
|
|
245
|
+
rescue UntraversableAssociationError
|
|
246
|
+
nil
|
|
247
|
+
end
|
|
248
|
+
end
|
|
249
|
+
|
|
250
|
+
def attribute_collection_for_base(attributes, base = nil)
|
|
251
|
+
attributes.map do |c|
|
|
252
|
+
[
|
|
253
|
+
attr_from_base_and_column(base, c),
|
|
254
|
+
Translate.attribute(
|
|
255
|
+
attr_from_base_and_column(base, c), context: object.context
|
|
256
|
+
)
|
|
257
|
+
]
|
|
258
|
+
end
|
|
259
|
+
end
|
|
260
|
+
|
|
261
|
+
def collection_for_base(action, base)
|
|
262
|
+
attribute_collection_for_base(
|
|
263
|
+
object.context.send("#{action}able_attributes", base), base)
|
|
264
|
+
end
|
|
265
|
+
|
|
266
|
+
def attr_from_base_and_column(base, column)
|
|
267
|
+
[base, column].reject(&:blank?).join(Constants::UNDERSCORE)
|
|
268
|
+
end
|
|
269
|
+
|
|
270
|
+
def formbuilder_error_message(action)
|
|
271
|
+
"#{action.sub(Constants::SEARCH, Constants::ATTRIBUTE)
|
|
272
|
+
} must be called inside a search FormBuilder!"
|
|
273
|
+
end
|
|
274
|
+
|
|
275
|
+
end
|
|
276
|
+
end
|
|
277
|
+
end
|
|
@@ -0,0 +1,311 @@
|
|
|
1
|
+
module Ransack
|
|
2
|
+
module Helpers
|
|
3
|
+
module FormHelper
|
|
4
|
+
|
|
5
|
+
# +search_form_for+
|
|
6
|
+
#
|
|
7
|
+
# <%= search_form_for(@q) do |f| %>
|
|
8
|
+
#
|
|
9
|
+
def search_form_for(record, options = {}, &proc)
|
|
10
|
+
search = extract_search_and_set_url(record, options, 'search_form_for')
|
|
11
|
+
options[:html] ||= {}
|
|
12
|
+
html_options = build_html_options(search, options, :get)
|
|
13
|
+
finalize_form_options(options, html_options)
|
|
14
|
+
form_for(record, options, &proc)
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
# +search_form_with+
|
|
18
|
+
#
|
|
19
|
+
# <%= search_form_with(model: @q) do |f| %>
|
|
20
|
+
#
|
|
21
|
+
def search_form_with(record_or_options = {}, options = {}, &proc)
|
|
22
|
+
if record_or_options.is_a?(Hash) && record_or_options.key?(:model)
|
|
23
|
+
# Called with keyword arguments: search_form_with(model: @q)
|
|
24
|
+
options = record_or_options
|
|
25
|
+
record = options.delete(:model)
|
|
26
|
+
else
|
|
27
|
+
# Called with positional arguments: search_form_with(@q)
|
|
28
|
+
record = record_or_options
|
|
29
|
+
end
|
|
30
|
+
search = extract_search_and_set_url(record, options, 'search_form_with')
|
|
31
|
+
options[:html] ||= {}
|
|
32
|
+
html_options = build_html_options(search, options, :get)
|
|
33
|
+
finalize_form_with_options(options, html_options)
|
|
34
|
+
form_with(model: search, **options, &proc)
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
# +turbo_search_form_for+
|
|
38
|
+
#
|
|
39
|
+
# <%= turbo_search_form_for(@q) do |f| %>
|
|
40
|
+
#
|
|
41
|
+
# This is a turbo-enabled version of search_form_for that submits via turbo streams
|
|
42
|
+
# instead of traditional HTML GET requests. Useful for seamless integration with
|
|
43
|
+
# paginated results and other turbo-enabled components.
|
|
44
|
+
#
|
|
45
|
+
def turbo_search_form_for(record, options = {}, &proc)
|
|
46
|
+
search = extract_search_and_set_url(record, options, 'turbo_search_form_for')
|
|
47
|
+
options[:html] ||= {}
|
|
48
|
+
turbo_options = build_turbo_options(options)
|
|
49
|
+
method = options.delete(:method) || :post
|
|
50
|
+
html_options = build_html_options(search, options, method).merge(turbo_options)
|
|
51
|
+
finalize_form_options(options, html_options)
|
|
52
|
+
form_for(record, options, &proc)
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
# +sort_link+
|
|
56
|
+
#
|
|
57
|
+
# <%= sort_link(@q, :name, [:name, 'kind ASC'], 'Player Name') %>
|
|
58
|
+
#
|
|
59
|
+
# You can also use a block:
|
|
60
|
+
#
|
|
61
|
+
# <%= sort_link(@q, :name, [:name, 'kind ASC']) do %>
|
|
62
|
+
# <strong>Player Name</strong>
|
|
63
|
+
# <% end %>
|
|
64
|
+
#
|
|
65
|
+
def sort_link(search_object, attribute, *args, &block)
|
|
66
|
+
search, routing_proxy = extract_search_and_routing_proxy(search_object)
|
|
67
|
+
unless Search === search
|
|
68
|
+
raise TypeError, 'First argument must be a Ransack::Search!'
|
|
69
|
+
end
|
|
70
|
+
args[args.first.is_a?(Array) ? 1 : 0, 0] = capture(&block) if block_given?
|
|
71
|
+
s = SortLink.new(search, attribute, args, params, &block)
|
|
72
|
+
link_to(s.name, url(routing_proxy, s.url_options), s.html_options(args))
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
# +sort_url+
|
|
76
|
+
# <%= sort_url(@q, :created_at, default_order: :desc) %>
|
|
77
|
+
#
|
|
78
|
+
def sort_url(search_object, attribute, *args)
|
|
79
|
+
search, routing_proxy = extract_search_and_routing_proxy(search_object)
|
|
80
|
+
unless Search === search
|
|
81
|
+
raise TypeError, 'First argument must be a Ransack::Search!'
|
|
82
|
+
end
|
|
83
|
+
s = SortLink.new(search, attribute, args, params)
|
|
84
|
+
url(routing_proxy, s.url_options)
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
private
|
|
88
|
+
|
|
89
|
+
def extract_search_and_set_url(record, options, method_name)
|
|
90
|
+
if record.is_a? Ransack::Search
|
|
91
|
+
search = record
|
|
92
|
+
options[:url] ||= polymorphic_path(
|
|
93
|
+
search.klass, format: options.delete(:format)
|
|
94
|
+
)
|
|
95
|
+
search
|
|
96
|
+
elsif record.is_a?(Array) &&
|
|
97
|
+
(search = record.detect { |o| o.is_a?(Ransack::Search) })
|
|
98
|
+
options[:url] ||= polymorphic_path(
|
|
99
|
+
options_for(record), format: options.delete(:format)
|
|
100
|
+
)
|
|
101
|
+
search
|
|
102
|
+
else
|
|
103
|
+
raise ArgumentError,
|
|
104
|
+
"No Ransack::Search object was provided to #{method_name}!"
|
|
105
|
+
end
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
def build_turbo_options(options)
|
|
109
|
+
data_options = {}
|
|
110
|
+
if options[:turbo_frame]
|
|
111
|
+
data_options[:turbo_frame] = options.delete(:turbo_frame)
|
|
112
|
+
end
|
|
113
|
+
data_options[:turbo_action] = options.delete(:turbo_action) || 'advance'
|
|
114
|
+
{ data: data_options }
|
|
115
|
+
end
|
|
116
|
+
|
|
117
|
+
def build_html_options(search, options, method)
|
|
118
|
+
{
|
|
119
|
+
class: html_option_for(options[:class], search),
|
|
120
|
+
id: html_option_for(options[:id], search),
|
|
121
|
+
method: method
|
|
122
|
+
}
|
|
123
|
+
end
|
|
124
|
+
|
|
125
|
+
def finalize_form_options(options, html_options)
|
|
126
|
+
options[:as] ||= Ransack.options[:search_key]
|
|
127
|
+
options[:html].reverse_merge!(html_options)
|
|
128
|
+
options[:builder] ||= FormBuilder
|
|
129
|
+
end
|
|
130
|
+
|
|
131
|
+
def finalize_form_with_options(options, html_options)
|
|
132
|
+
options[:scope] ||= Ransack.options[:search_key]
|
|
133
|
+
options[:html].reverse_merge!(html_options)
|
|
134
|
+
options[:builder] ||= FormBuilder
|
|
135
|
+
end
|
|
136
|
+
|
|
137
|
+
def options_for(record)
|
|
138
|
+
record.map { |r| parse_record(r) }
|
|
139
|
+
end
|
|
140
|
+
|
|
141
|
+
def parse_record(object)
|
|
142
|
+
return object.klass if object.is_a?(Ransack::Search)
|
|
143
|
+
object
|
|
144
|
+
end
|
|
145
|
+
|
|
146
|
+
def html_option_for(option, search)
|
|
147
|
+
return option.to_s if option.present?
|
|
148
|
+
"#{search.klass.to_s.underscore}_search"
|
|
149
|
+
end
|
|
150
|
+
|
|
151
|
+
def extract_search_and_routing_proxy(search)
|
|
152
|
+
return [search[1], search[0]] if search.is_a?(Array)
|
|
153
|
+
[search, nil]
|
|
154
|
+
end
|
|
155
|
+
|
|
156
|
+
def url(routing_proxy, options_for_url)
|
|
157
|
+
if routing_proxy && respond_to?(routing_proxy)
|
|
158
|
+
send(routing_proxy).url_for(options_for_url)
|
|
159
|
+
else
|
|
160
|
+
url_for(options_for_url)
|
|
161
|
+
end
|
|
162
|
+
end
|
|
163
|
+
|
|
164
|
+
class SortLink
|
|
165
|
+
def initialize(search, attribute, args, params)
|
|
166
|
+
@search = search
|
|
167
|
+
@params = parameters_hash(params)
|
|
168
|
+
@field = attribute.to_s
|
|
169
|
+
@sort_fields = extract_sort_fields_and_mutate_args!(args).compact
|
|
170
|
+
@current_dir = existing_sort_direction
|
|
171
|
+
@label_text = extract_label_and_mutate_args!(args)
|
|
172
|
+
@options = extract_options_and_mutate_args!(args)
|
|
173
|
+
@hide_indicator = @options.delete(:hide_indicator) ||
|
|
174
|
+
Ransack.options[:hide_sort_order_indicators]
|
|
175
|
+
@default_order = @options.delete :default_order
|
|
176
|
+
end
|
|
177
|
+
|
|
178
|
+
def up_arrow
|
|
179
|
+
Ransack.options[:up_arrow]
|
|
180
|
+
end
|
|
181
|
+
|
|
182
|
+
def down_arrow
|
|
183
|
+
Ransack.options[:down_arrow]
|
|
184
|
+
end
|
|
185
|
+
|
|
186
|
+
def default_arrow
|
|
187
|
+
Ransack.options[:default_arrow]
|
|
188
|
+
end
|
|
189
|
+
|
|
190
|
+
def name
|
|
191
|
+
[ERB::Util.h(@label_text), order_indicator]
|
|
192
|
+
.compact
|
|
193
|
+
.join(' '.freeze)
|
|
194
|
+
.html_safe
|
|
195
|
+
end
|
|
196
|
+
|
|
197
|
+
def url_options
|
|
198
|
+
@params.except(:host).merge(
|
|
199
|
+
@options.except(:class, :data, :host).merge(
|
|
200
|
+
@search.context.search_key => search_and_sort_params))
|
|
201
|
+
end
|
|
202
|
+
|
|
203
|
+
def html_options(args)
|
|
204
|
+
if args.empty?
|
|
205
|
+
html_options = @options
|
|
206
|
+
else
|
|
207
|
+
deprecation_message = "Passing two trailing hashes to `sort_link` is deprecated, merge the trailing hashes into a single one."
|
|
208
|
+
caller_location = caller_locations(2, 2).first
|
|
209
|
+
warn "#{deprecation_message} (called at #{caller_location.path}:#{caller_location.lineno})"
|
|
210
|
+
html_options = extract_options_and_mutate_args!(args)
|
|
211
|
+
end
|
|
212
|
+
|
|
213
|
+
html_options.merge(
|
|
214
|
+
class: [['sort_link'.freeze, @current_dir], html_options[:class]]
|
|
215
|
+
.compact.join(' '.freeze)
|
|
216
|
+
)
|
|
217
|
+
end
|
|
218
|
+
|
|
219
|
+
private
|
|
220
|
+
|
|
221
|
+
def parameters_hash(params)
|
|
222
|
+
if params.respond_to?(:to_unsafe_h)
|
|
223
|
+
params.to_unsafe_h
|
|
224
|
+
else
|
|
225
|
+
params
|
|
226
|
+
end
|
|
227
|
+
end
|
|
228
|
+
|
|
229
|
+
def extract_sort_fields_and_mutate_args!(args)
|
|
230
|
+
return args.shift if args[0].is_a?(Array)
|
|
231
|
+
[@field]
|
|
232
|
+
end
|
|
233
|
+
|
|
234
|
+
def extract_label_and_mutate_args!(args)
|
|
235
|
+
return args.shift if args[0].is_a?(String)
|
|
236
|
+
Translate.attribute(@field, context: @search.context)
|
|
237
|
+
end
|
|
238
|
+
|
|
239
|
+
def extract_options_and_mutate_args!(args)
|
|
240
|
+
return args.shift.with_indifferent_access if args[0].is_a?(Hash)
|
|
241
|
+
{}
|
|
242
|
+
end
|
|
243
|
+
|
|
244
|
+
def search_and_sort_params
|
|
245
|
+
search_params.merge(s: sort_params)
|
|
246
|
+
end
|
|
247
|
+
|
|
248
|
+
def search_params
|
|
249
|
+
query_params = @params[@search.context.search_key]
|
|
250
|
+
query_params.is_a?(Hash) ? query_params : {}
|
|
251
|
+
end
|
|
252
|
+
|
|
253
|
+
def sort_params
|
|
254
|
+
sort_array = recursive_sort_params_build(@sort_fields)
|
|
255
|
+
return sort_array[0] if sort_array.length == 1
|
|
256
|
+
sort_array
|
|
257
|
+
end
|
|
258
|
+
|
|
259
|
+
def recursive_sort_params_build(fields)
|
|
260
|
+
return [] if fields.empty?
|
|
261
|
+
[parse_sort(fields[0])] + recursive_sort_params_build(fields.drop 1)
|
|
262
|
+
end
|
|
263
|
+
|
|
264
|
+
def parse_sort(field)
|
|
265
|
+
attr_name, new_dir = field.to_s.split(/\s+/)
|
|
266
|
+
if no_sort_direction_specified?(new_dir)
|
|
267
|
+
new_dir = detect_previous_sort_direction_and_invert_it(attr_name)
|
|
268
|
+
end
|
|
269
|
+
"#{attr_name} #{new_dir}"
|
|
270
|
+
end
|
|
271
|
+
|
|
272
|
+
def detect_previous_sort_direction_and_invert_it(attr_name)
|
|
273
|
+
if sort_dir = existing_sort_direction(attr_name)
|
|
274
|
+
direction_text(sort_dir)
|
|
275
|
+
else
|
|
276
|
+
default_sort_order(attr_name) || 'asc'.freeze
|
|
277
|
+
end
|
|
278
|
+
end
|
|
279
|
+
|
|
280
|
+
def existing_sort_direction(f = @field)
|
|
281
|
+
return unless sort = @search.sorts.detect { |s| s && s.name == f }
|
|
282
|
+
sort.dir
|
|
283
|
+
end
|
|
284
|
+
|
|
285
|
+
def default_sort_order(attr_name)
|
|
286
|
+
return @default_order[attr_name] if Hash === @default_order
|
|
287
|
+
@default_order
|
|
288
|
+
end
|
|
289
|
+
|
|
290
|
+
def order_indicator
|
|
291
|
+
return if @hide_indicator
|
|
292
|
+
return default_arrow if no_sort_direction_specified?
|
|
293
|
+
if @current_dir == 'desc'.freeze
|
|
294
|
+
up_arrow
|
|
295
|
+
else
|
|
296
|
+
down_arrow
|
|
297
|
+
end
|
|
298
|
+
end
|
|
299
|
+
|
|
300
|
+
def no_sort_direction_specified?(dir = @current_dir)
|
|
301
|
+
dir != 'asc'.freeze && dir != 'desc'.freeze
|
|
302
|
+
end
|
|
303
|
+
|
|
304
|
+
def direction_text(dir)
|
|
305
|
+
return 'asc'.freeze if dir == 'desc'.freeze
|
|
306
|
+
'desc'.freeze
|
|
307
|
+
end
|
|
308
|
+
end
|
|
309
|
+
end
|
|
310
|
+
end
|
|
311
|
+
end
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
ar:
|
|
2
|
+
ransack:
|
|
3
|
+
search: "بحث"
|
|
4
|
+
predicate: "فاعل"
|
|
5
|
+
and: "و"
|
|
6
|
+
or: "أو"
|
|
7
|
+
any: "أيُّ"
|
|
8
|
+
all: "كل"
|
|
9
|
+
combinator: "دالة توافقية"
|
|
10
|
+
attribute: "خاصية"
|
|
11
|
+
value: "قيمة"
|
|
12
|
+
condition: "شرط"
|
|
13
|
+
sort: "ترتيب"
|
|
14
|
+
asc: "تصاعدي"
|
|
15
|
+
desc: "تنازلي"
|
|
16
|
+
predicates:
|
|
17
|
+
eq: "معادل"
|
|
18
|
+
eq_any: "معادل على اﻷقل لواحد"
|
|
19
|
+
eq_all: "معادل للجميع"
|
|
20
|
+
not_eq: "ليس معادلا لـ"
|
|
21
|
+
not_eq_any: "ليس معادلا على اﻷقل لواحد"
|
|
22
|
+
not_eq_all: "ليس معادلا للجميع"
|
|
23
|
+
matches: "موائم"
|
|
24
|
+
matches_any: "موائم لواحد على اﻷقل"
|
|
25
|
+
matches_all: "موائم للجميع"
|
|
26
|
+
does_not_match: "لا يتواءم"
|
|
27
|
+
does_not_match_any: "لا يتواءم مع واحد على اﻷقل"
|
|
28
|
+
does_not_match_all: "لا يتواءم مع الجميع"
|
|
29
|
+
lt: "أصغر من"
|
|
30
|
+
lt_any: "أصغر لواحد على اﻷقل"
|
|
31
|
+
lt_all: "أصغر من الجميع"
|
|
32
|
+
lteq: "أصغر أو مساو لـ"
|
|
33
|
+
lteq_any: "أصغر أو مساو لواحد على اﻷقل"
|
|
34
|
+
lteq_all: "أصغر أو مساو للجميع"
|
|
35
|
+
gt: "أكبر من"
|
|
36
|
+
gt_any: "أكبر من واحد على اﻷقل"
|
|
37
|
+
gt_all: "أكبر من الجميع"
|
|
38
|
+
gteq: "أكبر أو مساو لـ"
|
|
39
|
+
gteq_any: "أكبر أو مساو لواحد على اﻷقل"
|
|
40
|
+
gteq_all: "أكبر أو مساو للجميع"
|
|
41
|
+
in: "متضمن لـ"
|
|
42
|
+
in_any: "متضمن لواحد على اﻷقل"
|
|
43
|
+
in_all: "متضمن للجميع"
|
|
44
|
+
not_in: "غير متضمن"
|
|
45
|
+
not_in_any: "غير متضمن لواحد على اﻷقل"
|
|
46
|
+
not_in_all: "غير متضمن للجميع"
|
|
47
|
+
cont: "محتو"
|
|
48
|
+
cont_any: "محتو لواحد على اﻷقل"
|
|
49
|
+
cont_all: "محتو لجميع"
|
|
50
|
+
not_cont: "غير محتو"
|
|
51
|
+
not_cont_any: "غير محتو لواحد على اﻷقل"
|
|
52
|
+
not_cont_all: "غير محتو للجميع"
|
|
53
|
+
start: "يبدأ بـ"
|
|
54
|
+
start_any: "يبدأ بواحد على اﻷقل"
|
|
55
|
+
start_all: "يبدأ بالجميع"
|
|
56
|
+
not_start: "لا يبدأ بـ"
|
|
57
|
+
not_start_any: "لا يبدأ بواحد على اﻷقل"
|
|
58
|
+
not_start_all: "لا يبدأ بالجميع"
|
|
59
|
+
end: "ينتهي بـ"
|
|
60
|
+
end_any: "ينتهي بواحد على اﻷقل"
|
|
61
|
+
end_all: "ينتهي بالجميع"
|
|
62
|
+
not_end: "لا ينتهي بـ"
|
|
63
|
+
not_end_any: "لا ينتهي بواحد على اﻷقل"
|
|
64
|
+
not_end_all: "لا ينتهي بالجميع"
|
|
65
|
+
'true': "صحيح"
|
|
66
|
+
'false': "خطأ"
|
|
67
|
+
present: "مستقبل"
|
|
68
|
+
blank: "فراغ"
|
|
69
|
+
'null': "عدم"
|
|
70
|
+
not_null: "غير مساو لقيمة عدم"
|