handles_sortable_columns 0.1.2 → 0.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.
data/MIT-LICENSE CHANGED
@@ -1,4 +1,4 @@
1
- Copyright (c) 2010 Alex Fortuna
1
+ Copyright (c) 2010-2011 Alex Fortuna
2
2
 
3
3
  Permission is hereby granted, free of charge, to any person obtaining
4
4
  a copy of this software and associated documentation files (the
data/README.html ADDED
@@ -0,0 +1,140 @@
1
+ <head>
2
+ <meta content="text/html; charset=utf-8" http-equiv="Content-Type" />
3
+ <link href="dev/github.css" rel="stylesheet" type="text/css" />
4
+ </head>
5
+
6
+ <h1 id="sortable-table-columns">Sortable Table Columns</h1>
7
+
8
+ <h2 id="introduction">Introduction</h2>
9
+
10
+ <p>A simple yet flexible Rails gem/plugin to quickly add sortable table columns to your controller and views.</p>
11
+
12
+ <h2 id="setup-rails-3">Setup (Rails 3)</h2>
13
+
14
+ <p>In your app’s <code>Gemfile</code>, add:</p>
15
+
16
+ <pre><code>gem "handles_sortable_columns"
17
+ </code></pre>
18
+
19
+ <p>To install the gem with RDoc/ri documentation, do a:</p>
20
+
21
+ <pre><code>$ gem install handles_sortable_columns
22
+ </code></pre>
23
+
24
+ <p>Otherwise, do a <code>bundle install</code>.</p>
25
+
26
+ <h2 id="setup-rails-2">Setup (Rails 2)</h2>
27
+
28
+ <p>In your app’s <code>config/environment.rb</code> add:</p>
29
+
30
+ <pre><code>config.gem "handles_sortable_columns"
31
+ </code></pre>
32
+
33
+ <p>To install the gem, do a:</p>
34
+
35
+ <pre><code>$ gem sources --add http://rubygems.org
36
+ $ gem install handles_sortable_columns
37
+ </code></pre>
38
+
39
+ <p>, or use <code>rake gems:install</code>.</p>
40
+
41
+ <h2 id="basic-usage">Basic Usage</h2>
42
+
43
+ <p>Activate the feature in your controller class:</p>
44
+
45
+ <pre><code>class MyController &lt; ApplicationController
46
+ handles_sortable_columns
47
+ ...
48
+ </code></pre>
49
+
50
+ <p>In a view, mark up sortable columns by using the <tt>sortable_column</tt> helper:</p>
51
+
52
+ <pre><code>&lt;%= sortable_column "Product" %&gt;
53
+ &lt;%= sortable_column "Price" %&gt;
54
+ </code></pre>
55
+
56
+ <p>In controller action, fetch and use the order clause according to current state of sortable columns:</p>
57
+
58
+ <pre><code>def index
59
+ order = sortable_column_order
60
+ @records = Article.order(order) # Rails 3.
61
+ @records = Article.all(:order =&gt; order) # Rails 2.
62
+ end
63
+ </code></pre>
64
+
65
+ <p>That’s it for basic usage. Production usage may require passing additional parameters to listed methods.</p>
66
+
67
+ <h2 id="production-usage">Production Usage</h2>
68
+
69
+ <p>Please take time to read the gem’s full <a href="http://rdoc.info/projects/dadooda/handles_sortable_columns">RDoc documentation</a>. This README has a limited coverage.</p>
70
+
71
+ <h3 id="configuration">Configuration</h3>
72
+
73
+ <p>Change names of GET parameters used for sorting and pagination:</p>
74
+
75
+ <pre><code>class MyController &lt; ApplicationController
76
+ handles_sortable_columns do |conf|
77
+ conf.sort_param = "s"
78
+ conf.page_param = "p"
79
+ end
80
+ ...
81
+ </code></pre>
82
+
83
+ <p>Change CSS class of all sortable column <code>&lt;a&gt;</code> tags:</p>
84
+
85
+ <pre><code>handles_sortable_columns do |conf|
86
+ conf.class = "SortableLink"
87
+ conf.indicator_class = {:asc =&gt; "AscSortableLink", :desc =&gt; "DescSortableLink"}
88
+ end
89
+ </code></pre>
90
+
91
+ <p>Change how text-based sort indicator looks like:</p>
92
+
93
+ <pre><code>handles_sortable_columns do |conf|
94
+ conf.indicator_text = {:asc =&gt; "[asc]", :desc =&gt; "[desc]"}
95
+ end
96
+ </code></pre>
97
+
98
+ <p>Disable text-based sort indicator completely:</p>
99
+
100
+ <pre><code>handles_sortable_columns do |conf|
101
+ conf.indicator_text = {}
102
+ end
103
+ </code></pre>
104
+
105
+ <h3 id="helper-options">Helper Options</h3>
106
+
107
+ <p>Explicitly specify column name:</p>
108
+
109
+ <pre><code>&lt;%= sortable_column "Highest Price", :column =&gt; "max_price" %&gt;
110
+ </code></pre>
111
+
112
+ <p>Specify CSS class for this particular link:</p>
113
+
114
+ <pre><code>&lt;%= sortable_column "Name", :class =&gt; "SortableLink" %&gt;
115
+ </code></pre>
116
+
117
+ <p>Specify sort direction on first click:</p>
118
+
119
+ <pre><code>&lt;%= sortable_column "Created At", :direction =&gt; :asc %&gt;
120
+ </code></pre>
121
+
122
+ <h3 id="fetching-sort-order">Fetching Sort Order</h3>
123
+
124
+ <p>To fetch sort order <strong>securely</strong>, with <strong>column name validation</strong>, <strong>default values</strong> and <strong>multiple sort criteria</strong>, use the block form of <code>sortable_column_order</code>:</p>
125
+
126
+ <pre><code>order = sortable_column_order do |column, direction|
127
+ case column
128
+ when "name"
129
+ "#{column} #{direction}"
130
+ when "created_at", "updated_at"
131
+ "#{column} #{direction}, name ASC"
132
+ else
133
+ "name ASC"
134
+ end
135
+ end
136
+ </code></pre>
137
+
138
+ <h2 id="feedback">Feedback</h2>
139
+
140
+ <p>Send bug reports, suggestions and criticisms through <a href="http://github.com/dadooda/handles_sortable_columns">project’s page on GitHub</a>.</p>
data/README.md CHANGED
@@ -9,16 +9,34 @@ Introduction
9
9
  A simple yet flexible Rails gem/plugin to quickly add sortable table columns to your controller and views.
10
10
 
11
11
 
12
- Setup
13
- -----
12
+ Setup (Rails 3)
13
+ ---------------
14
+
15
+ In your app's `Gemfile`, add:
16
+
17
+ gem "handles_sortable_columns"
18
+
19
+ To install the gem with RDoc/ri documentation, do a:
14
20
 
15
- $ gem sources --add http://rubygems.org
16
21
  $ gem install handles_sortable_columns
17
22
 
18
- In your app's `config/environment.rb` do a:
23
+ Otherwise, do a `bundle install`.
24
+
25
+
26
+ Setup (Rails 2)
27
+ ---------------
28
+
29
+ In your app's `config/environment.rb` add:
19
30
 
20
31
  config.gem "handles_sortable_columns"
21
32
 
33
+ To install the gem, do a:
34
+
35
+ $ gem sources --add http://rubygems.org
36
+ $ gem install handles_sortable_columns
37
+
38
+ , or use `rake gems:install`.
39
+
22
40
 
23
41
  Basic Usage
24
42
  -----------
@@ -27,7 +45,7 @@ Activate the feature in your controller class:
27
45
 
28
46
  class MyController < ApplicationController
29
47
  handles_sortable_columns
30
- ...
48
+ ...
31
49
 
32
50
  In a view, mark up sortable columns by using the <tt>sortable_column</tt> helper:
33
51
 
@@ -38,7 +56,8 @@ In controller action, fetch and use the order clause according to current state
38
56
 
39
57
  def index
40
58
  order = sortable_column_order
41
- @records = Article.all(:order => order)
59
+ @records = Article.order(order) # Rails 3.
60
+ @records = Article.all(:order => order) # Rails 2.
42
61
  end
43
62
 
44
63
  That's it for basic usage. Production usage may require passing additional parameters to listed methods.
@@ -59,7 +78,7 @@ Change names of GET parameters used for sorting and pagination:
59
78
  conf.sort_param = "s"
60
79
  conf.page_param = "p"
61
80
  end
62
- ...
81
+ ...
63
82
 
64
83
  Change CSS class of all sortable column `<a>` tags:
65
84
 
data/Rakefile CHANGED
@@ -1,4 +1,5 @@
1
1
  require "rake/rdoctask"
2
+ require "yaml"
2
3
 
3
4
  GEM_NAME = "handles_sortable_columns"
4
5
 
@@ -14,10 +15,9 @@ begin
14
15
  gem.files = FileList[
15
16
  "[A-Z]*",
16
17
  "*.gemspec",
17
- "lib/**/*.rb",
18
18
  "init.rb",
19
- ] - ["README.html"]
20
- gem.extra_rdoc_files = ["README.md"]
19
+ "lib/**/*.rb",
20
+ ]
21
21
  end
