sortablecolumns 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/History.txt +3 -0
- data/Manifest.txt +12 -0
- data/README.txt +202 -0
- data/Rakefile +22 -0
- data/bin/sortable_columns +0 -0
- data/lib/sortablecolumns.rb +6 -0
- data/lib/sortablecolumns/helpers.rb +167 -0
- data/lib/sortablecolumns/sortable_columns.rb +254 -0
- data/test/col_def_test_yaml_files/person/dude/dude_report.yml +24 -0
- data/test/col_def_test_yaml_files/person/mysorter.yml +64 -0
- data/test/col_def_test_yaml_files/person/tacosorter.yml +23 -0
- data/test/sortablecolumns_test.rb +510 -0
- metadata +75 -0
data/History.txt
ADDED
data/Manifest.txt
ADDED
@@ -0,0 +1,12 @@
|
|
1
|
+
History.txt
|
2
|
+
Manifest.txt
|
3
|
+
README.txt
|
4
|
+
Rakefile
|
5
|
+
bin/sortable_columns
|
6
|
+
lib/sortablecolumns.rb
|
7
|
+
lib/sortablecolumns/helpers.rb
|
8
|
+
lib/sortablecolumns/sortable_columns.rb
|
9
|
+
test/col_def_test_yaml_files/person/dude/dude_report.yml
|
10
|
+
test/col_def_test_yaml_files/person/mysorter.yml
|
11
|
+
test/col_def_test_yaml_files/person/tacosorter.yml
|
12
|
+
test/sortablecolumns_test.rb
|
data/README.txt
ADDED
@@ -0,0 +1,202 @@
|
|
1
|
+
= SortableColumns
|
2
|
+
|
3
|
+
* http://rubyforge.org/projects/sortablecolumns/
|
4
|
+
|
5
|
+
== DESCRIPTION:
|
6
|
+
|
7
|
+
SortableColumns is a Rails plugin that allows easy creation of sortable HTML tables as plain HTML or as a YUI DataTable (requires YUI4Rails plugin - http://rubyforge.org/projects/yui4rails/). Table column characteristics (e.g., default sort direction, data type, CSS attributes, and methods to wrap the output in) are defined in YAML files (more options to be added later, such auto-detecting the column types, using a hash, etc.). Multiple table column definitions can be created for a single model.
|
8
|
+
|
9
|
+
An example live application can be found here: http://sortablecolumns.heroku.com/
|
10
|
+
Download the example app here: http://www.bryandonovan.com/sortable_columns_example.tar.gz
|
11
|
+
|
12
|
+
Also see: ActiveRecord::Acts::SortableColumns::ClassMethods#sortable_columns
|
13
|
+
|
14
|
+
== INSTALL:
|
15
|
+
|
16
|
+
* sudo gem install sortablecolumns
|
17
|
+
* IMPORTANT: create a directory named col_defs in your app/models directory if you want to use the default YAML directory (otherwise you can specify a path using :path_prefix).
|
18
|
+
|
19
|
+
== FEATURES/PROBLEMS:
|
20
|
+
|
21
|
+
=== Features
|
22
|
+
* Simple to define column characteristics in YAML
|
23
|
+
* Can be used with regular HTML or with YUI DataTable (http://developer.yahoo.com/yui/datatable/)
|
24
|
+
* Allows definitions of arbitrary columns, so you aren't limited to the columns in your model. E.g.,
|
25
|
+
you can use custom SQL queries that return a mix of columns from different models or "virtual" columns
|
26
|
+
created in the SQL query.
|
27
|
+
* Test coverage for all current features.
|
28
|
+
|
29
|
+
=== Problems
|
30
|
+
* Doesn't yet support date formats (should be easy to implement though and will hopefully happen soon)
|
31
|
+
|
32
|
+
== SYNOPSIS:
|
33
|
+
* First, create a directory to store your column definitions YAML files. The default location SortableColumns will look is app/models/col_defs.
|
34
|
+
* Create a YAML file for the configuration of your table columns.
|
35
|
+
* Call sortable_tables in your model
|
36
|
+
* Run query (get an ActiveRecord result set)
|
37
|
+
* Render table in your view
|
38
|
+
|
39
|
+
=== Example Usage
|
40
|
+
Say we have a Person model (or a custom SQL query result) with the following columns/attributes:
|
41
|
+
* firstname - string, should be a link to the people/show action, TD CSS class of "left".
|
42
|
+
* lastname - string, should be wrapped in sanitize.
|
43
|
+
* age - integer, default sort direction: descending. TD CSS class: "center".
|
44
|
+
* description - string/text - should have a TD CSS class of "left", should be wrapped in auto_link, sanitize, and simple_format.
|
45
|
+
* balance - decimal/currency - precision of 2, comma for a separator, space for delimiter, British pound for unit. Default sort: descending.
|
46
|
+
* edit and detroy links, called "Edit" and "Delete" (which, of course, are not fields in the query result, but will be in the displayed table).
|
47
|
+
|
48
|
+
We're going to call this sorter "mysorter". This will be the name of the YAML file and the name passed into the sortable_columns method in the model.
|
49
|
+
|
50
|
+
In model:
|
51
|
+
|
52
|
+
class Person < ActiveRecord::Base
|
53
|
+
sortable_columns :mysorter
|
54
|
+
|
55
|
+
# method to run query with sort options
|
56
|
+
def self.find_for_mysorter(options = {})
|
57
|
+
order_by = options[:order_by]
|
58
|
+
dir = options[:dir]
|
59
|
+
query = "select * from people"
|
60
|
+
query << " order by #{order_by}" if order_by
|
61
|
+
query << " #{dir}" if dir
|
62
|
+
Person.find_by_sql(query)
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
YAML file:
|
67
|
+
-
|
68
|
+
firstname:
|
69
|
+
heading: First
|
70
|
+
datatype: string
|
71
|
+
link_options:
|
72
|
+
controller: people
|
73
|
+
action: show
|
74
|
+
id: obj_id
|
75
|
+
td_class: left
|
76
|
+
|
77
|
+
-
|
78
|
+
lastname:
|
79
|
+
heading: Last
|
80
|
+
datatype: string
|
81
|
+
print_options:
|
82
|
+
wrappers: sanitize
|
83
|
+
-
|
84
|
+
age:
|
85
|
+
datatype: number
|
86
|
+
sort_options:
|
87
|
+
default_dir: desc
|
88
|
+
td_class: center
|
89
|
+
-
|
90
|
+
description:
|
91
|
+
datatype: string
|
92
|
+
sortable: false
|
93
|
+
print_options:
|
94
|
+
wrappers:
|
95
|
+
- auto_link
|
96
|
+
- sanitize
|
97
|
+
- simple_format
|
98
|
+
td_class: left
|
99
|
+
-
|
100
|
+
balance:
|
101
|
+
datatype: currency
|
102
|
+
precision: 2
|
103
|
+
separator: ","
|
104
|
+
delimiter: " "
|
105
|
+
unit: £
|
106
|
+
td_class: right
|
107
|
+
-
|
108
|
+
edit:
|
109
|
+
in_resultset: false
|
110
|
+
heading: false
|
111
|
+
th_class: invisible
|
112
|
+
print_text: Edit
|
113
|
+
link_options:
|
114
|
+
controller: people
|
115
|
+
action: edit
|
116
|
+
id: obj_id
|
117
|
+
-
|
118
|
+
delete:
|
119
|
+
in_resultset: false
|
120
|
+
heading: false
|
121
|
+
th_class: invisible
|
122
|
+
print_text: Delete
|
123
|
+
link_options:
|
124
|
+
controller: people
|
125
|
+
action: destroy
|
126
|
+
id: obj_id
|
127
|
+
extras:
|
128
|
+
method: delete
|
129
|
+
confirm: Are you sure?
|
130
|
+
|
131
|
+
In the link_options, use obj_id to specify that the current object's id field should be used.
|
132
|
+
|
133
|
+
In the controller:
|
134
|
+
|
135
|
+
def index #plain HTML table
|
136
|
+
@people = Person.find_for_mysorter(options=params.dup)
|
137
|
+
respond_to do |format|
|
138
|
+
format.html
|
139
|
+
end
|
140
|
+
end
|
141
|
+
|
142
|
+
def yui #YUI DataTable
|
143
|
+
@people = Person.find_for_mysorter(options=params.dup)
|
144
|
+
@col_defs = Person.mysorter_col_defs_for_yui
|
145
|
+
@data_keys = Person.mysorter_fields_for_yui
|
146
|
+
|
147
|
+
@data_table = Yui4Rails::Widgets::DataTable.new(:table_div_id => "markup",
|
148
|
+
:col_defs => @col_defs,
|
149
|
+
:data_keys => @data_keys,
|
150
|
+
:table_id => 'yui_table')
|
151
|
+
|
152
|
+
@data_table.paginate(5)
|
153
|
+
|
154
|
+
respond_to do |format|
|
155
|
+
format.html # index.html.erb
|
156
|
+
end
|
157
|
+
end
|
158
|
+
|
159
|
+
In the view:
|
160
|
+
|
161
|
+
<%= print_table(@people, :mysorter %>
|
162
|
+
Or if you want alternating styles for table rows:
|
163
|
+
<%= print_table(@people, :mysorter, :tr => {:classes => ['even','odd']}) %>
|
164
|
+
And you can specify a table CSS class & id:
|
165
|
+
<%= print_table(@people, :mysorter, :table => {:class => 'yui-skin-sam', :id => 'yui_table'}) %>
|
166
|
+
|
167
|
+
For YUI DataTable, add the followoing after the print_table call:
|
168
|
+
<%= @data_table.render(:source => :html)%>
|
169
|
+
Also make sure the table is inside a div with the same id as specified in the controller when using the YUI DataTable.
|
170
|
+
|
171
|
+
== REQUIREMENTS:
|
172
|
+
|
173
|
+
* YUI4Rails gem if you want to use YUI datatables
|
174
|
+
|
175
|
+
== Disclaimer
|
176
|
+
|
177
|
+
This is beta-quality software. It works well according to my tests, but the API may change and other features may be added.
|
178
|
+
|
179
|
+
== LICENSE:
|
180
|
+
|
181
|
+
(The MIT License)
|
182
|
+
|
183
|
+
Copyright (c) 2008 Bryan Donovan
|
184
|
+
|
185
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
186
|
+
a copy of this software and associated documentation files (the
|
187
|
+
'Software'), to deal in the Software without restriction, including
|
188
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
189
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
190
|
+
permit persons to whom the Software is furnished to do so, subject to
|
191
|
+
the following conditions:
|
192
|
+
|
193
|
+
The above copyright notice and this permission notice shall be
|
194
|
+
included in all copies or substantial portions of the Software.
|
195
|
+
|
196
|
+
THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
|
197
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
198
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
199
|
+
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
200
|
+
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
201
|
+
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
202
|
+
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/Rakefile
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
# -*- ruby -*-
|
2
|
+
|
3
|
+
require 'rubygems'
|
4
|
+
require 'hoe'
|
5
|
+
require './lib/sortablecolumns.rb'
|
6
|
+
|
7
|
+
Hoe.new('sortablecolumns', Sortablecolumns::VERSION) do |p|
|
8
|
+
p.name = "sortablecolumns"
|
9
|
+
p.author = "Bryan Donovan - http://www.bryandonovan.com"
|
10
|
+
p.email = "b.dondo+rubyforge@gmail.com"
|
11
|
+
p.description = "Sortable HTML tables for Rails"
|
12
|
+
p.summary = "Sortable HTML tables for Rails"
|
13
|
+
p.url = "http://rubyforge.org/projects/sortablecolumns/"
|
14
|
+
p.changes = p.paragraphs_of('History.txt', 0..1).join("\n\n")
|
15
|
+
p.remote_rdoc_dir = '' # Release to root
|
16
|
+
end
|
17
|
+
|
18
|
+
rule '' do |t|
|
19
|
+
system "cd test && ruby sortablecolumns_test.rb"
|
20
|
+
end
|
21
|
+
|
22
|
+
# vim: syntax=Ruby
|
File without changes
|
@@ -0,0 +1,6 @@
|
|
1
|
+
module Sortablecolumns #:nodoc:
|
2
|
+
VERSION = '0.1.0'
|
3
|
+
end
|
4
|
+
Dir[File.join(File.dirname(__FILE__), "sortablecolumns/**/*.rb")].sort.each { |lib| require lib }
|
5
|
+
ActiveRecord::Base.send(:include, ActiveRecord::Acts::Sortablecolumns)
|
6
|
+
ActionView::Base.send(:include, Sortablecolumns::Helpers)
|
@@ -0,0 +1,167 @@
|
|
1
|
+
module Sortablecolumns
|
2
|
+
module Helpers
|
3
|
+
|
4
|
+
#Prints entire HTML table with content
|
5
|
+
def print_table(collection, sorter, options={})
|
6
|
+
klass = collection.first.class
|
7
|
+
txt = print_table_thead(klass, sorter)
|
8
|
+
txt << print_table_body(collection, sorter, options)
|
9
|
+
return content_tag('table', txt, options[:table])
|
10
|
+
end
|
11
|
+
|
12
|
+
#Prints a single table column (TD element) with content
|
13
|
+
def print_col(obj, sorter, col)
|
14
|
+
col = col.to_s
|
15
|
+
klass = obj.class
|
16
|
+
txt = klass.send("#{sorter}_col_text",obj,col)
|
17
|
+
wrappers = []
|
18
|
+
|
19
|
+
datatype = klass.send("#{sorter}_datatype",col) || 'string'
|
20
|
+
|
21
|
+
if datatype == 'number'
|
22
|
+
precision = klass.send("#{sorter}_precision",col)
|
23
|
+
txt = number_with_precision(txt, precision) if precision
|
24
|
+
end
|
25
|
+
|
26
|
+
if datatype == 'currency'
|
27
|
+
precision = klass.send("#{sorter}_precision",col)
|
28
|
+
unit = klass.send("#{sorter}_unit",col)
|
29
|
+
separator = klass.send("#{sorter}_separator",col)
|
30
|
+
delimiter = klass.send("#{sorter}_delimiter",col)
|
31
|
+
txt = number_to_currency(txt, :precision => precision,
|
32
|
+
:unit => unit, :separator => separator, :delimiter => delimiter)
|
33
|
+
end
|
34
|
+
|
35
|
+
do_link = klass.send("#{sorter}_link?",col)
|
36
|
+
|
37
|
+
if do_link
|
38
|
+
link_ops = klass.send("#{sorter}_link_options",col).dup
|
39
|
+
raise "link_options must be defined for #{klass}:#{col}" unless link_ops
|
40
|
+
if link_ops[:object_url]
|
41
|
+
txt = link_to(txt, send("#{klass.to_s.downcase}_url", obj))
|
42
|
+
elsif link_ops[:controller] && link_ops[:action]
|
43
|
+
if link_ops[:id] && link_ops[:id] == 'obj_id'
|
44
|
+
link_ops[:id] = obj.id
|
45
|
+
end
|
46
|
+
if link_ops[:extras]
|
47
|
+
extras = link_ops.delete(:extras)
|
48
|
+
txt = link_to(txt, link_ops, extras)
|
49
|
+
else
|
50
|
+
txt = link_to(txt, link_ops)
|
51
|
+
end
|
52
|
+
elsif link_ops[:url]
|
53
|
+
url = link_ops[:url].gsub(/:id/, obj.id.to_s)
|
54
|
+
unless url.match(/http/)
|
55
|
+
url = 'http://' + default_url_options[:host] + url
|
56
|
+
end
|
57
|
+
txt = link_to(txt, url)
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
print_options = klass.send("#{sorter}_print_options",col)
|
62
|
+
wrappers << print_options['wrappers'] if print_options && print_options['wrappers']
|
63
|
+
|
64
|
+
wrappers.flatten.each do |wrapper|
|
65
|
+
if wrapper.is_a? Hash
|
66
|
+
key = wrapper.keys.first
|
67
|
+
extra_args = wrapper[key]
|
68
|
+
txt = send(key, txt, extra_args)
|
69
|
+
else
|
70
|
+
txt = send(wrapper, txt)
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
td_class = klass.send("#{sorter}_td_class",col)
|
75
|
+
|
76
|
+
return content_tag("td", txt, :class => td_class)
|
77
|
+
end
|
78
|
+
|
79
|
+
#Prints single table row with content
|
80
|
+
def print_table_row(obj, sorter, options={})
|
81
|
+
txt = ''
|
82
|
+
klass = obj.class
|
83
|
+
cols = klass.send("#{sorter}_col_keys_in_order")
|
84
|
+
cols.each do |col|
|
85
|
+
txt << print_col(obj, sorter, col)
|
86
|
+
end
|
87
|
+
content_tag("tr", txt, options)
|
88
|
+
end
|
89
|
+
|
90
|
+
#Prints table body with content
|
91
|
+
def print_table_body(collection, sorter, options={})
|
92
|
+
txt = ""
|
93
|
+
if options[:tr] && options[:tr][:classes]
|
94
|
+
alternate = true
|
95
|
+
tr_classes = options[:tr][:classes]
|
96
|
+
end
|
97
|
+
tr_class = nil
|
98
|
+
i = 0
|
99
|
+
collection.each do |obj|
|
100
|
+
if alternate
|
101
|
+
tr_class = tr_classes[i % 2]
|
102
|
+
end
|
103
|
+
txt << print_table_row(obj, sorter, :class => tr_class)
|
104
|
+
i += 1
|
105
|
+
end
|
106
|
+
content_tag("tbody", txt)
|
107
|
+
end
|
108
|
+
|
109
|
+
#Prints single TH tag with content
|
110
|
+
def print_col_heading(klass, sorter, col, options={})
|
111
|
+
col = col.to_s
|
112
|
+
th_txt = klass.send("#{sorter}_heading", col)
|
113
|
+
th_class = klass.send("#{sorter}_th_class", col)
|
114
|
+
return content_tag("th", '', :class => th_class) unless th_txt
|
115
|
+
sortable = klass.send("#{sorter}_sortable?", col)
|
116
|
+
return content_tag("th", th_txt, :class => th_class) unless sortable
|
117
|
+
url = get_col_heading_url(klass, sorter, col)
|
118
|
+
link = link_to(th_txt, url)
|
119
|
+
return content_tag("th", link, :class => th_class)
|
120
|
+
end
|
121
|
+
|
122
|
+
#Get URL for sortable table column header (TH element)
|
123
|
+
def get_col_heading_url(klass, sorter, col)
|
124
|
+
order_by = col
|
125
|
+
default_dir = 'asc'
|
126
|
+
sort_ops = klass.send("#{sorter}_sort_options", col)
|
127
|
+
if sort_ops
|
128
|
+
order_by = sort_ops['order_by'] if sort_ops['order_by']
|
129
|
+
default_dir = sort_ops['default_dir'] if sort_ops['default_dir']
|
130
|
+
end
|
131
|
+
|
132
|
+
reg = Regexp.new(order_by.to_s)
|
133
|
+
if params[:order_by] =~ reg
|
134
|
+
dir = (params[:dir] == "asc") ? "desc" : "asc"
|
135
|
+
else
|
136
|
+
dir = default_dir
|
137
|
+
end
|
138
|
+
|
139
|
+
get_url(order_by, dir)
|
140
|
+
end
|
141
|
+
|
142
|
+
#get url for given set of params, order_by, and dir
|
143
|
+
def get_url(order_by, dir)
|
144
|
+
_params = params.dup
|
145
|
+
_params[:order_by] = order_by
|
146
|
+
_params[:dir] = dir
|
147
|
+
url_for(_params)
|
148
|
+
end
|
149
|
+
|
150
|
+
#Prints a row of TH tags with content
|
151
|
+
def print_table_heading_row(klass, sorter, options={})
|
152
|
+
cols = klass.send("#{sorter}_col_keys_in_order")
|
153
|
+
txt = ''
|
154
|
+
cols.each do |col|
|
155
|
+
txt << print_col_heading(klass, sorter, col)
|
156
|
+
end
|
157
|
+
txt
|
158
|
+
content_tag("tr", txt, options)
|
159
|
+
end
|
160
|
+
|
161
|
+
#Prints THEAD tags with content
|
162
|
+
def print_table_thead(klass, sorter)
|
163
|
+
content_tag('thead', print_table_heading_row(klass, sorter))
|
164
|
+
end
|
165
|
+
|
166
|
+
end
|
167
|
+
end
|
@@ -0,0 +1,254 @@
|
|
1
|
+
# Sortablecolumns Rails Plugin
|
2
|
+
# Lets you define column definitions for a sortable HTML table.
|
3
|
+
# Author: Bryan Donovan
|
4
|
+
# March 2008
|
5
|
+
|
6
|
+
require 'active_record'
|
7
|
+
require 'active_support'
|
8
|
+
require 'action_controller'
|
9
|
+
|
10
|
+
module ActiveRecord #:nodoc:
|
11
|
+
module Acts #:nodoc:
|
12
|
+
module Sortablecolumns
|
13
|
+
def self.included(base) # :nodoc:
|
14
|
+
base.extend(ClassMethods)
|
15
|
+
end
|
16
|
+
|
17
|
+
module ClassMethods
|
18
|
+
include ActiveSupport::CoreExtensions::Hash::Keys
|
19
|
+
|
20
|
+
# == Configuration options
|
21
|
+
#
|
22
|
+
# * <tt>sorter_name</tt> (required) - specify the name of the sorter, same name used for YAML file, method prefixes
|
23
|
+
# * <tt>subclass_name</tt> (optional) - specify the subclass name if your model inherits from another model. You must create your YAML file in a subdirectory of the same name (lowercase). E.g., app/models/person/manager_sorter.yml for a Manager model that inherits from the Person model.
|
24
|
+
# * <tt>path_prefix</tt> (optional) - path to your column definitions directory where your YAML files are stored (relative to RAILS_ROOT). If this isn't specified, Sortablecolumns looks for column definitions in /app/models/col_defs, but you must create that directory manually.
|
25
|
+
# == Examples
|
26
|
+
# class Person < ActiveRecord::Base
|
27
|
+
# sortable_columns :mysorter
|
28
|
+
# sortable_columns :othersorter, :path_prefix => '/my_column_defs'
|
29
|
+
# end
|
30
|
+
|
31
|
+
# class Manager < Person
|
32
|
+
# sortable_columns :manager_sorter, :subclass_name => 'Manager'
|
33
|
+
# end
|
34
|
+
def sortable_columns(sorter_name, options = {})
|
35
|
+
options = {:subclass_name => nil, :path_prefix => nil}.merge(options)
|
36
|
+
write_inheritable_attribute(:sorter_options, options)
|
37
|
+
class_inheritable_reader :sorter_options
|
38
|
+
|
39
|
+
self.class_eval <<-END
|
40
|
+
def self.#{sorter_name}_cols=(val)
|
41
|
+
@@#{sorter_name}_cols = val
|
42
|
+
end
|
43
|
+
|
44
|
+
def self.#{sorter_name}_cols
|
45
|
+
@@#{sorter_name}_cols
|
46
|
+
end
|
47
|
+
cattr_accessor :#{sorter_name}_cols
|
48
|
+
|
49
|
+
def self.#{sorter_name}_col_defs
|
50
|
+
@@#{sorter_name}_cols ||= #{sorter_name}_initialize_col_defs
|
51
|
+
end
|
52
|
+
|
53
|
+
def self.#{sorter_name}_col_text(obj, col)
|
54
|
+
return obj.send(col) if self.#{sorter_name}_in_resultset?(col)
|
55
|
+
return self.#{sorter_name}_print_text(col)
|
56
|
+
end
|
57
|
+
|
58
|
+
def self.#{sorter_name}_yaml_path
|
59
|
+
raise "RAILS_ROOT is not defined" unless defined?(RAILS_ROOT)
|
60
|
+
#klass_name = self.class_name.downcase
|
61
|
+
klass_name = Inflector.underscore(self.class_name)
|
62
|
+
file_name = "#{sorter_name}.yml"
|
63
|
+
if sorter_options[:subclass_name]
|
64
|
+
sub_path = File.join(klass_name, Inflector.underscore(sorter_options[:subclass_name]), file_name)
|
65
|
+
else
|
66
|
+
sub_path = File.join(klass_name, file_name)
|
67
|
+
end
|
68
|
+
if sorter_options[:path_prefix]
|
69
|
+
return File.join(RAILS_ROOT, sorter_options[:path_prefix], sub_path)
|
70
|
+
else
|
71
|
+
#defaults to col_defs subdirectory in app/models
|
72
|
+
return File.join(RAILS_ROOT, "app/models/col_defs", sub_path)
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
def self.#{sorter_name}_initialize_col_defs
|
77
|
+
YAML.load_file(#{sorter_name}_yaml_path)
|
78
|
+
end
|
79
|
+
|
80
|
+
def self.#{sorter_name}_col_def_hash
|
81
|
+
@@#{sorter_name}_col_def_hash ||= #{sorter_name}_initialize_col_def_hash
|
82
|
+
end
|
83
|
+
|
84
|
+
def self.#{sorter_name}_initialize_col_def_hash
|
85
|
+
col_def_hash = {}
|
86
|
+
#{sorter_name}_col_defs.each do |c|
|
87
|
+
c.keys.each do |key|
|
88
|
+
col_def_hash[key] = c[key]
|
89
|
+
end
|
90
|
+
end
|
91
|
+
col_def_hash
|
92
|
+
end
|
93
|
+
|
94
|
+
def self.#{sorter_name}_col_keys_in_order
|
95
|
+
@@#{sorter_name}_col_keys_in_order ||= #{sorter_name}_initialize_col_keys_in_order
|
96
|
+
end
|
97
|
+
|
98
|
+
def self.#{sorter_name}_initialize_col_keys_in_order
|
99
|
+
cols = []
|
100
|
+
#{sorter_name}_col_defs.each do |hsh|
|
101
|
+
hsh.each do |key, sub_hash|
|
102
|
+
cols << key
|
103
|
+
end
|
104
|
+
end
|
105
|
+
cols
|
106
|
+
end
|
107
|
+
|
108
|
+
def self.#{sorter_name}_heading(col)
|
109
|
+
return false if #{sorter_name}_col_def_hash[col]['heading'] == false
|
110
|
+
#{sorter_name}_col_def_hash[col]['heading'] || col.humanize
|
111
|
+
end
|
112
|
+
|
113
|
+
def self.#{sorter_name}_headings_in_order
|
114
|
+
@@#{sorter_name}_headings_in_order ||= #{sorter_name}_initialize_headings_in_order
|
115
|
+
end
|
116
|
+
|
117
|
+
def self.#{sorter_name}_initialize_headings_in_order
|
118
|
+
headings = []
|
119
|
+
#{sorter_name}_col_keys_in_order.each do |key|
|
120
|
+
headings << #{sorter_name}_heading(key) if #{sorter_name}_heading(key)
|
121
|
+
end
|
122
|
+
headings
|
123
|
+
end
|
124
|
+
|
125
|
+
def self.#{sorter_name}_col_def(col)
|
126
|
+
#{sorter_name}_col_def_hash[col]
|
127
|
+
end
|
128
|
+
|
129
|
+
def self.#{sorter_name}_datatype(col)
|
130
|
+
#{sorter_name}_col_def_hash[col]['datatype']
|
131
|
+
end
|
132
|
+
|
133
|
+
def self.#{sorter_name}_sort_options(col)
|
134
|
+
#{sorter_name}_col_def_hash[col]['sort_options']
|
135
|
+
end
|
136
|
+
|
137
|
+
def self.#{sorter_name}_default_sort_dir(col)
|
138
|
+
if sort_ops = #{sorter_name}_col_def_hash[col]['sort_options']
|
139
|
+
sort_ops['default_dir'] ? sort_ops['default_dir'] : 'asc'
|
140
|
+
else
|
141
|
+
'asc'
|
142
|
+
end
|
143
|
+
end
|
144
|
+
|
145
|
+
def self.#{sorter_name}_print_options(col)
|
146
|
+
if #{sorter_name}_col_def_hash[col]
|
147
|
+
#{sorter_name}_col_def_hash[col]['print_options']
|
148
|
+
end
|
149
|
+
end
|
150
|
+
|
151
|
+
def self.#{sorter_name}_td_class(col)
|
152
|
+
#{sorter_name}_col_def_hash[col]['td_class']
|
153
|
+
end
|
154
|
+
|
155
|
+
def self.#{sorter_name}_th_class(col)
|
156
|
+
#{sorter_name}_col_def_hash[col]['th_class']
|
157
|
+
end
|
158
|
+
|
159
|
+
def self.#{sorter_name}_precision(col)
|
160
|
+
#{sorter_name}_col_def_hash[col]['precision']
|
161
|
+
end
|
162
|
+
|
163
|
+
def self.#{sorter_name}_delimiter(col)
|
164
|
+
#{sorter_name}_col_def_hash[col]['delimiter'] || ","
|
165
|
+
end
|
166
|
+
|
167
|
+
def self.#{sorter_name}_separator(col)
|
168
|
+
#{sorter_name}_col_def_hash[col]['separator'] || "."
|
169
|
+
end
|
170
|
+
|
171
|
+
def self.#{sorter_name}_unit(col)
|
172
|
+
#{sorter_name}_col_def_hash[col]['unit'] || "$"
|
173
|
+
end
|
174
|
+
|
175
|
+
def self.#{sorter_name}_print_text(col)
|
176
|
+
#{sorter_name}_col_def_hash[col]['print_text'] || ''
|
177
|
+
end
|
178
|
+
|
179
|
+
def self.#{sorter_name}_sortable?(col)
|
180
|
+
hsh = #{sorter_name}_col_def_hash[col]
|
181
|
+
return false if hsh.has_key?('sortable') && hsh['sortable'] == false
|
182
|
+
return false if hsh.has_key?('heading') && hsh['heading'] == false
|
183
|
+
return true
|
184
|
+
end
|
185
|
+
|
186
|
+
def self.#{sorter_name}_link_options(col)
|
187
|
+
link_ops = #{sorter_name}_col_def_hash[col]['link_options']
|
188
|
+
return link_ops.symbolize_keys! if link_ops
|
189
|
+
end
|
190
|
+
|
191
|
+
def self.#{sorter_name}_link?(col)
|
192
|
+
return true if #{sorter_name}_link_options(col)
|
193
|
+
return false
|
194
|
+
end
|
195
|
+
|
196
|
+
def self.#{sorter_name}_in_resultset?(col)
|
197
|
+
hsh = #{sorter_name}_col_def_hash[col]
|
198
|
+
return false if hsh.has_key?('in_resultset') && hsh['in_resultset'] == false
|
199
|
+
return true
|
200
|
+
end
|
201
|
+
|
202
|
+
def self.#{sorter_name}_col_def_for_yui(col)
|
203
|
+
label = #{sorter_name}_heading(col) ? #{sorter_name}_heading(col) : ''
|
204
|
+
sortable = #{sorter_name}_sortable?(col)
|
205
|
+
datatype = #{sorter_name}_datatype(col)
|
206
|
+
if datatype == 'number' or datatype == 'currency'
|
207
|
+
formatter = datatype
|
208
|
+
end
|
209
|
+
sort_dir = #{sorter_name}_default_sort_dir(col)
|
210
|
+
if sort_dir == 'desc'
|
211
|
+
sort_ops = {:defaultDir => "YAHOO.widget.DataTable.CLASS_DESC"}
|
212
|
+
end
|
213
|
+
yui = {:key => col, :label => label, :sortable => sortable}
|
214
|
+
yui[:sortOptions] = sort_ops if sort_ops
|
215
|
+
yui[:formatter] = formatter if formatter
|
216
|
+
yui
|
217
|
+
end
|
218
|
+
|
219
|
+
def self.#{sorter_name}_col_defs_for_yui
|
220
|
+
yui_col_defs = []
|
221
|
+
#{sorter_name}_col_keys_in_order.each do |col|
|
222
|
+
yui_col_defs << #{sorter_name}_col_def_for_yui(col)
|
223
|
+
end
|
224
|
+
yui_col_defs
|
225
|
+
end
|
226
|
+
|
227
|
+
def self.#{sorter_name}_field_def_for_yui(col)
|
228
|
+
datatype = #{sorter_name}_datatype(col)
|
229
|
+
yui_field_def = {:key => col}
|
230
|
+
if datatype == 'number'
|
231
|
+
yui_field_def[:parser] = "YAHOO.util.DataSource.parseNumber"
|
232
|
+
end
|
233
|
+
if datatype == 'currency'
|
234
|
+
yui_field_def[:parser] = "this.parseNumberFromCurrency"
|
235
|
+
end
|
236
|
+
yui_field_def
|
237
|
+
end
|
238
|
+
|
239
|
+
def self.#{sorter_name}_fields_for_yui
|
240
|
+
yui_fields = []
|
241
|
+
#{sorter_name}_col_keys_in_order.each do |col|
|
242
|
+
yui_fields << #{sorter_name}_field_def_for_yui(col)
|
243
|
+
end
|
244
|
+
yui_fields
|
245
|
+
end
|
246
|
+
|
247
|
+
|
248
|
+
END
|
249
|
+
|
250
|
+
end #sortable_columns
|
251
|
+
end #ClassMethods
|
252
|
+
end #Sortablecolumns
|
253
|
+
end #Acts
|
254
|
+
end #ActiveRecord
|