peentar-smart_listing 1.1.3

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 (47) hide show
  1. checksums.yaml +7 -0
  2. data/LICENSE +21 -0
  3. data/README.md +279 -0
  4. data/Rakefile +34 -0
  5. data/app/assets/javascripts/smart_listing.coffee.erb +438 -0
  6. data/app/helpers/smart_listing/application_helper.rb +5 -0
  7. data/app/helpers/smart_listing/helper.rb +366 -0
  8. data/app/views/kaminari/smart_listing/_first_page.html.erb +13 -0
  9. data/app/views/kaminari/smart_listing/_gap.html.erb +8 -0
  10. data/app/views/kaminari/smart_listing/_last_page.html.erb +13 -0
  11. data/app/views/kaminari/smart_listing/_next_page.html.erb +13 -0
  12. data/app/views/kaminari/smart_listing/_page.html.erb +12 -0
  13. data/app/views/kaminari/smart_listing/_paginator.html.erb +25 -0
  14. data/app/views/kaminari/smart_listing/_prev_page.html.erb +13 -0
  15. data/app/views/smart_listing/_action_custom.html.erb +10 -0
  16. data/app/views/smart_listing/_action_delete.html.erb +12 -0
  17. data/app/views/smart_listing/_action_edit.html.erb +11 -0
  18. data/app/views/smart_listing/_action_show.html.erb +11 -0
  19. data/app/views/smart_listing/_item_new.html.erb +30 -0
  20. data/app/views/smart_listing/_pagination_per_page_link.html.erb +12 -0
  21. data/app/views/smart_listing/_pagination_per_page_links.html.erb +19 -0
  22. data/app/views/smart_listing/_sortable.html.erb +21 -0
  23. data/app/views/smart_listing/_update_list.js.erb +2 -0
  24. data/app/views/smart_listing/create.js.erb +2 -0
  25. data/app/views/smart_listing/destroy.js.erb +1 -0
  26. data/app/views/smart_listing/edit.js.erb +1 -0
  27. data/app/views/smart_listing/index.js.erb +1 -0
  28. data/app/views/smart_listing/item/_create.js.erb +3 -0
  29. data/app/views/smart_listing/item/_create_continue.js.erb +6 -0
  30. data/app/views/smart_listing/item/_destroy.js.erb +2 -0
  31. data/app/views/smart_listing/item/_edit.js.erb +2 -0
  32. data/app/views/smart_listing/item/_new.js.erb +2 -0
  33. data/app/views/smart_listing/item/_remove.js.erb +2 -0
  34. data/app/views/smart_listing/item/_update.js.erb +2 -0
  35. data/app/views/smart_listing/new.js.erb +1 -0
  36. data/app/views/smart_listing/update.js.erb +2 -0
  37. data/config/locales/en.yml +15 -0
  38. data/config/routes.rb +2 -0
  39. data/lib/generators/smart_listing/install_generator.rb +20 -0
  40. data/lib/generators/smart_listing/templates/initializer.rb +88 -0
  41. data/lib/generators/smart_listing/views_generator.rb +23 -0
  42. data/lib/smart_listing.rb +216 -0
  43. data/lib/smart_listing/config.rb +159 -0
  44. data/lib/smart_listing/engine.rb +5 -0
  45. data/lib/smart_listing/version.rb +3 -0
  46. data/lib/tasks/smart_list_tasks.rake +4 -0
  47. metadata +245 -0
