##// END OF EJS Templates
Prevent "can't convert nil into String" error when :sort_order param is not present....
Jean-Philippe Lang -
r1395:9e5624c362ad
parent child
Show More
@@ -1,160 +1,160
1 # Helpers to sort tables using clickable column headers.
1 # Helpers to sort tables using clickable column headers.
2 #
2 #
3 # Author: Stuart Rackham <srackham@methods.co.nz>, March 2005.
3 # Author: Stuart Rackham <srackham@methods.co.nz>, March 2005.
4 # License: This source code is released under the MIT license.
4 # License: This source code is released under the MIT license.
5 #
5 #
6 # - Consecutive clicks toggle the column's sort order.
6 # - Consecutive clicks toggle the column's sort order.
7 # - Sort state is maintained by a session hash entry.
7 # - Sort state is maintained by a session hash entry.
8 # - Icon image identifies sort column and state.
8 # - Icon image identifies sort column and state.
9 # - Typically used in conjunction with the Pagination module.
9 # - Typically used in conjunction with the Pagination module.
10 #
10 #
11 # Example code snippets:
11 # Example code snippets:
12 #
12 #
13 # Controller:
13 # Controller:
14 #
14 #
15 # helper :sort
15 # helper :sort
16 # include SortHelper
16 # include SortHelper
17 #
17 #
18 # def list
18 # def list
19 # sort_init 'last_name'
19 # sort_init 'last_name'
20 # sort_update
20 # sort_update
21 # @items = Contact.find_all nil, sort_clause
21 # @items = Contact.find_all nil, sort_clause
22 # end
22 # end
23 #
23 #
24 # Controller (using Pagination module):
24 # Controller (using Pagination module):
25 #
25 #
26 # helper :sort
26 # helper :sort
27 # include SortHelper
27 # include SortHelper
28 #
28 #
29 # def list
29 # def list
30 # sort_init 'last_name'
30 # sort_init 'last_name'
31 # sort_update
31 # sort_update
32 # @contact_pages, @items = paginate :contacts,
32 # @contact_pages, @items = paginate :contacts,
33 # :order_by => sort_clause,
33 # :order_by => sort_clause,
34 # :per_page => 10
34 # :per_page => 10
35 # end
35 # end
36 #
36 #
37 # View (table header in list.rhtml):
37 # View (table header in list.rhtml):
38 #
38 #
39 # <thead>
39 # <thead>
40 # <tr>
40 # <tr>
41 # <%= sort_header_tag('id', :title => 'Sort by contact ID') %>
41 # <%= sort_header_tag('id', :title => 'Sort by contact ID') %>
42 # <%= sort_header_tag('last_name', :caption => 'Name') %>
42 # <%= sort_header_tag('last_name', :caption => 'Name') %>
43 # <%= sort_header_tag('phone') %>
43 # <%= sort_header_tag('phone') %>
44 # <%= sort_header_tag('address', :width => 200) %>
44 # <%= sort_header_tag('address', :width => 200) %>
45 # </tr>
45 # </tr>
46 # </thead>
46 # </thead>
47 #
47 #
48 # - The ascending and descending sort icon images are sort_asc.png and
48 # - The ascending and descending sort icon images are sort_asc.png and
49 # sort_desc.png and reside in the application's images directory.
49 # sort_desc.png and reside in the application's images directory.
50 # - Introduces instance variables: @sort_name, @sort_default.
50 # - Introduces instance variables: @sort_name, @sort_default.
51 # - Introduces params :sort_key and :sort_order.
51 # - Introduces params :sort_key and :sort_order.
52 #
52 #
53 module SortHelper
53 module SortHelper
54
54
55 # Initializes the default sort column (default_key) and sort order
55 # Initializes the default sort column (default_key) and sort order
56 # (default_order).
56 # (default_order).
57 #
57 #
58 # - default_key is a column attribute name.
58 # - default_key is a column attribute name.
59 # - default_order is 'asc' or 'desc'.
59 # - default_order is 'asc' or 'desc'.
60 # - name is the name of the session hash entry that stores the sort state,
60 # - name is the name of the session hash entry that stores the sort state,
61 # defaults to '<controller_name>_sort'.
61 # defaults to '<controller_name>_sort'.
62 #
62 #
63 def sort_init(default_key, default_order='asc', name=nil)
63 def sort_init(default_key, default_order='asc', name=nil)
64 @sort_name = name || params[:controller] + params[:action] + '_sort'
64 @sort_name = name || params[:controller] + params[:action] + '_sort'
65 @sort_default = {:key => default_key, :order => default_order}
65 @sort_default = {:key => default_key, :order => default_order}
66 end
66 end
67
67
68 # Updates the sort state. Call this in the controller prior to calling
68 # Updates the sort state. Call this in the controller prior to calling
69 # sort_clause.
69 # sort_clause.
70 #
70 #
71 def sort_update()
71 def sort_update()
72 if params[:sort_key]
72 if params[:sort_key]
73 sort = {:key => params[:sort_key], :order => params[:sort_order]}
73 sort = {:key => params[:sort_key], :order => params[:sort_order]}
74 elsif session[@sort_name]
74 elsif session[@sort_name]
75 sort = session[@sort_name] # Previous sort.
75 sort = session[@sort_name] # Previous sort.
76 else
76 else
77 sort = @sort_default
77 sort = @sort_default
78 end
78 end
79 session[@sort_name] = sort
79 session[@sort_name] = sort
80 end
80 end
81
81
82 # Returns an SQL sort clause corresponding to the current sort state.
82 # Returns an SQL sort clause corresponding to the current sort state.
83 # Use this to sort the controller's table items collection.
83 # Use this to sort the controller's table items collection.
84 #
84 #
85 def sort_clause()
85 def sort_clause()
86 session[@sort_name][:key] + ' ' + session[@sort_name][:order]
86 session[@sort_name][:key] + ' ' + (session[@sort_name][:order] || 'ASC')
87 end
87 end
88
88
89 # Returns a link which sorts by the named column.
89 # Returns a link which sorts by the named column.
90 #
90 #
91 # - column is the name of an attribute in the sorted record collection.
91 # - column is the name of an attribute in the sorted record collection.
92 # - The optional caption explicitly specifies the displayed link text.
92 # - The optional caption explicitly specifies the displayed link text.
93 # - A sort icon image is positioned to the right of the sort link.
93 # - A sort icon image is positioned to the right of the sort link.
94 #
94 #
95 def sort_link(column, caption, default_order)
95 def sort_link(column, caption, default_order)
96 key, order = session[@sort_name][:key], session[@sort_name][:order]
96 key, order = session[@sort_name][:key], session[@sort_name][:order]
97 if key == column
97 if key == column
98 if order.downcase == 'asc'
98 if order.downcase == 'asc'
99 icon = 'sort_asc.png'
99 icon = 'sort_asc.png'
100 order = 'desc'
100 order = 'desc'
101 else
101 else
102 icon = 'sort_desc.png'
102 icon = 'sort_desc.png'
103 order = 'asc'
103 order = 'asc'
104 end
104 end
105 else
105 else
106 icon = nil
106 icon = nil
107 order = default_order
107 order = default_order
108 end
108 end
109 caption = titleize(Inflector::humanize(column)) unless caption
109 caption = titleize(Inflector::humanize(column)) unless caption
110
110
111 sort_options = { :sort_key => column, :sort_order => order }
111 sort_options = { :sort_key => column, :sort_order => order }
112 # don't reuse params if filters are present
112 # don't reuse params if filters are present
113 url_options = params.has_key?(:set_filter) ? sort_options : params.merge(sort_options)
113 url_options = params.has_key?(:set_filter) ? sort_options : params.merge(sort_options)
114
114
115 link_to_remote(caption,
115 link_to_remote(caption,
116 {:update => "content", :url => url_options},
116 {:update => "content", :url => url_options},
117 {:href => url_for(url_options)}) +
117 {:href => url_for(url_options)}) +
118 (icon ? nbsp(2) + image_tag(icon) : '')
118 (icon ? nbsp(2) + image_tag(icon) : '')
119 end
119 end
120
120
121 # Returns a table header <th> tag with a sort link for the named column
121 # Returns a table header <th> tag with a sort link for the named column
122 # attribute.
122 # attribute.
123 #
123 #
124 # Options:
124 # Options:
125 # :caption The displayed link name (defaults to titleized column name).
125 # :caption The displayed link name (defaults to titleized column name).
126 # :title The tag's 'title' attribute (defaults to 'Sort by :caption').
126 # :title The tag's 'title' attribute (defaults to 'Sort by :caption').
127 #
127 #
128 # Other options hash entries generate additional table header tag attributes.
128 # Other options hash entries generate additional table header tag attributes.
129 #
129 #
130 # Example:
130 # Example:
131 #
131 #
132 # <%= sort_header_tag('id', :title => 'Sort by contact ID', :width => 40) %>
132 # <%= sort_header_tag('id', :title => 'Sort by contact ID', :width => 40) %>
133 #
133 #
134 # Renders:
134 # Renders:
135 #
135 #
136 # <th title="Sort by contact ID" width="40">
136 # <th title="Sort by contact ID" width="40">
137 # <a href="/contact/list?sort_order=desc&amp;sort_key=id">Id</a>
137 # <a href="/contact/list?sort_order=desc&amp;sort_key=id">Id</a>
138 # &nbsp;&nbsp;<img alt="Sort_asc" src="/images/sort_asc.png" />
138 # &nbsp;&nbsp;<img alt="Sort_asc" src="/images/sort_asc.png" />
139 # </th>
139 # </th>
140 #
140 #
141 def sort_header_tag(column, options = {})
141 def sort_header_tag(column, options = {})
142 caption = options.delete(:caption) || titleize(Inflector::humanize(column))
142 caption = options.delete(:caption) || titleize(Inflector::humanize(column))
143 default_order = options.delete(:default_order) || 'asc'
143 default_order = options.delete(:default_order) || 'asc'
144 options[:title]= l(:label_sort_by, "\"#{caption}\"") unless options[:title]
144 options[:title]= l(:label_sort_by, "\"#{caption}\"") unless options[:title]
145 content_tag('th', sort_link(column, caption, default_order), options)
145 content_tag('th', sort_link(column, caption, default_order), options)
146 end
146 end
147
147
148 private
148 private
149
149
150 # Return n non-breaking spaces.
150 # Return n non-breaking spaces.
151 def nbsp(n)
151 def nbsp(n)
152 '&nbsp;' * n
152 '&nbsp;' * n
153 end
153 end
154
154
155 # Return capitalized title.
155 # Return capitalized title.
156 def titleize(title)
156 def titleize(title)
157 title.split.map {|w| w.capitalize }.join(' ')
157 title.split.map {|w| w.capitalize }.join(' ')
158 end
158 end
159
159
160 end
160 end
General Comments 0
You need to be logged in to leave comments. Login now