22
22
  rescue LoadError
23
23
  STDERR.puts "This gem requires Jeweler to be built"
@@ -28,11 +28,20 @@ task :rebuild => [:gemspec, :build]
28
28
 
29
29
  desc "Push (publish) gem to RubyGems (aka Gemcutter)"
30
30
  task :push => :rebuild do
31
- # Yet found no way to ask Jeweler forge a complete version string for us.
32
- vh = YAML.load(File.read("VERSION.yml"))
33
- version = [vh[:major], vh[:minor], vh[:patch]].join(".")
34
- pkgfile = File.join("pkg", [GEM_NAME, "-", version, ".gem"].to_s)
35
- system("gem", "push", pkgfile)
31
+ # NOTE: Yet found no way to ask Jeweler forge a complete version string for us.
32
+ h = YAML.load_file("VERSION.yml")
33
+ version = [h[:major], h[:minor], h[:patch], h[:build]].compact.join(".")
34
+ pkgfile = File.join("pkg", "#{GEM_NAME}-#{version}.gem")
35
+ Kernel.system("gem", "push", pkgfile)
36
+ end
37
+
38
+ desc "Generate RDoc documentation"
39
+ Rake::RDocTask.new(:rdoc) do |rdoc|
40
+ rdoc.rdoc_dir = "doc"
41
+ rdoc.title = "Handles::SortableColumns"
42
+ #rdoc.options << "--line-numbers"
43
+ #rdoc.options << "--inline-source"
44
+ rdoc.rdoc_files.include("lib/**/*.rb")
36
45
  end
