mirror of
https://github.com/activerecord-hackery/ransack.git
synced 2022-11-09 13:47:45 -05:00
c3a9110e24
Fixes #92
162 lines
5.3 KiB
Ruby
162 lines
5.3 KiB
Ruby
module Ransack
|
|
module Helpers
|
|
module FormHelper
|
|
|
|
def search_form_for(record, options = {}, &proc)
|
|
if record.is_a?(Ransack::Search)
|
|
search = record
|
|
options[:url] ||= polymorphic_path(
|
|
search.klass, format: options.delete(:format)
|
|
)
|
|
elsif record.is_a?(Array) &&
|
|
(search = record.detect { |o| o.is_a?(Ransack::Search) })
|
|
options[:url] ||= polymorphic_path(
|
|
record.map { |o| o.is_a?(Ransack::Search) ? o.klass : o },
|
|
format: options.delete(:format)
|
|
)
|
|
else
|
|
raise ArgumentError,
|
|
"No Ransack::Search object was provided to search_form_for!"
|
|
end
|
|
options[:html] ||= {}
|
|
html_options = {
|
|
:class => options[:class].present? ?
|
|
"#{options[:class]}" :
|
|
"#{search.klass.to_s.underscore}_search",
|
|
:id => options[:id].present? ?
|
|
"#{options[:id]}" :
|
|
"#{search.klass.to_s.underscore}_search",
|
|
:method => :get
|
|
}
|
|
options[:as] ||= Ransack.options[:search_key]
|
|
options[:html].reverse_merge!(html_options)
|
|
options[:builder] ||= FormBuilder
|
|
|
|
form_for(record, options, &proc)
|
|
end
|
|
|
|
# sort_link @q, :name, [:name, 'kind ASC'], 'Player Name'
|
|
def sort_link(search, attribute, *args)
|
|
# Extract out a routing proxy for url_for scoping later
|
|
if search.is_a?(Array)
|
|
routing_proxy = search.shift
|
|
search = search.first
|
|
end
|
|
|
|
raise TypeError, "First argument must be a Ransack::Search!" unless
|
|
Search === search
|
|
|
|
# This is the field that this link represents. The direction of the sort icon (up/down arrow) will
|
|
# depend on the sort status of this field
|
|
field_name = attribute.to_s
|
|
|
|
# Determine the fields we want to sort on
|
|
sort_fields = if Array === args.first
|
|
args.shift
|
|
else
|
|
Array(field_name)
|
|
end
|
|
|
|
label_text =
|
|
if String === args.first
|
|
args.shift.to_s
|
|
else
|
|
Translate.attribute(field_name, :context => search.context)
|
|
end
|
|
|
|
options = args.first.is_a?(Hash) ? args.shift.dup : {}
|
|
default_order = options.delete :default_order
|
|
default_order_is_a_hash = Hash === default_order
|
|
|
|
# If the default order is a hash of fields, duplicate it and let us access it with strings or symbols
|
|
default_order = default_order.dup.with_indifferent_access if
|
|
default_order_is_a_hash
|
|
|
|
search_params = params[search.context.search_key].presence ||
|
|
{}.with_indifferent_access
|
|
|
|
# Find the current direction (if there is one) of the primary sort field
|
|
if existing_sort = search.sorts.detect { |s| s.name == field_name }
|
|
field_current_dir = existing_sort.dir
|
|
end
|
|
|
|
sort_params = []
|
|
|
|
Array(sort_fields).each do |sort_field|
|
|
attr_name, new_dir = sort_field.to_s.split(/\s+/)
|
|
current_dir = nil
|
|
|
|
# if the user didn't specify the sort direction, detect the previous
|
|
# sort direction on this field and reverse it
|
|
if Ransack::Constants::ASC_DESC.none? { |d| d == new_dir }
|
|
if existing_sort = search.sorts.detect { |s| s.name == attr_name }
|
|
current_dir = existing_sort.dir
|
|
end
|
|
|
|
new_dir =
|
|
if current_dir
|
|
if current_dir == Ransack::Constants::DESC
|
|
Ransack::Constants::ASC
|
|
else
|
|
Ransack::Constants::DESC
|
|
end
|
|
elsif default_order_is_a_hash
|
|
default_order[attr_name] || Ransack::Constants::ASC
|
|
else
|
|
default_order || Ransack::Constants::ASC
|
|
end
|
|
end
|
|
|
|
sort_params << "#{attr_name} #{new_dir}"
|
|
end
|
|
|
|
# if there is only one sort parameter, remove it from the array and just
|
|
# use the string as the parameter
|
|
sort_params = sort_params.first if sort_params.size == 1
|
|
|
|
html_options = args.first.is_a?(Hash) ? args.shift.dup : {}
|
|
css = [Ransack::Constants::SORT_LINK, field_current_dir]
|
|
.compact.join(Ransack::Constants::SPACE)
|
|
html_options[:class] = [css, html_options[:class]]
|
|
.compact.join(Ransack::Constants::SPACE)
|
|
|
|
query_hash = {}
|
|
query_hash[search.context.search_key] = search_params
|
|
.merge(:s => sort_params)
|
|
options.merge!(query_hash)
|
|
options_for_url = params.merge(options)
|
|
|
|
url =
|
|
if routing_proxy && respond_to?(routing_proxy)
|
|
send(routing_proxy).url_for(options_for_url)
|
|
else
|
|
url_for(options_for_url)
|
|
end
|
|
|
|
name = link_name(label_text, field_current_dir)
|
|
|
|
link_to(name, url, html_options)
|
|
end
|
|
|
|
private
|
|
|
|
def link_name(label_text, dir)
|
|
[ERB::Util.h(label_text), order_indicator_for(dir)]
|
|
.compact
|
|
.join(Ransack::Constants::NON_BREAKING_SPACE)
|
|
.html_safe
|
|
end
|
|
|
|
def order_indicator_for(dir)
|
|
if dir == Ransack::Constants::ASC
|
|
Ransack::Constants::ASC_ARROW
|
|
elsif dir == Ransack::Constants::DESC
|
|
Ransack::Constants::DESC_ARROW
|
|
else
|
|
nil
|
|
end
|
|
end
|
|
|
|
end
|
|
end
|
|
end
|