@@ -0,0 +1,13 @@
1
+ <%# Link to the "Previous" page
2
+ - available local variables
3
+ url: url to the previous page
4
+ current_page: a page object for the currently displayed page
5
+ total_pages: total number of pages
6
+ per_page: number of items to fetch per page
7
+ remote: data-remote
8
+ -%>
9
+ <% unless current_page.first? %>
10
+ <li class="prev">
11
+ <%= link_to_unless current_page.first?, raw(t 'views.pagination.previous'), url, :rel => 'prev', :remote => remote %>
12
+ </li>
13
+ <% end %>
@@ -0,0 +1,10 @@
1
+ <%#
2
+ Custom action.
3
+
4
+ Available local variables:
5
+ url
6
+ icon
7
+ html_options: custom html options
8
+ -%>
9
+
10
+ <%= link_to_if(action_if, content_tag(:span, '', :class => icon, :title => title), url, html_options) %>
@@ -0,0 +1,12 @@
1
+ <%#
2
+ Delete action.
3
+
4
+ Available local variables:
5
+ action_if: false if action is disabled
6
+ url: destroy url
7
+ icon: icon css classes
8
+ confirmation: confrimation text
9
+ title
10
+ -%>
11
+
12
+ <%= link_to_if(action_if, content_tag(:i, "", :class => icon), url, :remote => true, :class => "destroy", :method => :delete, :title => title || t("smart_listing.actions.destroy"), :data => {:confirmation => confirmation || t("smart_listing.msgs.destroy_confirmation")} ) %>
@@ -0,0 +1,11 @@
1
+ <%#
2
+ Edit action.
3
+
4
+ Available local variables:
5
+ action_if: false if action is disabled
6
+ url: edit url
7
+ icon: icon css classes
8
+ title
9
+ -%>
10
+
11
+ <%= link_to_if(action_if, content_tag(:i, '', :class => icon), url, :remote => true, :class => "edit", :title => title || t("smart_listing.actions.edit") ) %>
@@ -0,0 +1,11 @@
1
+ <%#
2
+ Show action.
3
+
4
+ Available local variables:
5
+ action_if: false if action is disabled
6
+ url: show url
7
+ icon: icon clss classes
8
+ title
9
+ -%>
10
+
11
+ <%= link_to_if(action_if, content_tag(:i, '', :class => icon), url, :class => "show", :title => title || t("smart_listing.actions.show") ) %>
@@ -0,0 +1,30 @@
1
+ <%#
2
+ New list item element (contains new item placeholder and add button).
3
+
4
+ Available local variables:
5
+ placeholder_classes: classes for the main container
6
+ new_item_action_classes: new item action classes
7
+ colspan
8
+ no_items_classes: no items container classes
9
+ no_items_text: no items text displayed inside container
10
+ new_item_button_url: argument to link_to (new item button)
11
+ new_item_button_classes
12
+ new_item_button_text
13
+ new_item_autoshow automatically show new item placeholder
14
+ new_item_content new item placeholder content (usually some form)
15
+ -%>
16
+
17
+ <%= content_tag(:tr, '', :class => placeholder_classes + %w{info}, :data => {smart_listing_config.data_attributes(:autoshow) => new_item_autoshow}) do %>
18
+ <%= new_item_content %>
19
+ <% end %>
20
+ <%= content_tag(:tr, :class => new_item_action_classes + %w{info}) do %>
21
+ <%= content_tag(:td, :colspan => colspan) do %>
22
+ <%= content_tag(:p, :class => no_items_classes + %w{pull-left}) do %>
23
+ <%= no_items_text %>
24
+ <% end %>
25
+ <%= link_to(new_item_button_url, :remote => true, :class => new_item_button_classes + %w{btn pull-right}) do %>
26
+ <%= content_tag(:i, '', :class => smart_listing_config.classes(:icon_new)) %>
27
+ <%= new_item_button_text %>
28
+ <% end %>
29
+ <% end %>
30
+ <% end %>
@@ -0,0 +1,12 @@
1
+ <%#
2
+ Pagination single per-page link.
3
+
4
+ Available local variables:
5
+ page: page number
6
+ url: page url (if page is not selected)
7
+ smart_listing: current SmartListing instance
8
+ builder: current builder instance
9
+ -%>
10
+
11
+ <% name = page == 0 ? t('views.pagination.unlimited') : page %>
12
+ <%= url ? link_to(name, url, :remote => smart_listing.remote?) : content_tag(:span, name) %>
@@ -0,0 +1,19 @@
1
+ <%#
2
+ Pagination per-page links.
3
+
4
+ Available local variables:
5
+ container_classes: classes for the main container
6
+ per_page_sizes: array of available per-page sizes
7
+ smart_listing: current SmartListing instance
8
+ builder: current builder instance
9
+ -%>
10
+
11
+ <%= content_tag(:div, :class => container_classes ) do %>
12
+ <% if smart_listing.options[:paginate] && (smart_listing.count > smart_listing.page_sizes.first) %>
13
+ <%= t('views.pagination.per_page') %>
14
+ <% per_page_sizes.each do |p| %><%= builder.pagination_per_page_link p %><% break if p >= smart_listing.count %><% end %>
15
+ |
16
+ <% end %>
17
+ <%= t('views.pagination.total') %>
18
+ <%= content_tag(:span, smart_listing.count, :class => "count") %>
19
+ <% end %>
@@ -0,0 +1,21 @@
1
+ <%#
2
+ Sortable attribute listing header.
3
+
4
+ Available local variables:
5
+ container_classes: classes for the main container
6
+ url: sortable link url
7
+ attribute: current attribute name
8
+ title: current attribute title
9
+ order: defines column sort order
10
+ smart_listing: current SmartListing instance
11
+ builder: current builder instance
12
+ -%>
13
+
14
+ <%= link_to url, :class => container_classes, :data => {:attr => attribute}, :remote => true do %>
15
+ <%= title %>
16
+ <% if order %>
17
+ <span class="<%= order == "asc" ? smart_listing_config.classes(:icon_sort_up) : smart_listing_config.classes(:icon_sort_down) %>"></span>
18
+ <% else %>
19
+ <span class="<%= smart_listing_config.classes(:icon_sort_none) %>"></span>
20
+ <% end %>
21
+ <% end %>
@@ -0,0 +1,2 @@
1
+ var smart_listing = $('#<%= name %>').smart_listing();
2
+ smart_listing.update_list("<%= escape_javascript(render(:partial => part, :locals => {:smart_listing => smart_listing}.merge(locals))) %>", <%= smart_listing_data.to_json.html_safe %>);
@@ -0,0 +1,2 @@
1
+ <%= smart_listing_item :create, smart_listing_resource,
2
+ smart_listing_resource.valid? ? "item" : "form" %>
@@ -0,0 +1 @@
1
+ <%= smart_listing_item :destroy, smart_listing_resource %>
@@ -0,0 +1 @@
1
+ <%= smart_listing_item :edit, smart_listing_resource, "form" %>
@@ -0,0 +1 @@
1
+ <%= smart_listing_update %>
@@ -0,0 +1,3 @@
1
+ var smart_listing = $('#<%= name %>').smart_listing();
2
+ smart_listing.setAutoshow(false);
3
+ smart_listing.create(<%= id || 0 %>, <%= object.persisted? %>, "<%= escape_javascript(render(:partial => part, :locals => {object_key => object})) %>");
@@ -0,0 +1,6 @@
1
+ var smart_listing = $('#<%= name %>').smart_listing();
2
+ smart_listing.setAutoshow(true);
3
+ smart_listing.create(<%= id || 0 %>, <%= object.persisted? %>, "<%= escape_javascript(render(:partial => part, :locals => {object_key => object})) %>");
4
+ <% if object.persisted? %>
5
+ smart_listing.new_item("<%= escape_javascript(render(:partial => new.last, :locals => {object_key => new.first})) %>");
6
+ <% end %>
@@ -0,0 +1,2 @@
1
+ var smart_listing = $('#<%= name.to_s %>').smart_listing();
2
+ smart_listing.destroy(<%= id %>, <%= object.destroyed? %>);
@@ -0,0 +1,2 @@
1
+ var smart_listing = $('#<%= name %>').smart_listing();
2
+ smart_listing.edit(<%= id %>, "<%= escape_javascript(render(:partial => part, :locals => {object_key => object})) %>");
@@ -0,0 +1,2 @@
1
+ var smart_listing = $('#<%= name %>').smart_listing();
2
+ smart_listing.new_item("<%= escape_javascript(render(:partial => part, :locals => {object_key => object})) %>");
@@ -0,0 +1,2 @@
1
+ var smart_listing = $('#<%= name %>').smart_listing();
2
+ smart_listing.remove(<%= id %>);
@@ -0,0 +1,2 @@
1
+ var smart_listing = $('#<%= name %>').smart_listing();
2
+ smart_listing.update(<%= id %>, <%= valid.nil? ? object.valid? : valid %>, "<%= escape_javascript(render(:partial => part, :locals => {object_key => object})) %>");
@@ -0,0 +1 @@
1
+ <%= smart_listing_item :new, smart_listing_resource, "form" %>
@@ -0,0 +1,2 @@
1
+ <%= smart_listing_item :update, smart_listing_resource,
2
+ smart_listing_resource.valid? ? "item" : "form" %>
@@ -0,0 +1,15 @@
1
+ en:
2
+ smart_listing:
3
+ msgs:
4
+ destroy_confirmation: Destroy?
5
+ no_items: No items
6
+ actions:
7
+ destroy: Destroy
8
+ edit: Edit
9
+ show: Show
10
+ new: New item
11
+ views:
12
+ pagination:
13
+ per_page: Per page
14
+ unlimited: Unlimited
15
+ total: Total
@@ -0,0 +1,2 @@
1
+ SmartListing::Engine.routes.draw do
2
+ end
@@ -0,0 +1,20 @@
1
+ module SmartListing
2
+ module Generators
3
+ class InstallGenerator < Rails::Generators::Base
4
+ source_root File.expand_path('../templates', __FILE__)
5
+
6
+ def self.banner #:nodoc:
7
+ <<-BANNER.chomp
8
+ rails g smart_listing:install
9
+
10
+ Copies initializer file
11
+ BANNER
12
+ end
13
+
14
+ desc ''
15
+ def copy_views
16
+ template 'initializer.rb', 'config/initializers/smart_listing.rb'
17
+ end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,88 @@
1
+ SmartListing.configure do |config|
2
+ config.global_options({
3
+ #:param_names => { # param names
4
+ #:page => :page,
5
+ #:per_page => :per_page,
6
+ #:sort => :sort,
7
+ #},
8
+ #:array => false, # controls whether smart list should be using arrays or AR collections
9
+ #:max_count => nil, # limit number of rows
10
+ #:unlimited_per_page => false, # allow infinite page size
11
+ #:paginate => true, # allow pagination
12
+ #:memorize_per_page => false, # save per page settings in the cookie
13
+ #:page_sizes => DEFAULT_PAGE_SIZES, # set available page sizes array
14
+ #:kaminari_options => {:theme => "smart_listing"}, # Kaminari's paginate helper options
15
+ #:sort_dirs => [nil, "asc", "desc"], # Default sorting directions cycle of sortables
16
+ })
17
+
18
+ config.constants :classes, {
19
+ #:main => "smart-listing",
20
+ #:editable => "editable",
21
+ #:content => "content",
22
+ #:loading => "loading",
23
+ #:status => "smart-listing-status",
24
+ #:item_actions => "actions",
25
+ #:new_item_placeholder => "new-item-placeholder",
26
+ #:new_item_action => "new-item-action",
27
+ #:new_item_button => "btn",
28
+ #:hidden => "hidden",
29
+ #:autoselect => "autoselect",
30
+ #:callback => "callback",
31
+ #:pagination_wrapper => "text-center",
32
+ #:pagination_container => "pagination",
33
+ #:pagination_per_page => "pagination-per-page text-center",
34
+ #:inline_editing => "info",
35
+ #:no_records => "no-records",
36
+ #:limit => "smart-listing-limit",
37
+ #:limit_alert => "smart-listing-limit-alert",
38
+ #:controls => "smart-listing-controls",
39
+ #:controls_reset => "reset",
40
+ #:filtering => "filter",
41
+ #:filtering_search => "glyphicon-search",
42
+ #:filtering_cancel => "glyphicon-remove",
43
+ #:filtering_disabled => "disabled",
44
+ #:sortable => "sortable",
45
+ #:icon_new => "glyphicon glyphicon-plus",
46
+ #:icon_edit => "glyphicon glyphicon-pencil",
47
+ #:icon_trash => "glyphicon glyphicon-trash",
48
+ #:icon_inactive => "glyphicon glyphicon-circle",
49
+ #:icon_show => "glyphicon glyphicon-share-alt",
50
+ #:icon_sort_none => "glyphicon glyphicon-resize-vertical",
51
+ #:icon_sort_up => "glyphicon glyphicon-chevron-up",
52
+ #:icon_sort_down => "glyphicon glyphicon-chevron-down",
53
+ #:muted => "text-muted",
54
+ }
55
+
56
+ config.constants :data_attributes, {
57
+ #:main => "smart-listing",
58
+ #:controls_initialized => "smart-listing-controls-initialized",
59
+ #:confirmation => "confirmation",
60
+ #:id => "id",
61
+ #:href => "href",
62
+ #:callback_href => "callback-href",
63
+ #:max_count => "max-count",
64
+ #:item_count => "item-count",
65
+ #:inline_edit_backup => "smart-listing-edit-backup",
66
+ #:params => "params",
67
+ #:observed => "observed",
68
+ #:href => "href",
69
+ #:autoshow => "autoshow",
70
+ #:popover => "slpopover",
71
+ }
72
+
73
+ config.constants :selectors, {
74
+ #:item_action_destroy => "a.destroy",
75
+ #:edit_cancel => "button.cancel",
76
+ #:row => "tr",
77
+ #:head => "thead",
78
+ #:filtering_icon => "i"
79
+ #:filtering_button => "button",
80
+ #:filtering_icon => "button span",
81
+ #:filtering_input => ".filter input",
82
+ #:pagination_count => ".pagination-per-page .count",
83
+ }
84
+
85
+ config.constants :element_templates, {
86
+ #:row => "<tr />",
87
+ }
88
+ end
@@ -0,0 +1,23 @@
1
+ module SmartListing
2
+ module Generators
3
+ class ViewsGenerator < Rails::Generators::Base
4
+ source_root File.expand_path('../../../../app/views/smart_listing', __FILE__)
5
+
6
+ def self.banner #:nodoc:
7
+ <<-BANNER.chomp
8
+ rails g smart_listing:views
9
+
10
+ Copies all smart listing partials templates to your application.
11
+ BANNER
12
+ end
13
+
14
+ desc ''
15
+ def copy_views
16
+ filename_pattern = File.join self.class.source_root, "*.html.erb"
17
+ Dir.glob(filename_pattern).map {|f| File.basename f}.each do |f|
18
+ copy_file f, "app/views/smart_listing/#{f}"
19
+ end
20
+ end
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,216 @@
1
+ require 'smart_listing/config'
2
+ require "smart_listing/engine"
3
+ require "kaminari"
4
+
5
+ # Fix parsing nested params
6
+ module Kaminari
7
+ module Helpers
8
+ class Tag
9
+ def page_url_for(page)
10
+ @template.url_for @params.deep_merge(page_param(page)).merge(:only_path => true)
11
+ end
12
+
13
+ private
14
+
15
+ def page_param(page)
16
+ Rack::Utils.parse_nested_query("#{@param_name}=#{page <= 1 ? nil : page}").symbolize_keys
17
+ end
18
+ end
19
+ end
20
+ end
21
+
22
+ module SmartListing
23
+ class Base
24
+ attr_reader :name, :collection, :options, :per_page, :sort, :page, :partial, :count
25
+
26
+ def initialize name, collection, options = {}
27
+ @name = name
28
+
29
+ config_profile = options.delete(:config_profile)
30
+
31
+ @options = {
32
+ :partial => @name, # SmartListing partial name
33
+ :sort_attributes => :implicit, # allow implicitly setting sort attributes
34
+ :default_sort => {}, # default sorting
35
+ :href => nil, # set SmartListing target url (in case when different than current url)
36
+ :remote => true, # SmartListing is remote by default
37
+ :callback_href => nil, # set SmartListing callback url (in case when different than current url)
38
+ }.merge(SmartListing.config(config_profile).global_options).merge(options)
39
+
40
+ if @options[:array]
41
+ @collection = collection.to_a
42
+ else
43
+ @collection = collection
44
+ end
45
+ end
46
+
47
+ def setup params, cookies
48
+ @params = params
49
+
50
+ @page = get_param :page
51
+ @per_page = !get_param(:per_page) || get_param(:per_page).empty? ? (@options[:memorize_per_page] && get_param(:per_page, cookies).to_i > 0 ? get_param(:per_page, cookies).to_i : page_sizes.first) : get_param(:per_page).to_i
52
+ @per_page = page_sizes.first unless page_sizes.include?(@per_page) || (unlimited_per_page? && @per_page == 0)
53
+
54
+ @sort = parse_sort(get_param(:sort)) || @options[:default_sort]
55
+ sort_keys = (@options[:sort_attributes] == :implicit ? @sort.keys.collect{|s| [s, s]} : @options[:sort_attributes])
56
+
57
+ set_param(:per_page, @per_page, cookies) if @options[:memorize_per_page]
58
+
59
+ @count = @collection.size
60
+ @count = @count.length if @count.is_a?(Hash)
61
+
62
+ # Reset @page if greater than total number of pages
63
+ if @per_page > 0
64
+ no_pages = (@count.to_f / @per_page.to_f).ceil.to_i
65
+ if @page.to_i > no_pages
66
+ @page = no_pages
67
+ end
68
+ end
69
+
70
+ if @options[:array]
71
+ if @sort && @sort.any? # when array we sort only by first attribute
72
+ i = sort_keys.index{|x| x[0] == @sort.first[0]}
73
+ @collection = @collection.sort do |x, y|
74
+ xval = x
75
+ yval = y
76
+ sort_keys[i][1].split(".").each do |m|
77
+ xval = xval.try(m)
78
+ yval = yval.try(m)
79
+ end
80
+ xval = xval.upcase if xval.is_a?(String)
81
+ yval = yval.upcase if yval.is_a?(String)
82
+
83
+ if xval.nil? || yval.nil?
84
+ xval.nil? ? 1 : -1
85
+ else
86
+ if @sort.first[1] == "asc"
87
+ (xval <=> yval) || (xval && !yval ? 1 : -1)
88
+ else
89
+ (yval <=> xval) || (yval && !xval ? 1 : -1)
90
+ end
91
+ end
92
+ end
93
+ end
94
+ if @options[:paginate] && @per_page > 0
95
+ @collection = ::Kaminari.paginate_array(@collection).page(@page).per(@per_page)
96
+ if @collection.length == 0
97
+ @collection = @collection.page(@collection.num_pages)
98
+ end
99
+ end
100
+ else
101
+ # let's sort by all attributes
102
+ #
103
+ @collection = @collection.order(sort_keys.collect{|s| "#{s[1]} #{@sort[s[0]]}" if @sort[s[0]]}.compact) if @sort && @sort.any?
104
+
105
+ if @options[:paginate] && @per_page > 0
106
+ @collection = @collection.page(@page).per(@per_page)
107
+ end
108
+ end
109
+ end
110
+
111
+ def partial
112
+ @options[:partial]
113
+ end
114
+
115
+ def param_names
116
+ @options[:param_names]
117
+ end
118
+
119
+ def param_name key
120
+ "#{base_param}[#{param_names[key]}]"
121
+ end
122
+
123
+ def unlimited_per_page?
124
+ !!@options[:unlimited_per_page]
125
+ end
126
+
127
+ def max_count
128
+ @options[:max_count]
129
+ end
130
+
131
+ def href
132
+ @options[:href]
133
+ end
134
+
135
+ def callback_href
136
+ @options[:callback_href]
137
+ end
138
+
139
+ def remote?
140
+ @options[:remote]
141
+ end
142
+
143
+ def page_sizes
144
+ @options[:page_sizes]
145
+ end
146
+
147
+ def kaminari_options
148
+ @options[:kaminari_options]
149
+ end
150
+
151
+ def sort_dirs
152
+ @options[:sort_dirs]
153
+ end
154
+
155
+ def all_params overrides = {}
156
+ ap = {base_param => {}}
157
+ @options[:param_names].each do |k, v|
158
+ if overrides[k]
159
+ ap[base_param][v] = overrides[k]
160
+ else
161
+ ap[base_param][v] = self.send(k)
162
+ end
163
+ end
164
+ ap
165
+ end
166
+
167
+ def sort_order attribute
168
+ @sort && @sort[attribute].present? ? @sort[attribute] : nil
169
+ end
170
+
171
+ def base_param
172
+ "#{name}_smart_listing"
173
+ end
174
+
175
+ private
176
+
177
+ def get_param key, store = @params
178
+ if store.is_a?(ActionDispatch::Cookies::CookieJar)
179
+ store["#{base_param}_#{param_names[key]}"]
180
+ else
181
+ store[base_param].try(:[], param_names[key])
182
+ end
183
+ end
184
+
185
+ def set_param key, value, store = @params
186
+ if store.is_a?(ActionDispatch::Cookies::CookieJar)
187
+ store["#{base_param}_#{param_names[key]}"] = value
188
+ else
189
+ store[base_param] ||= {}
190
+ store[base_param][param_names[key]] = value
191
+ end
192
+ end
193
+
194
+ def parse_sort sort_params
195
+ sort = nil
196
+
197
+ if @options[:sort_attributes] == :implicit
198
+ sort = sort_params.dup if sort_params.present?
199
+ elsif @options[:sort_attributes]
200
+ @options[:sort_attributes].each do |a|
201
+ k, v = a
202
+ if sort_params && sort_params[k.to_s]
203
+ dir = ["asc", "desc", ""].delete(sort_params[k.to_s])
204
+
205
+ if dir
206
+ sort ||= {}
207
+ sort[k] = dir
208
+ end
209
+ end
210
+ end
211
+ end
212
+
213
+ sort
214
+ end
215
+ end
216
+ end