37
46
 
38
47
  desc "Compile README preview"
data/VERSION.yml CHANGED
@@ -1,4 +1,5 @@
1
1
  ---
2
2
  :major: 0
3
3
  :minor: 1
4
- :patch: 2
4
+ :patch: 3
5
+ #:build: pre1
@@ -1,42 +1,39 @@
1
1
  # Generated by jeweler
2
- # DO NOT EDIT THIS FILE
3
- # Instead, edit Jeweler::Tasks in Rakefile, and run `rake gemspec`
2
+ # DO NOT EDIT THIS FILE DIRECTLY
3
+ # Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec'
4
4
  # -*- encoding: utf-8 -*-
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = %q{handles_sortable_columns}
8
- s.version = "0.1.2"
8
+ s.version = "0.1.3"
9
9
 
10
10
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
11
  s.authors = ["Alex Fortuna"]
12
- s.date = %q{2010-09-08}
12
+ s.date = %q{2011-07-29}
13
13
  s.description = %q{Sortable Table Columns}
14
14
  s.email = %q{alex.r@askit.org}
15
15
  s.extra_rdoc_files = [
16
+ "README.html",
16
17
  "README.md"
17
18
  ]
18
19
  s.files = [
19
20
  "MIT-LICENSE",
20
- "README.md",
21
- "Rakefile",
22
- "VERSION.yml",
23
- "handles_sortable_columns.gemspec",
24
- "init.rb",
25
- "lib/action_controller/base/handles_sortable_columns.rb",
26
- "lib/handles/sortable_columns.rb",
27
- "lib/handles_sortable_columns.rb"
21
+ "README.html",
22
+ "README.md",
23
+ "Rakefile",
24
+ "VERSION.yml",
25
+ "handles_sortable_columns.gemspec",
26
+ "init.rb",
27
+ "lib/action_controller/base/handles_sortable_columns.rb",
28
+ "lib/handles/sortable_columns.rb",
29
+ "lib/handles_sortable_columns.rb"
28
30
  ]
