activerecord-hackery--ransack/lib/ransack/helpers/form_helper.rb

172 lines
5.1 KiB
Ruby
Raw Normal View History

2011-03-31 00:31:39 +00:00
module Ransack
module Helpers
module FormHelper
2014-08-14 22:27:07 +00:00
def asc
'asc'.freeze
end
def desc
'desc'.freeze
end
def asc_arrow
'▲'.freeze
end
def desc_arrow
'▼'.freeze
end
def non_breaking_space
' '.freeze
end
2011-03-31 00:31:39 +00:00
def search_form_for(record, options = {}, &proc)
if record.is_a?(Ransack::Search)
search = record
2014-04-18 08:49:38 +00:00
options[:url] ||= polymorphic_path(
search.klass, format: options.delete(:format)
)
2013-12-10 18:18:17 +00:00
elsif record.is_a?(Array) &&
(search = record.detect { |o| o.is_a?(Ransack::Search) })
2013-08-04 13:13:41 +00:00
options[:url] ||= polymorphic_path(
2014-04-18 08:49:38 +00:00
record.map { |o| o.is_a?(Ransack::Search) ? o.klass : o },
format: options.delete(:format)
2013-12-10 18:18:17 +00:00
)
2011-03-31 00:31:39 +00:00
else
2013-08-04 13:13:41 +00:00
raise ArgumentError,
"No Ransack::Search object was provided to search_form_for!"
2011-03-31 00:31:39 +00:00
end
options[:html] ||= {}
html_options = {
:class => options[:class].present? ?
2013-12-10 18:18:17 +00:00
"#{options[:class]}" :
"#{search.klass.to_s.underscore}_search",
:id => options[:id].present? ?
2013-12-10 18:18:17 +00:00
"#{options[:id]}" :
"#{search.klass.to_s.underscore}_search",
:method => :get
2011-03-31 00:31:39 +00:00
}
2014-08-14 22:27:07 +00:00
options[:as] ||= 'q'.freeze
2011-03-31 00:31:39 +00:00
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
2013-12-10 18:18:17 +00:00
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 = if ! args.first.try(:is_a?, Hash)
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
# 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 Hash === default_order
search_params = params[search.context.search_key].presence ||
2013-12-10 18:18:17 +00:00
{}.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.downcase.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 %w{ 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
current_dir == desc ? asc : desc
else
if Hash === default_order
default_order[attr_name] || asc
else
default_order || asc
end
end
2013-12-10 18:18:17 +00:00
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
if sort_params.size == 1
sort_params = sort_params.first
end
html_options = args.first.is_a?(Hash) ? args.shift.dup : {}
css = ['sort_link', field_current_dir].compact.join(' ')
html_options[:class] = [css, html_options[:class]].compact.join(' ')
query_hash = {}
2013-12-10 18:18:17 +00:00
query_hash[search.context.search_key] = search_params
.merge(:s => sort_params)
options.merge!(query_hash)
2013-07-22 13:23:39 +00:00
options_for_url = params.merge options
url = if routing_proxy && respond_to?(routing_proxy)
2013-07-22 13:23:39 +00:00
send(routing_proxy).url_for(options_for_url)
else
2013-07-22 13:23:39 +00:00
url_for(options_for_url)
end
2013-12-10 18:18:17 +00:00
link_to(
[ERB::Util.h(label), order_indicator_for(field_current_dir)]
2013-12-10 18:18:17 +00:00
.compact
2014-08-14 22:27:07 +00:00
.join(non_breaking_space)
2013-12-10 18:18:17 +00:00
.html_safe,
url,
html_options
2013-12-10 18:18:17 +00:00
)
end
private
def order_indicator_for(order)
2014-08-14 22:27:07 +00:00
if order == asc
asc_arrow
elsif order == desc
desc_arrow
else
nil
end
end
2011-03-31 00:31:39 +00:00
end
end
end