handles_sortable_columns 0.1.2 → 0.1.3

Sign up to get free protection for your applications and to get access to all the features.
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