29
31
  s.homepage = %q{http://github.com/dadooda/handles_sortable_columns}
30
- s.rdoc_options = ["--charset=UTF-8"]
31
32
  s.require_paths = ["lib"]
32
- s.rubygems_version = %q{1.3.7}
33
+ s.rubygems_version = %q{1.6.2}
33
34
  s.summary = %q{Sortable Table Columns}
34
- s.test_files = [
35
- "spec/handles_sortable_columns_spec.rb"
36
- ]
37
35
 
38
36
  if s.respond_to? :specification_version then
39
- current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
40
37
  s.specification_version = 3
41
38
 
42
39
  if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
@@ -45,3 +42,4 @@ Gem::Specification.new do |s|
45
42
  else
46
43
  end
47
44
  end
45
+
@@ -1,3 +1,5 @@
1
- class ActionController::Base #:nodoc:
2
- include ::Handles::SortableColumns
1
+ module ActionController #:nodoc:
2
+ class Base #:nodoc:
3
+ include ::Handles::SortableColumns
4
+ end
3
5
  end
@@ -9,7 +9,7 @@ module Handles #:nodoc:
9
9
  #
10
10
  # class MyController < ApplicationController
11
11
  # handles_sortable_columns
12
- # ...
12
+ # ...
13
13
  #
14
14
  # In a view, mark up sortable columns by using the <tt>sortable_column</tt> helper:
15
15
  #
@@ -20,30 +20,30 @@ module Handles #:nodoc:
20
20
  #
21
21
  # def index
22
22
  # order = sortable_column_order
23
- # @records = Article.all(:order => order)
23
+ # @records = Article.order(order) # Rails 3.
24
+ # @records = Article.all(:order => order) # Rails 2.
24
25
  # end
25
26
  #
26
27
  # That's it for basic usage. Production usage may require passing additional parameters to listed methods.
27
28
  #
28
29
  # See also:
29
- # * <tt>MetaClassMethods#handles_sortable_columns</tt>
30
- # * <tt>HelperMethods#sortable_column</tt>
31
- # * <tt>InstanceMethods#sortable_column_order</tt>
30
+ # * MetaClassMethods#handles_sortable_columns
31
+ # * InstanceMethods#sortable_column_order
32
32
  module SortableColumns
33
- def self.included(owner)
33
+ def self.included(owner) #:nodoc:
34
34
  owner.extend MetaClassMethods
35
35
  end
36
36
 
37
- # Sortable columns configuration object. Passed to block when you do a:
37
+ # Sortable columns configuration object. Passed to the block when you do a:
38
38
  #
39
- # handles_sortable_column do |conf|
39
+ # handles_sortable_columns do |conf|
40
40
  # ...
41
41
  # end
42
42
  class Config
43
43
  # CSS class for link (regardless of sorted state). Default:
44
44
  #
45
- # nil
46
- attr_accessor :class
45
+ # SortableColumnLink
46
+ attr_accessor :link_class
47
47
 
48
48
  # GET parameter name for page number. Default:
49
49
  #
@@ -67,30 +67,33 @@ module Handles #:nodoc:
67
67
 
68
68
  def initialize(attrs = {})
69
69
  defaults = {
70
- :page_param => "page",
71
- :sort_param => "sort",
72
- :indicator_text => {:asc => "&nbsp;&darr;&nbsp;", :desc => "&nbsp;&uarr;&nbsp;"},
73
- :indicator_class => {:asc => "SortedAsc", :desc => "SortedDesc"},
70
+ :link_class => "SortableColumnLink",
71
+ :indicator_class => {:asc => "SortedAsc", :desc => "SortedDesc"},
72
+ :indicator_text => {:asc => "&nbsp;&darr;&nbsp;", :desc => "&nbsp;&uarr;&nbsp;"},
73
+ :page_param => "page",
74
+ :sort_param => "sort",
74
75
  }
75
76
 
76
77
  defaults.merge(attrs).each {|k, v| send("#{k}=", v)}
77
78
  end
78
79
 
80
+ # Bracket access for convenience.
79
81
  def [](key)
80
82
  send(key)
81
83
  end
82
84
 
85
+ # Bracket access for convenience.
83
86
  def []=(key, value)
84
87
  send("#{key}=", value)
85
88
  end
86
89
  end # Config
87
90
 
88
91
  module MetaClassMethods
89
- # Activate and optionally configure the sortable columns.
92
+ # Activate and optionally configure the sortable columns feature in your controller.
90
93
  #
91
94
  # class MyController < ApplicationController
92
95
  # handles_sortable_columns
93
- # end
96
+ # ...
94
97
  #
95
98
  # With configuration:
96
99
  #
@@ -101,42 +104,43 @@ module Handles #:nodoc:
101
104
  # conf.indicator_text = {}
102
105
  # ...
103
106
  # end
104
- # end
107
+ # ...
108
+ #
109
+ # With filter options:
110
+ #
111
+ # class MyController < ApplicationController
112
+ # handles_sortable_columns(:only => [:index]) do |conf|
113
+ # ...
114
+ # end
115
+ # ...
105
116
  #
106
- # <tt>conf</tt> is a <tt>Config</tt> object.
107
- def handles_sortable_columns(&block)
117
+ # NOTE: <tt>conf</tt> is a Config object.
118
+ def handles_sortable_columns(fopts = {}, &block)
108
119
  # Multiple activation protection.
109
120
  if not self < InstanceMethods
110
- extend ClassMethods
111
121
  include InstanceMethods
112
- helper HelperMethods
122
+ helper_method :sortable_column
113
123
  end
114
124
 
115
- # Configuration is processed at every activation.
116
- yield(sortable_columns_config) if block
125
+ # Process configuration at every activation.
126
+ before_filter(fopts) do |ac|
127
+ ac.instance_eval do
128
+ # NOTE: Can't `yield`, we're in a block already.
129
+ block.call(sortable_columns_config) if block
130
+ end
131
+ end
117
132
  end
118
133
  end # MetaClassMethods
119
134
 
120
- module ClassMethods
121
- # Internal/advanced use only. Access/initialize the sortable columns config.
122
- def sortable_columns_config
123
- # NOTE: This is controller's class instance variable.
124
- @sortable_columns_config ||= ::Handles::SortableColumns::Config.new
125
- end
126
-
127
- # Internal/advanced use only. Convert title to sortable column name.
128
- #
129
- # sortable_column_name_from_title("ProductName") # => "product_name"
130
- def sortable_column_name_from_title(title)
131
- title.gsub(/(\s)(\S)/) {$2.upcase}.underscore
132
- end
135
+ module InstanceMethods
136
+ private
133
137
 
134
138
  # Internal/advanced use only. Parse sortable column sort param into a Hash with predefined keys.
135
139
  #
136
140
  # parse_sortable_column_sort_param("name") # => {:column => "name", :direction => :asc}
137
141
  # parse_sortable_column_sort_param("-name") # => {:column => "name", :direction => :desc}
138
142
  # parse_sortable_column_sort_param("") # => {:column => nil, :direction => nil}
139
- def parse_sortable_column_sort_param(sort)
143
+ def parse_sortable_column_sort_param(sort) #:nodoc:
140
144
  out = {:column => nil, :direction => nil}
141
145
  if sort.to_s.strip.match /\A((?:-|))([^-]+)\z/
142
146
  out[:direction] = $1.empty?? :asc : :desc
@@ -144,96 +148,45 @@ module Handles #:nodoc:
144
148
  end
145
149
  out
146
150
  end
147
- end # ClassMethods
148
-
149
- module InstanceMethods
150
- protected
151
-
152
- # Compile SQL order clause according to current state of sortable columns.
153
- #
154
- # Basic (kickstart) usage:
155
- #
156
- # order = sortable_column_order
157
- #
158
- # <b>WARNING!</b> Basic usage is <b>not recommended</b> for production since it is potentially
159
- # vulnerable to SQL injection!
160
- #
161
- # Production usage with multiple sort criteria, column name validation and defaults:
162
- #
163
- # order = sortable_column_order do |column, direction|
164
- # case column
165
- # when "name"
166
- # "#{column} #{direction}"
167
- # when "created_at", "updated_at"
168
- # "#{column} #{direction}, name ASC"
169
- # else
170
- # "name ASC"
171
- # end
172
- # end
173
- #
174
- # Apply order:
175
- #
176
- # @records = Article.all(:order => order) # Rails 2.x.
177
- # @records = Article.order(order) # Rails 3.
178
- def sortable_column_order(&block)
179
- conf = {}
180
- conf[k = :sort_param] = self.class.sortable_columns_config[k]
181
-
182
- # Parse sort param.
183
- pp = self.class.parse_sortable_column_sort_param(params[conf[:sort_param]])
184
-
185
- order = if block
186
- yield(pp[:column], pp[:direction])
187
- else
188
- # No block -- do a straight mapping.
189
- if pp[:column]
190
- [pp[:column], pp[:direction]].join(" ")
191
- end
192
- end
193
151
 
194
- # Can be nil.
195
- order
196
- end
197
- end # InstanceMethods
198
-
199
- module HelperMethods
200
152
  # Render a sortable column link.
201
153
  #
202
154
  # Options:
203
- # * <tt>:column</tt> -- Column name. E.g. <tt>"created_at"</tt>.
155
+ #
156
+ # * <tt>:column</tt> -- Column name. E.g. <tt>created_at</tt>.
204
157
  # * <tt>:direction</tt> -- Sort direction on first click. <tt>:asc</tt> or <tt>:desc</tt>. Default is <tt>:asc</tt>.
205
- # * <tt>:class</tt> -- CSS class for link (regardless of sorted state).
206
- # * <tt>:style</tt> -- CSS style for link (regardless of sorted state).
158
+ # * <tt>:link_class</tt> -- CSS class for link, regardless of sorted state.
159
+ # * <tt>:link_style</tt> -- CSS style for link, regardless of sorted state.
207
160
  #
208
161
  # Examples:
209
162
  #
210
163
  # <%= sortable_column "Product" %>
211
- # <%= sortable_column "Highest Price", :column_name => "max_price" %>
212
- # <%= sortable_column "Name", :class => "SortableLink" %>
164
+ # <%= sortable_column "Highest Price", :column => "max_price" %>
165
+ # <%= sortable_column "Name", :link_class => "SortableLink" %>
213
166
  # <%= sortable_column "Created At", :direction => :asc %>
214
- def sortable_column(title, options = {})
167
+ def sortable_column(title, options = {}) #:doc:
215
168
  options = options.dup
216
169
  o = {}
217
170
  conf = {}
218
- conf[k = :sort_param] = controller.class.sortable_columns_config[k]
219
- conf[k = :page_param] = controller.class.sortable_columns_config[k]
220
- conf[k = :indicator_text] = controller.class.sortable_columns_config[k]
221
- conf[k = :indicator_class] = controller.class.sortable_columns_config[k]
171
+ conf[k = :sort_param] = sortable_columns_config[k]
172
+ conf[k = :page_param] = sortable_columns_config[k]
173
+ conf[k = :indicator_text] = sortable_columns_config[k]
174
+ conf[k = :indicator_class] = sortable_columns_config[k]
222
175
 
223
176
  #HELP sortable_column
224
- o[k = :column] = options.delete(k) || controller.class.sortable_column_name_from_title(title)
177
+ o[k = :column] = options.delete(k) || sortable_column_title_to_name(title)
225
178
  o[k = :direction] = options.delete(k).to_s.downcase =~ /\Adesc\z/ ? :desc : :asc
226
- o[k = :class] = options.delete(k) || controller.class.sortable_columns_config[k]
227
- o[k = :style] = options.delete(k)
179
+ o[k = :link_class] = options.delete(k) || sortable_columns_config[k]
180
+ o[k = :link_style] = options.delete(k)
228
181
  #HELP /sortable_column
229
182
 
230
183
  raise "Unknown option(s): #{options.inspect}" if not options.empty?
231
184
 
232
185
  # Parse sort param.
233
- pp = controller.class.parse_sortable_column_sort_param(params[conf[:sort_param]])
186
+ pp = parse_sortable_column_sort_param(params[conf[:sort_param]])
234
187
 
235
188
  css_class = []
236
- if (s = o[:class]).present?
189
+ if (s = o[:link_class]).present?
237
190
  css_class << s
238
191
  end
239
192
 
@@ -247,11 +200,14 @@ module Handles #:nodoc:
247
200
 
248
201
  html_options = {}
249
202
  html_options[:class] = css_class.join(" ") if css_class.present?
250
- html_options[:style] = o[:style] if o[:style].present?
203
+ html_options[:style] = o[:link_style] if o[:link_style].present?
204
+
205
+ # Rails 3 / Rails 2 fork.
206
+ tpl = respond_to?(:view_context) ? view_context : @template
251
207
 
252
208
  # Already sorted?
253
209
  if pp[:column] == o[:column].to_s
254
- pcs << link_to(title, params.merge({conf[:sort_param] => [("-" if pp[:direction] == :asc), o[:column]].join, conf[:page_param] => 1}), html_options) # Opposite sort order when clicked.
210
+ pcs << tpl.link_to(title, params.merge({conf[:sort_param] => [("-" if pp[:direction] == :asc), o[:column]].join, conf[:page_param] => 1}), html_options) # Opposite sort order when clicked.
255
211
 
256
212
  # Append indicator, if configured.
257
213
  if (s = conf[:indicator_text][pp[:direction]]).present?
@@ -259,12 +215,71 @@ module Handles #:nodoc:
259
215
  end
260
216
  else
261
217
  # Not sorted.
262
- pcs << link_to(title, params.merge({conf[:sort_param] => [("-" if o[:direction] != :asc), o[:column]].join, conf[:page_param] => 1}), html_options)
218
+ pcs << tpl.link_to(title, params.merge({conf[:sort_param] => [("-" if o[:direction] != :asc), o[:column]].join, conf[:page_param] => 1}), html_options)
263
219
  end
264
220
 
265
221
  # For Rails 3 provide #html_safe.
266
222
  (v = pcs.join).respond_to?(:html_safe) ? v.html_safe : v
267
223
  end
268
- end # HelperMethods
224
+
225
+ # Compile SQL order clause according to current state of sortable columns.
226
+ #
227
+ # Basic (kickstart) usage:
228
+ #
229
+ # order = sortable_column_order
230
+ #
231
+ # <b>WARNING:</b> Basic usage is <b>not recommended</b> for production since it is potentially
232
+ # vulnerable to SQL injection!
233
+ #
234
+ # Production usage with multiple sort criteria, column name validation and defaults:
235
+ #
236
+ # order = sortable_column_order do |column, direction|
237
+ # case column
238
+ # when "name"
239
+ # "#{column} #{direction}"
240
+ # when "created_at", "updated_at"
241
+ # "#{column} #{direction}, name ASC"
242
+ # else
243
+ # "name ASC"
244
+ # end
245
+ # end
246
+ #
247
+ # Apply order:
248
+ #
249
+ # @records = Article.order(order) # Rails 3.
250
+ # @records = Article.all(:order => order) # Rails 2.
251
+ def sortable_column_order(&block)
252
+ conf = {}
253
+ conf[k = :sort_param] = sortable_columns_config[k]
254
+
255
+ # Parse sort param.
256
+ pp = parse_sortable_column_sort_param(params[conf[:sort_param]])
257
+
258
+ order = if block
259
+ column, direction = pp[:column], pp[:direction]
260
+ yield(column, direction) # NOTE: Makes RDoc/ri look a little smarter.
261
+ else
262
+ # No block -- do a straight mapping.
263
+ if pp[:column]
264
+ [pp[:column], pp[:direction]].join(" ")
265
+ end
266
+ end
267
+
268
+ # Can be nil.
269
+ order
270
+ end
271
+
272
+ # Internal use only. Convert title to sortable column name.
273
+ #
274
+ # sortable_column_title_to_name("ProductName") # => "product_name"
275
+ def sortable_column_title_to_name(title) #:nodoc:
276
+ title.gsub(/(\s)(\S)/) {$2.upcase}.underscore
277
+ end
278
+
279
+ # Internal use only. Access/initialize feature's config.
280
+ def sortable_columns_config #:nodoc:
281
+ @sortable_columns_config ||= ::Handles::SortableColumns::Config.new
282
+ end
283
+ end # InstanceMethods
269
284
  end # SortableColumns
270
285
  end # Handles
metadata CHANGED
@@ -1,13 +1,8 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: handles_sortable_columns
3
3
  version: !ruby/object:Gem::Version
4
- hash: 31
5
- prerelease: false
6
- segments:
7
- - 0
8
- - 1
9
- - 2
10
- version: 0.1.2
4
+ prerelease:
5
+ version: 0.1.3
11
6
  platform: ruby
12
7
  authors:
13
8
  - Alex Fortuna
@@ -15,7 +10,7 @@ autorequire:
15
10
  bindir: bin
16
11
  cert_chain: []
17
12
 
18
- date: 2010-09-08 00:00:00 +04:00
13
+ date: 2011-07-29 00:00:00 +04:00
19
14
  default_executable:
20
15
  dependencies: []
21
16
 
@@ -26,9 +21,11 @@ executables: []
26
21
  extensions: []
27
22
 
28
23
  extra_rdoc_files:
24
+ - README.html
29
25
  - README.md
30
26
  files:
31
27
  - MIT-LICENSE
28
+ - README.html
32
29
  - README.md
33
30
  - Rakefile
34
31
  - VERSION.yml
@@ -37,14 +34,13 @@ files:
37
34
  - lib/action_controller/base/handles_sortable_columns.rb
38
35
  - lib/handles/sortable_columns.rb
39
36
  - lib/handles_sortable_columns.rb
40
- - spec/handles_sortable_columns_spec.rb
41
37
  has_rdoc: true
42
38
  homepage: http://github.com/dadooda/handles_sortable_columns
43
39
  licenses: []
44
40
 
45
41
  post_install_message:
46
- rdoc_options:
47
- - --charset=UTF-8
42
+ rdoc_options: []
43
+
48
44
  require_paths:
49
45
  - lib
50
46
  required_ruby_version: !ruby/object:Gem::Requirement
@@ -52,25 +48,19 @@ required_ruby_version: !ruby/object:Gem::Requirement
52
48
  requirements:
53
49
  - - ">="
54
50
  - !ruby/object:Gem::Version
55
- hash: 3
56
- segments:
57
- - 0
58
51
  version: "0"
59
52
  required_rubygems_version: !ruby/object:Gem::Requirement
60
53
  none: false
61
54
  requirements:
62
55
  - - ">="
63
56
  - !ruby/object:Gem::Version
64
- hash: 3
65
- segments:
66
- - 0
67
57
  version: "0"
68
58
  requirements: []
69
59
 
70
60
  rubyforge_project:
71
- rubygems_version: 1.3.7
61
+ rubygems_version: 1.6.2
72
62
  signing_key:
73
63
  specification_version: 3
74
64
  summary: Sortable Table Columns
75
- test_files:
76
- - spec/handles_sortable_columns_spec.rb
65
+ test_files: []
66
+
@@ -1,42 +0,0 @@
1
- describe "ClassMethods" do
2
- module WrapSortableColumnsClassMethods
3
- class MyController < ActionController::Base
4
- handles_sortable_columns
5
- end
6
- end
7
-
8
- describe "#sortable_column_name_from_title" do
9
- it "generally works" do
10
- tests = [
11
- ["Product", "product"],
12
- ["product", "product"],
13
- ["created_at", "created_at"],
14
- ["created at", "created_at"],
15
- ["CreatedAt", "created_at"],
16
- ["Created At", "created_at"],
17
- ]
18
-
19
- tests.each do |input, expected|
20
- WrapSortableColumnsClassMethods::MyController.sortable_column_name_from_title(input).should == expected
21
- end
22
- end
23
- end # #sortable_column_name_from_title
24
-
25
- describe "#parse_sortable_column_sort_param" do
26
- it "generally works" do
27
- tests = [
28
- ["name", {:column => "name", :direction => :asc}],
29
- ["-name", {:column => "name", :direction => :desc}],
30
- [" -name ", {:column => "name", :direction => :desc}],
31
- ["", {:column => nil, :direction => nil}],
32
- ["-", {:column => nil, :direction => nil}],
33
- ["- name", {:column => "name", :direction => :desc}],
34
- ["--kaka", {:column => nil, :direction => nil}],
35
- ]
36
-
37
- tests.each do |input, expected|
38
- WrapSortableColumnsClassMethods::MyController.parse_sortable_column_sort_param(input).should == expected
39
- end
40
- end
41
- end # #parse_sortable_column_sort_param
42
- end # ClassMethods