sorted 0.3.8 → 0.3.9
Sign up to get free protection for your applications and to get access to all the features.
- data/.document +0 -2
- data/README.rdoc +67 -45
- data/lib/sorted.rb +1 -2
- data/lib/sorted/orms/active_record.rb +17 -0
- data/lib/sorted/parser.rb +79 -0
- data/lib/sorted/railtie.rb +2 -2
- data/lib/sorted/toggler.rb +8 -1
- data/lib/sorted/version.rb +1 -1
- data/lib/sorted/view_helpers/action_view.rb +19 -4
- data/sorted.gemspec +1 -2
- data/spec/sorted/orms/active_record_spec.rb +11 -0
- data/spec/sorted/parser_spec.rb +90 -0
- data/spec/sorted/toggler_spec.rb +57 -0
- data/spec/sorted/view_helpers/action_view_spec.rb +37 -0
- data/spec/spec_helper.rb +2 -2
- metadata +17 -17
- data/.watchr +0 -24
- data/lib/sorted/finders/active_record.rb +0 -41
- data/lib/sorted/sorter.rb +0 -122
- data/spec/sorted_spec.rb +0 -122
- data/spec/sorter_spec.rb +0 -65
- data/spec/toggler_spec.rb +0 -39
data/.document
CHANGED
data/README.rdoc
CHANGED
@@ -1,87 +1,109 @@
|
|
1
1
|
= sorted
|
2
2
|
|
3
|
-
Sorted is a simple object that will take an sql order string and a url
|
3
|
+
Sorted is a simple object that will take an sql order string and a url
|
4
|
+
sort string to let you sort large datasets over many pages (using
|
5
|
+
{will_paginate}[http://github.com/mislav/will_paginatea] or
|
6
|
+
{kaminari}[https://github.com/amatsuda/kaminari]) without loosing state.
|
4
7
|
|
5
|
-
|
6
|
-
|
7
|
-
== Example
|
8
|
+
If you would like to see it in action clone the
|
9
|
+
{example app}[https://github.com/mynameisrufus/sorted_app]
|
8
10
|
|
9
11
|
=== Gemfile
|
10
12
|
|
11
|
-
gem sorted
|
13
|
+
gem 'sorted' '~> 0.3.9'
|
12
14
|
|
13
15
|
=== View
|
14
16
|
|
15
17
|
link_to_sorted "Email", :email
|
16
18
|
|
17
|
-
This will
|
19
|
+
This will generate a link with a url like this:
|
18
20
|
|
19
21
|
http://myapp/users?sort=email_asc
|
20
22
|
|
21
|
-
|
23
|
+
and on the next page load when you then sort by something else....
|
22
24
|
|
23
25
|
http://myapp/users?sort=name_asc!email_asc
|
24
26
|
|
25
27
|
=== Model
|
26
28
|
|
27
|
-
This will initially sort by email ascending
|
29
|
+
This will initially sort by email ascending with the optional second
|
30
|
+
default order argument:
|
31
|
+
|
32
|
+
@users = User.sort(params[:sort], "email ASC").page(params[:page])
|
33
|
+
|
34
|
+
==== Joins and includes
|
35
|
+
|
36
|
+
If you want to sort by a belongs to relationship add the table name to
|
37
|
+
the order argument. For example assuming a user belongs to a company:
|
38
|
+
|
39
|
+
@users = User.joins(:company).sort(params[:sort], "companies.name ASC").page(params[:page])
|
40
|
+
|
41
|
+
When generating links using the +link_to_sorted+ method you should
|
42
|
+
specify the table for every attribute you use as well otherwise you
|
43
|
+
will probably get an ambiguous column name error.
|
44
|
+
|
45
|
+
<th class="ui-state-default"><%= link_to_sorted "Company name", 'companies.name' %></th>
|
46
|
+
<th class="ui-state-default"><%= link_to_sorted "Users name", 'users.name' %></th>
|
47
|
+
|
48
|
+
==== Typecasting and DB functions
|
28
49
|
|
29
|
-
|
50
|
+
Do your type casting and function calls in your select statement with an
|
51
|
+
alias, for example:
|
30
52
|
|
31
|
-
|
53
|
+
# controller
|
54
|
+
@users = User.select("income::BigInt as bg_income").sort(params[:sort], "bg_income ASC")
|
55
|
+
|
56
|
+
# view
|
57
|
+
<th class="ui-state-default"><%= link_to_sorted "Income", 'bg_income' %></th>
|
32
58
|
|
33
|
-
|
34
|
-
RELATIONS is the name of the relationship table and COLUMN is an attribute in that table. For example,
|
35
|
-
assuming the User model belongs_to a :company.
|
59
|
+
or using a DB function:
|
36
60
|
|
37
|
-
|
61
|
+
# controller
|
62
|
+
@users = User.select("inet_aton(`ip_address`) AS in_ip").sort(params[:sort], "in_ip ASC")
|
63
|
+
|
64
|
+
# view
|
65
|
+
<th class="ui-state-default"><%= link_to_sorted "IP address", 'in_ip' %></th>
|
38
66
|
|
39
67
|
== Presentation
|
40
68
|
|
41
|
-
You might want to roll your own link_to_sorted method to use jQuery ui
|
69
|
+
You might want to roll your own +link_to_sorted+ method to use jQuery ui
|
70
|
+
css classes for example, all you need is the sorted object.
|
42
71
|
|
43
72
|
def link_to_sorted(name, order)
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
73
|
+
dup_params = (request.get? && !params.nil?) ? params.dup : nil
|
74
|
+
sorter = ActionView::Base::SortedViewHelper.new(order, dup_params)
|
75
|
+
css_class = case sorter.css
|
76
|
+
when "sorted asc"
|
77
|
+
"ui-icon ui-icon-triangle-1-n"
|
78
|
+
when "sorted desc"
|
79
|
+
"ui-icon ui-icon-triangle-1-s"
|
80
|
+
when "sorted"
|
81
|
+
"ui-icon ui-icon-carat-2-n-s"
|
82
|
+
end
|
53
83
|
link_to(content_tag(:span, nil, {:class => css_class}) + name.to_s, sorter.params)
|
54
84
|
end
|
55
85
|
|
56
|
-
Tables are best displayed with alternating shades for each row, so
|
57
|
-
|
58
|
-
def odd_even
|
59
|
-
@odd_even ||= 0
|
60
|
-
@odd_even += 1
|
61
|
-
(@odd_even % 2) == 1 ? 'odd' : 'even'
|
62
|
-
end
|
63
|
-
|
64
|
-
Then in your table do something like this:
|
86
|
+
Tables are best displayed with alternating shades for each row, so add
|
87
|
+
an alternating class to you table rows using the rails +cycle+ method:
|
65
88
|
|
66
|
-
<tr class="<%=
|
89
|
+
<tr class="<%= cycle 'odd', 'even' %>">
|
67
90
|
|
68
91
|
== Rails 2.3.x
|
69
92
|
|
70
|
-
|
93
|
+
Sorted works with rails 2.3.x but you will have to roll your own scope
|
94
|
+
and view helper.
|
71
95
|
|
72
96
|
Here is the named scope for your model(s):
|
73
97
|
|
74
|
-
named_scope :
|
75
|
-
{ :order => Sorted::
|
98
|
+
named_scope :sort, lambda { |sort, order|
|
99
|
+
{ :order => Sorted::Parser.new(sort, order).to_sql }
|
76
100
|
}
|
77
101
|
|
78
|
-
and the
|
102
|
+
and the application helper method:
|
79
103
|
|
80
|
-
def
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
sorter = sorted(order)
|
86
|
-
link_to(name, sorter.params, {:class => sorter.to_css})
|
104
|
+
def link_to_sorted(name, order, options = {})
|
105
|
+
dup_params = (request.get? && !params.nil?) ? params.dup : nil
|
106
|
+
sorter = Sorted::ViewHelpers::ActionView::SortedViewHelper.new(order, dup_params)
|
107
|
+
options[:class] = [options[:class], sorter.css].join(' ').strip
|
108
|
+
link_to(name.to_s, sorter.params, options)
|
87
109
|
end
|
data/lib/sorted.rb
CHANGED
@@ -0,0 +1,17 @@
|
|
1
|
+
require 'active_record'
|
2
|
+
require 'sorted'
|
3
|
+
|
4
|
+
module Sorted
|
5
|
+
module Orms
|
6
|
+
module ActiveRecord
|
7
|
+
def self.enable!
|
8
|
+
::ActiveRecord::Base.class_eval do
|
9
|
+
def self.sort(sort, order = nil)
|
10
|
+
sorter = ::Sorted::Parser.new(sort, order)
|
11
|
+
order sorter.to_sql
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,79 @@
|
|
1
|
+
require 'sorted/toggler'
|
2
|
+
|
3
|
+
module Sorted
|
4
|
+
# Takes a sort query string and an SQL order string and parses the
|
5
|
+
# values to produce key value pairs.
|
6
|
+
#
|
7
|
+
# Example:
|
8
|
+
# Sorted::Parser.new('phone_desc', 'name ASC').to_s #-> "phone_desc!name_asc"
|
9
|
+
class Parser
|
10
|
+
attr_reader :sort, :order, :sorts, :orders
|
11
|
+
|
12
|
+
# Regex to make sure we only get valid names and not injected code.
|
13
|
+
SORTED_QUERY_REGEX = /([a-zA-Z0-9._]+)_(asc|desc)$/
|
14
|
+
SQL_REGEX = /(([a-z0-9._]+)\s([asc|desc]+)|[a-z0-9._]+)/i
|
15
|
+
|
16
|
+
def initialize(sort, order = nil)
|
17
|
+
@sort = sort
|
18
|
+
@order = order
|
19
|
+
@sorts = parse_sort
|
20
|
+
@orders = parse_order
|
21
|
+
end
|
22
|
+
|
23
|
+
def parse_sort
|
24
|
+
sort.to_s.split(/!/).map do |sort_string|
|
25
|
+
if m = sort_string.match(SORTED_QUERY_REGEX)
|
26
|
+
[m[1], m[2].downcase]
|
27
|
+
end
|
28
|
+
end.compact
|
29
|
+
end
|
30
|
+
|
31
|
+
def parse_order
|
32
|
+
order.to_s.split(/,/).map do |order_string|
|
33
|
+
if m = order_string.match(SQL_REGEX)
|
34
|
+
[(m[2].nil? ? m[1] : m[2]),(m[3].nil? ? "asc" : m[3].downcase)]
|
35
|
+
end
|
36
|
+
end.compact
|
37
|
+
end
|
38
|
+
|
39
|
+
def to_hash
|
40
|
+
array.inject({}){|h,a| h.merge(Hash[a[0],a[1]])}
|
41
|
+
end
|
42
|
+
|
43
|
+
def to_sql
|
44
|
+
array.map{|a| "#{a[0]} #{a[1].upcase}" }.join(', ')
|
45
|
+
end
|
46
|
+
|
47
|
+
def to_s
|
48
|
+
array.map{|a| a.join('_') }.join('!')
|
49
|
+
end
|
50
|
+
|
51
|
+
def to_a
|
52
|
+
array
|
53
|
+
end
|
54
|
+
|
55
|
+
def toggle
|
56
|
+
@array = Toggler.new(sorts, orders).to_a
|
57
|
+
self
|
58
|
+
end
|
59
|
+
|
60
|
+
def reset
|
61
|
+
@array = default
|
62
|
+
self
|
63
|
+
end
|
64
|
+
|
65
|
+
private
|
66
|
+
|
67
|
+
def array
|
68
|
+
@array ||= default
|
69
|
+
end
|
70
|
+
|
71
|
+
def default
|
72
|
+
sorts_new = sorts.dup
|
73
|
+
orders.each do |o|
|
74
|
+
sorts_new << o unless sorts_new.flatten.include?(o[0])
|
75
|
+
end
|
76
|
+
sorts_new
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
data/lib/sorted/railtie.rb
CHANGED
@@ -4,8 +4,8 @@ module Sorted
|
|
4
4
|
class Railtie < Rails::Railtie
|
5
5
|
initializer "sorted.active_record" do |app|
|
6
6
|
if defined? ::ActiveRecord
|
7
|
-
require 'sorted/
|
8
|
-
Sorted::
|
7
|
+
require 'sorted/orms/active_record'
|
8
|
+
Sorted::Orms::ActiveRecord.enable!
|
9
9
|
end
|
10
10
|
end
|
11
11
|
|
data/lib/sorted/toggler.rb
CHANGED
@@ -1,6 +1,13 @@
|
|
1
1
|
module Sorted
|
2
|
+
# Takes a parsed arrays of sorts and orders, it then will reorder the
|
3
|
+
# pairs and flip the assendance of the first sort pair.
|
4
|
+
#
|
5
|
+
# Example:
|
6
|
+
# sorts = [['name', 'asc'], ['phone', 'desc']]
|
7
|
+
# oredrs = [['name', 'asc']]
|
8
|
+
# Sorted::Toggler.new(sorts, orders).to_a #-> [['name', 'desc'], ['phone', 'desc']]
|
2
9
|
class Toggler
|
3
|
-
def initialize(
|
10
|
+
def initialize(sorts, orders)
|
4
11
|
@array = []
|
5
12
|
@sorts = sorts
|
6
13
|
@orders = orders
|
data/lib/sorted/version.rb
CHANGED
@@ -4,13 +4,28 @@ require 'sorted'
|
|
4
4
|
module Sorted
|
5
5
|
module ViewHelpers
|
6
6
|
module ActionView
|
7
|
-
|
8
|
-
|
7
|
+
class SortedViewHelper
|
8
|
+
attr_reader :params
|
9
|
+
|
10
|
+
def initialize(order, params)
|
11
|
+
sort = params.delete :sort
|
12
|
+
@params = params
|
13
|
+
@parser = ::Sorted::Parser.new(sort, order).toggle
|
14
|
+
@params[:sort] = @parser.to_s
|
15
|
+
end
|
16
|
+
|
17
|
+
def css
|
18
|
+
if @parser.sorts.flatten.include? @parser.orders[0][0]
|
19
|
+
"sorted #{@parser.sorts.assoc(@parser.orders[0][0]).last}"
|
20
|
+
else
|
21
|
+
"sorted"
|
22
|
+
end
|
23
|
+
end
|
9
24
|
end
|
10
25
|
|
11
26
|
def link_to_sorted(name, order, options = {})
|
12
|
-
sorter =
|
13
|
-
options[:class] = [options[:class], sorter.
|
27
|
+
sorter = SortedViewHelper.new(order, ((request.get? && !params.nil?) ? params.dup : nil))
|
28
|
+
options[:class] = [options[:class], sorter.css].join(' ').strip
|
14
29
|
link_to(name.to_s, sorter.params, options)
|
15
30
|
end
|
16
31
|
end
|
data/sorted.gemspec
CHANGED
@@ -15,10 +15,9 @@ Gem::Specification.new do |s|
|
|
15
15
|
s.rubyforge_project = "sorted"
|
16
16
|
|
17
17
|
s.add_development_dependency "bundler", ">= 1.0.0"
|
18
|
-
s.add_development_dependency "rails", ">= 3.
|
18
|
+
s.add_development_dependency "rails", ">= 3.1.2"
|
19
19
|
s.add_development_dependency "rspec", ">= 2.0.0"
|
20
20
|
|
21
|
-
|
22
21
|
s.files = `git ls-files`.split("\n")
|
23
22
|
s.executables = `git ls-files`.split("\n").map{|f| f =~ /^bin\/(.*)/ ? $1 : nil}.compact
|
24
23
|
s.require_path = 'lib'
|
@@ -0,0 +1,90 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Sorted::Parser, "params parsing" do
|
4
|
+
it "should not raise if pased nil arguments" do
|
5
|
+
lambda { Sorted::Parser.new(nil, nil).toggle }.should_not raise_error
|
6
|
+
end
|
7
|
+
|
8
|
+
it "should return a nice array from the order sql" do
|
9
|
+
sort = nil
|
10
|
+
order = "email ASC, phone ASC, name DESC"
|
11
|
+
result = [["email", "asc"], ["phone", "asc"], ["name", "desc"]]
|
12
|
+
|
13
|
+
sorter = Sorted::Parser.new(sort, order)
|
14
|
+
sorter.orders.should eq result
|
15
|
+
end
|
16
|
+
|
17
|
+
it "should return a nice array from the sort params" do
|
18
|
+
sort = "email_desc!name_desc"
|
19
|
+
order = nil
|
20
|
+
result = [["email", "desc"], ["name", "desc"]]
|
21
|
+
|
22
|
+
sorter = Sorted::Parser.new(sort, order)
|
23
|
+
sorter.sorts.should eq result
|
24
|
+
end
|
25
|
+
|
26
|
+
it "should combine sort and order params with sort params being of higer importance" do
|
27
|
+
sort = "email_desc!name_desc"
|
28
|
+
order = "email ASC, phone ASC, name DESC"
|
29
|
+
result = [["email", "desc"], ["name", "desc"], ["phone", "asc"]]
|
30
|
+
|
31
|
+
sorter = Sorted::Parser.new(sort, order)
|
32
|
+
sorter.to_a.should eq result
|
33
|
+
end
|
34
|
+
|
35
|
+
it "should allow numbers, underscores and full stops in sort params" do
|
36
|
+
sort = "assessmentsTable.name_desc!users_300.name_5_desc"
|
37
|
+
order = nil
|
38
|
+
result = [["assessmentsTable.name", "desc"], ["users_300.name_5", "desc"]]
|
39
|
+
|
40
|
+
sorter = Sorted::Parser.new(sort, order)
|
41
|
+
sorter.sorts.should eq result
|
42
|
+
end
|
43
|
+
|
44
|
+
it "should allow numbers, underscores and full stops in order params" do
|
45
|
+
sort = nil
|
46
|
+
order = "assessmentsTable.name ASC, users_300.name_5 ASC"
|
47
|
+
result = [["assessmentsTable.name", "asc"], ["users_300.name_5", "asc"]]
|
48
|
+
|
49
|
+
sorter = Sorted::Parser.new(sort, order)
|
50
|
+
sorter.orders.should eq result
|
51
|
+
end
|
52
|
+
|
53
|
+
it "should default to asc if sort params order is ommited" do
|
54
|
+
sort = nil
|
55
|
+
order = :email
|
56
|
+
result = [["email", "asc"]]
|
57
|
+
|
58
|
+
sorter = Sorted::Parser.new(sort, order)
|
59
|
+
sorter.orders.should eq result
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
describe Sorted::Parser, "return types" do
|
64
|
+
it "should return an sql sort string" do
|
65
|
+
sort = "email_desc!name_desc"
|
66
|
+
order = "email ASC, phone ASC, name DESC"
|
67
|
+
result = "email DESC, name DESC, phone ASC"
|
68
|
+
|
69
|
+
sorter = Sorted::Parser.new(sort, order)
|
70
|
+
sorter.to_sql.should eq result
|
71
|
+
end
|
72
|
+
|
73
|
+
it "should return an hash" do
|
74
|
+
sort = "email_desc!name_desc"
|
75
|
+
order = "email ASC, phone ASC, name DESC"
|
76
|
+
result = {"email" => "desc", "name" => "desc", "phone" => "asc"}
|
77
|
+
|
78
|
+
sorter = Sorted::Parser.new(sort, order)
|
79
|
+
sorter.to_hash.should eq result
|
80
|
+
end
|
81
|
+
|
82
|
+
it "should return an the encoded sort string" do
|
83
|
+
sort = "email_desc!name_desc"
|
84
|
+
order = "email ASC, phone ASC, name DESC"
|
85
|
+
result = "email_desc!name_desc!phone_asc"
|
86
|
+
|
87
|
+
sorter = Sorted::Parser.new(sort, order)
|
88
|
+
sorter.to_s.should eq result
|
89
|
+
end
|
90
|
+
end
|
@@ -0,0 +1,57 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Sorted::Toggler do
|
4
|
+
it "should bring phone to first order importance but not toggle ascendance" do
|
5
|
+
orders = [["email", "asc"], ["phone", "asc"]]
|
6
|
+
sorts = [["phone", "asc"]]
|
7
|
+
result = [["phone", "asc"], ["email", "asc"]]
|
8
|
+
|
9
|
+
toggler = Sorted::Toggler.new(sorts, orders)
|
10
|
+
toggler.to_a.should eq result
|
11
|
+
end
|
12
|
+
|
13
|
+
it "should toggle ascendance of email" do
|
14
|
+
orders = [["email", "desc"]]
|
15
|
+
sorts = [["email", "asc"]]
|
16
|
+
result = [["email", "desc"]]
|
17
|
+
|
18
|
+
toggler = Sorted::Toggler.new(sorts, orders)
|
19
|
+
toggler.to_a.should eq result
|
20
|
+
end
|
21
|
+
|
22
|
+
it "should return both order params un-toggled with no sort param" do
|
23
|
+
orders = [["email", "asc"], ["phone", "asc"]]
|
24
|
+
sorts = []
|
25
|
+
result = [["email", "asc"], ["phone", "asc"]]
|
26
|
+
|
27
|
+
toggler = Sorted::Toggler.new(sorts, orders)
|
28
|
+
toggler.to_a.should eq result
|
29
|
+
end
|
30
|
+
|
31
|
+
it "should toggle the email ascendance" do
|
32
|
+
orders = [["email", "asc"]]
|
33
|
+
sorts = [["email", "asc"], ["phone", "asc"]]
|
34
|
+
result = [["email", "desc"], ["phone", "asc"]]
|
35
|
+
|
36
|
+
toggler = Sorted::Toggler.new(sorts, orders)
|
37
|
+
toggler.to_a.should eq result
|
38
|
+
end
|
39
|
+
|
40
|
+
it "should toggle the email ascendance" do
|
41
|
+
orders = [["email", "desc"]]
|
42
|
+
sorts = [["email", "asc"], ["phone", "asc"]]
|
43
|
+
result = [["email", "desc"], ["phone", "asc"]]
|
44
|
+
|
45
|
+
toggler = Sorted::Toggler.new(sorts, orders)
|
46
|
+
toggler.to_a.should eq result
|
47
|
+
end
|
48
|
+
|
49
|
+
it "should toggle two 1..n sort values" do
|
50
|
+
orders = [["email", "asc"], ["phone", "asc"]]
|
51
|
+
sorts = [["email", "asc"], ["phone", "asc"]]
|
52
|
+
result = [["email", "desc"], ["phone", "desc"]]
|
53
|
+
|
54
|
+
toggler = Sorted::Toggler.new(sorts, orders)
|
55
|
+
toggler.to_a.should eq result
|
56
|
+
end
|
57
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Sorted::ViewHelpers::ActionView do
|
4
|
+
it "should integrate with ActiveRecord::Base" do
|
5
|
+
ActionView::Base.send(:include, Sorted::ViewHelpers::ActionView)
|
6
|
+
ActionView::Base.new.should respond_to(:link_to_sorted)
|
7
|
+
end
|
8
|
+
end
|
9
|
+
|
10
|
+
describe Sorted::ViewHelpers::ActionView::SortedViewHelper do
|
11
|
+
it "should return the default sort order and preserve the existing params" do
|
12
|
+
order = :email
|
13
|
+
params = { :page => 10 }
|
14
|
+
result = { :page => 10, :sort => "email_asc" }
|
15
|
+
|
16
|
+
sorter = Sorted::ViewHelpers::ActionView::SortedViewHelper.new order, params
|
17
|
+
sorter.params.should eq result
|
18
|
+
end
|
19
|
+
|
20
|
+
it "should only return the sorted css class if email has not yet been sorted" do
|
21
|
+
order = :email
|
22
|
+
params = {}
|
23
|
+
result = "sorted"
|
24
|
+
|
25
|
+
sorter = Sorted::ViewHelpers::ActionView::SortedViewHelper.new order, params
|
26
|
+
sorter.css.should eq result
|
27
|
+
end
|
28
|
+
|
29
|
+
it "should only return the sorted css class if email has not yet been sorted" do
|
30
|
+
order = :email
|
31
|
+
params = { :sort => "email_asc" }
|
32
|
+
result = "sorted asc"
|
33
|
+
|
34
|
+
sorter = Sorted::ViewHelpers::ActionView::SortedViewHelper.new order, params
|
35
|
+
sorter.css.should eq result
|
36
|
+
end
|
37
|
+
end
|
data/spec/spec_helper.rb
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
$LOAD_PATH.unshift(File.dirname(__FILE__))
|
2
2
|
$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
|
3
|
-
require 'sorted
|
3
|
+
require 'sorted'
|
4
|
+
require 'sorted/orms/active_record'
|
4
5
|
require 'sorted/view_helpers/action_view'
|
5
6
|
require 'rspec'
|
6
|
-
require 'rspec/autorun'
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: sorted
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.3.
|
4
|
+
version: 0.3.9
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,11 +9,11 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2011-
|
12
|
+
date: 2011-11-20 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: bundler
|
16
|
-
requirement: &
|
16
|
+
requirement: &70134746957060 !ruby/object:Gem::Requirement
|
17
17
|
none: false
|
18
18
|
requirements:
|
19
19
|
- - ! '>='
|
@@ -21,21 +21,21 @@ dependencies:
|
|
21
21
|
version: 1.0.0
|
22
22
|
type: :development
|
23
23
|
prerelease: false
|
24
|
-
version_requirements: *
|
24
|
+
version_requirements: *70134746957060
|
25
25
|
- !ruby/object:Gem::Dependency
|
26
26
|
name: rails
|
27
|
-
requirement: &
|
27
|
+
requirement: &70134746956600 !ruby/object:Gem::Requirement
|
28
28
|
none: false
|
29
29
|
requirements:
|
30
30
|
- - ! '>='
|
31
31
|
- !ruby/object:Gem::Version
|
32
|
-
version: 3.
|
32
|
+
version: 3.1.2
|
33
33
|
type: :development
|
34
34
|
prerelease: false
|
35
|
-
version_requirements: *
|
35
|
+
version_requirements: *70134746956600
|
36
36
|
- !ruby/object:Gem::Dependency
|
37
37
|
name: rspec
|
38
|
-
requirement: &
|
38
|
+
requirement: &70134746956100 !ruby/object:Gem::Requirement
|
39
39
|
none: false
|
40
40
|
requirements:
|
41
41
|
- - ! '>='
|
@@ -43,7 +43,7 @@ dependencies:
|
|
43
43
|
version: 2.0.0
|
44
44
|
type: :development
|
45
45
|
prerelease: false
|
46
|
-
version_requirements: *
|
46
|
+
version_requirements: *70134746956100
|
47
47
|
description: lets you sort large data sets using view helpers and a scope
|
48
48
|
email:
|
49
49
|
- rufuspost@gmail.com
|
@@ -53,23 +53,23 @@ extra_rdoc_files: []
|
|
53
53
|
files:
|
54
54
|
- .document
|
55
55
|
- .gitignore
|
56
|
-
- .watchr
|
57
56
|
- Gemfile
|
58
57
|
- LICENSE
|
59
58
|
- README.rdoc
|
60
59
|
- Rakefile
|
61
60
|
- lib/sorted.rb
|
62
|
-
- lib/sorted/
|
61
|
+
- lib/sorted/orms/active_record.rb
|
62
|
+
- lib/sorted/parser.rb
|
63
63
|
- lib/sorted/railtie.rb
|
64
|
-
- lib/sorted/sorter.rb
|
65
64
|
- lib/sorted/toggler.rb
|
66
65
|
- lib/sorted/version.rb
|
67
66
|
- lib/sorted/view_helpers/action_view.rb
|
68
67
|
- sorted.gemspec
|
69
|
-
- spec/
|
70
|
-
- spec/
|
68
|
+
- spec/sorted/orms/active_record_spec.rb
|
69
|
+
- spec/sorted/parser_spec.rb
|
70
|
+
- spec/sorted/toggler_spec.rb
|
71
|
+
- spec/sorted/view_helpers/action_view_spec.rb
|
71
72
|
- spec/spec_helper.rb
|
72
|
-
- spec/toggler_spec.rb
|
73
73
|
homepage: http://rubygems.org/gems/sorted
|
74
74
|
licenses: []
|
75
75
|
post_install_message:
|
@@ -84,7 +84,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
84
84
|
version: '0'
|
85
85
|
segments:
|
86
86
|
- 0
|
87
|
-
hash:
|
87
|
+
hash: -354722037037653326
|
88
88
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
89
89
|
none: false
|
90
90
|
requirements:
|
@@ -93,7 +93,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
93
93
|
version: 1.3.6
|
94
94
|
requirements: []
|
95
95
|
rubyforge_project: sorted
|
96
|
-
rubygems_version: 1.8.
|
96
|
+
rubygems_version: 1.8.11
|
97
97
|
signing_key:
|
98
98
|
specification_version: 3
|
99
99
|
summary: sort data with a database
|
data/.watchr
DELETED
@@ -1,24 +0,0 @@
|
|
1
|
-
module WatchrActions
|
2
|
-
def self.run_spec(file)
|
3
|
-
unless File.exist?(file)
|
4
|
-
puts "#{file} does not exist"
|
5
|
-
return
|
6
|
-
end
|
7
|
-
|
8
|
-
puts "Running #{file}"
|
9
|
-
system "rspec #{file}"
|
10
|
-
end
|
11
|
-
end
|
12
|
-
|
13
|
-
watch(/^lib\/(?:sorted\/)?(.*).rb/) do |m|
|
14
|
-
WatchrActions.run_spec("spec/#{m[1]}_spec.rb")
|
15
|
-
end
|
16
|
-
|
17
|
-
watch(/^spec\/.*_spec.rb/) do |m|
|
18
|
-
WatchrActions.run_spec(m[0])
|
19
|
-
end
|
20
|
-
|
21
|
-
watch(/^lib\/sorted\/finders\/active_record.rb/) do |m|
|
22
|
-
WatchrActions.run_spec('spec/sorted_spec.rb')
|
23
|
-
end
|
24
|
-
|
@@ -1,41 +0,0 @@
|
|
1
|
-
require 'active_record'
|
2
|
-
require 'sorted'
|
3
|
-
|
4
|
-
module Sorted
|
5
|
-
module Finders
|
6
|
-
module ActiveRecord
|
7
|
-
def self.enable!
|
8
|
-
::ActiveRecord::Base.class_eval do
|
9
|
-
# Define a symbolic sort column. This allows mapping a simple column name
|
10
|
-
# to a more complex sql order clause.
|
11
|
-
# class Model < ActiveRecord::Base
|
12
|
-
# symbolic_sort :ip_address, 'inet_aton(`ip_address`)'
|
13
|
-
# end
|
14
|
-
def self.symbolic_sort(key, sql)
|
15
|
-
symbolic_sorts[key] = sql
|
16
|
-
end
|
17
|
-
|
18
|
-
def self.sorted(params)
|
19
|
-
sorter = ::Sorted::Sorter.new(params[:order], :sort => params[:sort], :symbolic_sorts => symbolic_sorts)
|
20
|
-
# Check if we parsed some relationship includes and apply them
|
21
|
-
# before applying the order
|
22
|
-
relation = self
|
23
|
-
if sorter.includes.size > 0
|
24
|
-
# Remove self.name from includes
|
25
|
-
my_name = self.name.to_sym
|
26
|
-
real_includes = sorter.includes.delete_if{|include_name| include_name == my_name}
|
27
|
-
relation = includes(real_includes) if real_includes.size > 0
|
28
|
-
end
|
29
|
-
relation.order(sorter.to_sql)
|
30
|
-
end
|
31
|
-
|
32
|
-
private
|
33
|
-
|
34
|
-
def self.symbolic_sorts
|
35
|
-
@symbolic_sorts ||= {}
|
36
|
-
end
|
37
|
-
end
|
38
|
-
end
|
39
|
-
end
|
40
|
-
end
|
41
|
-
end
|
data/lib/sorted/sorter.rb
DELETED
@@ -1,122 +0,0 @@
|
|
1
|
-
module Sorted
|
2
|
-
class Sorter
|
3
|
-
attr_reader :includes
|
4
|
-
def initialize(order, params = nil)
|
5
|
-
@includes = []
|
6
|
-
@symbolic_sorts = {}
|
7
|
-
|
8
|
-
if order.is_a?(String) || order.is_a?(Symbol)
|
9
|
-
parse_order(order)
|
10
|
-
end
|
11
|
-
if params.is_a?(Hash)
|
12
|
-
@params = params
|
13
|
-
if @params[:sort].is_a?(String)
|
14
|
-
parse_sort @params[:sort]
|
15
|
-
end
|
16
|
-
@symbolic_sorts = @params[:symbolic_sorts] || {}
|
17
|
-
end
|
18
|
-
end
|
19
|
-
|
20
|
-
def parse_sort(sort_string)
|
21
|
-
sort_string.split(/!/).each do |sort|
|
22
|
-
if parsed = parse_query(sort)
|
23
|
-
sorts << parsed
|
24
|
-
end
|
25
|
-
end
|
26
|
-
end
|
27
|
-
|
28
|
-
def parse_order(order_string_or_symbol)
|
29
|
-
order_string_or_symbol.to_s.split(/,/).each do |order|
|
30
|
-
if parsed = parse_sql(order)
|
31
|
-
orders << parsed
|
32
|
-
end
|
33
|
-
end
|
34
|
-
end
|
35
|
-
|
36
|
-
def parse_query(sort)
|
37
|
-
if m = sort.match(/([a-zA-Z0-9._]+)_(asc|desc)$/)
|
38
|
-
parse_include(m[1])
|
39
|
-
[m[1],m[2]]
|
40
|
-
end
|
41
|
-
end
|
42
|
-
|
43
|
-
def parse_sql(order)
|
44
|
-
if m = order.match(/(([a-zA-Z._:][a-zA-Z._:0-9]*)\s([asc|ASC|desc|DESC]+)|[a-zA-Z._:][a-zA-Z._:0-9]*)/)
|
45
|
-
sort_column = (m[2].nil? ? m[1] : m[2])
|
46
|
-
parse_include(sort_column)
|
47
|
-
[sort_column,(m[3].nil? ? "asc" : m[3].downcase)]
|
48
|
-
end
|
49
|
-
end
|
50
|
-
|
51
|
-
def parse_include(order)
|
52
|
-
if match_data = /^([^\.]+)\..+/.match(order)
|
53
|
-
include_name = match_data[1].singularize.to_sym
|
54
|
-
@includes << include_name unless @includes.include?(include_name)
|
55
|
-
end
|
56
|
-
end
|
57
|
-
|
58
|
-
def toggle
|
59
|
-
@array = Toggler.new(orders, sorts).to_a
|
60
|
-
self
|
61
|
-
end
|
62
|
-
|
63
|
-
def reset
|
64
|
-
@array = default
|
65
|
-
self
|
66
|
-
end
|
67
|
-
|
68
|
-
def to_hash
|
69
|
-
array.inject({}){|h,a| h.merge(Hash[a[0],a[1]])}
|
70
|
-
end
|
71
|
-
|
72
|
-
def to_sql
|
73
|
-
array.map do |a|
|
74
|
-
column = @symbolic_sorts[a[0].to_sym] || a[0]
|
75
|
-
"#{column} #{a[1].upcase}"
|
76
|
-
end.join(', ')
|
77
|
-
end
|
78
|
-
|
79
|
-
def to_s
|
80
|
-
array.map{|a| a.join('_')}.join('!')
|
81
|
-
end
|
82
|
-
|
83
|
-
def to_a
|
84
|
-
array
|
85
|
-
end
|
86
|
-
|
87
|
-
def to_css
|
88
|
-
if sorts.flatten.include?(orders[0][0])
|
89
|
-
"sorted #{sorts.assoc(orders[0][0]).last}"
|
90
|
-
else
|
91
|
-
"sorted"
|
92
|
-
end
|
93
|
-
end
|
94
|
-
|
95
|
-
def params
|
96
|
-
@params ||= {}
|
97
|
-
@params[:sort] = to_s
|
98
|
-
@params
|
99
|
-
end
|
100
|
-
|
101
|
-
def orders
|
102
|
-
@orders ||= []
|
103
|
-
end
|
104
|
-
|
105
|
-
def sorts
|
106
|
-
@sorts ||= []
|
107
|
-
end
|
108
|
-
|
109
|
-
private
|
110
|
-
def default
|
111
|
-
sorts_new = sorts.dup
|
112
|
-
orders.each do |order|
|
113
|
-
sorts_new << order unless sorts_new.flatten.include?(order[0])
|
114
|
-
end
|
115
|
-
sorts_new
|
116
|
-
end
|
117
|
-
|
118
|
-
def array
|
119
|
-
@array ||= default
|
120
|
-
end
|
121
|
-
end
|
122
|
-
end
|
data/spec/sorted_spec.rb
DELETED
@@ -1,122 +0,0 @@
|
|
1
|
-
require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
|
2
|
-
require 'action_controller'
|
3
|
-
require 'sorted'
|
4
|
-
|
5
|
-
describe Sorted::Finders::ActiveRecord do
|
6
|
-
before(:each) do
|
7
|
-
Sorted::Finders::ActiveRecord.enable!
|
8
|
-
end
|
9
|
-
|
10
|
-
it "should integrate with ActiveRecord::Base" do
|
11
|
-
ActiveRecord::Base.should respond_to(:sorted)
|
12
|
-
end
|
13
|
-
|
14
|
-
it "should define a symbolic_sorts method" do
|
15
|
-
ActiveRecord::Base.should respond_to(:symbolic_sort)
|
16
|
-
end
|
17
|
-
|
18
|
-
it "should define symbolic_sorts" do
|
19
|
-
a = Class.new(ActiveRecord::Base)
|
20
|
-
b = Class.new(ActiveRecord::Base)
|
21
|
-
|
22
|
-
a.symbolic_sort(:foo, 'foo')
|
23
|
-
b.symbolic_sort(:bar, 'bar')
|
24
|
-
|
25
|
-
a.instance_variable_get(:@symbolic_sorts).should == {:foo => 'foo'}
|
26
|
-
b.instance_variable_get(:@symbolic_sorts).should == {:bar => 'bar'}
|
27
|
-
end
|
28
|
-
|
29
|
-
it "should add orders to the relation" do
|
30
|
-
a = Class.new(ActiveRecord::Base)
|
31
|
-
relation = a.sorted(:order => nil, :sort => 'a_asc')
|
32
|
-
relation.order_values.should == ["a ASC"]
|
33
|
-
end
|
34
|
-
|
35
|
-
it "should add orders to the relation using symbolic_sorts" do
|
36
|
-
a = Class.new(ActiveRecord::Base)
|
37
|
-
a.symbolic_sort(:ip, 'inet_aton(`ip`)')
|
38
|
-
relation = a.sorted(:order => nil, :sort => 'ip_asc')
|
39
|
-
relation.order_values.should == ["inet_aton(`ip`) ASC"]
|
40
|
-
end
|
41
|
-
end
|
42
|
-
|
43
|
-
describe Sorted::ViewHelpers::ActionView do
|
44
|
-
before(:each) do
|
45
|
-
class TestController
|
46
|
-
def params
|
47
|
-
@params ||= {}
|
48
|
-
end
|
49
|
-
|
50
|
-
def params=(params)
|
51
|
-
@params = params
|
52
|
-
end
|
53
|
-
|
54
|
-
def request
|
55
|
-
Request.new
|
56
|
-
end
|
57
|
-
|
58
|
-
def _prefixes
|
59
|
-
end
|
60
|
-
end
|
61
|
-
class Request
|
62
|
-
def get?; true end
|
63
|
-
end
|
64
|
-
@controller = TestController.new
|
65
|
-
ActionView::Base.send(:include, Sorted::ViewHelpers::ActionView)
|
66
|
-
end
|
67
|
-
|
68
|
-
it "should integrate with ActionView::Base" do
|
69
|
-
ActionView::Base.new.should respond_to(:sorted)
|
70
|
-
end
|
71
|
-
|
72
|
-
it "should integrate with ActionView::Base" do
|
73
|
-
ActionView::Base.new.should respond_to(:link_to_sorted)
|
74
|
-
end
|
75
|
-
|
76
|
-
it "should not change the direction of name using view helper" do
|
77
|
-
@controller.params = {:sort => "name_desc!email_asc"}
|
78
|
-
sorter = ActionView::Base.new([], {}, @controller).sorted(:email)
|
79
|
-
sorter.toggle.to_a.should == [["email", "asc"], ["name", "desc"]]
|
80
|
-
end
|
81
|
-
|
82
|
-
it "should reverse email direction using view helper" do
|
83
|
-
@controller.params = {:sort => "email_asc!name_desc"}
|
84
|
-
sorter = ActionView::Base.new([], {}, @controller).sorted(:email)
|
85
|
-
sorter.toggle.to_a.should == [["email", "desc"], ["name", "desc"]]
|
86
|
-
end
|
87
|
-
|
88
|
-
it "should reverse email direction using view helper" do
|
89
|
-
@controller.params = {:sort => "email_desc!name_desc!phone_desc"}
|
90
|
-
sorter = ActionView::Base.new([], {}, @controller).sorted(:email)
|
91
|
-
sorter.toggle.params.should == {:sort => "email_asc!name_desc!phone_desc"}
|
92
|
-
@controller.params = sorter.params
|
93
|
-
sorter = ActionView::Base.new([], {}, @controller).sorted(:email)
|
94
|
-
sorter.toggle.params.should == {:sort => "email_desc!name_desc!phone_desc"}
|
95
|
-
end
|
96
|
-
|
97
|
-
it "should not reverse order when made first again" do
|
98
|
-
@controller.params = {:sort => "phone_desc!name_desc!email_desc"}
|
99
|
-
sorter = ActionView::Base.new([], {}, @controller).sorted(:email)
|
100
|
-
sorter.toggle.params.should == {:sort => "email_desc!phone_desc!name_desc"}
|
101
|
-
sorter = ActionView::Base.new([], {}, @controller).sorted(:name)
|
102
|
-
sorter.toggle.params.should == {:sort => "name_desc!phone_desc!email_desc"}
|
103
|
-
end
|
104
|
-
|
105
|
-
it "should order correctly" do
|
106
|
-
sorter = ActionView::Base.new([], {}, @controller).sorted(:email)
|
107
|
-
sorter.toggle.params.should == {:sort => "email_asc"}
|
108
|
-
@controller.params = sorter.params
|
109
|
-
sorter = ActionView::Base.new([], {}, @controller).sorted(:name)
|
110
|
-
sorter.toggle.params.should == {:sort => "name_asc!email_asc"}
|
111
|
-
end
|
112
|
-
|
113
|
-
it "should return a hash of options for url builder with sorted query string" do
|
114
|
-
@controller.params = {:sort => "email_asc!name_desc", :page => 2}
|
115
|
-
ActionView::Base.new([], {}, @controller).sorted(:email).params.should == {:sort => "email_desc!name_desc", :page => 2}
|
116
|
-
end
|
117
|
-
|
118
|
-
it "should not die if params nil" do
|
119
|
-
sorter = ActionView::Base.new([], {}, @controller).sorted(:email)
|
120
|
-
sorter.params.should == {:sort => "email_asc"}
|
121
|
-
end
|
122
|
-
end
|
data/spec/sorter_spec.rb
DELETED
@@ -1,65 +0,0 @@
|
|
1
|
-
require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
|
2
|
-
require 'action_controller'
|
3
|
-
require 'sorted'
|
4
|
-
|
5
|
-
describe Sorted::Sorter, "parse methods" do
|
6
|
-
it "should not die if pased dumb things" do
|
7
|
-
lambda { Sorted::Sorter.new(false, Time.now).should_not }.should_not raise_error
|
8
|
-
end
|
9
|
-
|
10
|
-
it "should return a nice array from the order sql" do
|
11
|
-
sorter = Sorted::Sorter.new("email ASC, phone ASC, name DESC", {:sort => "email_desc!name_desc"})
|
12
|
-
sorter.orders.should == [["email", "asc"], ["phone", "asc"], ["name", "desc"]]
|
13
|
-
end
|
14
|
-
|
15
|
-
it "should return a nice array from the sort params" do
|
16
|
-
sorter = Sorted::Sorter.new("email ASC, phone ASC, name DESC", {:sort => "email_desc!name_desc"})
|
17
|
-
sorter.sorts.should == [["email", "desc"], ["name", "desc"]]
|
18
|
-
end
|
19
|
-
|
20
|
-
it "should allow numbers, underscores, full stops and colons in" do
|
21
|
-
sorter = Sorted::Sorter.new('users.email ASC, users.phone_number DESC, assessments.name ASC, assessments.number_as_string::BigInt, assessments.column_with_number_123', {:sort => "users.email_desc!users.first_name_desc"})
|
22
|
-
sorter.to_sql.should == "users.email DESC, users.first_name DESC, users.phone_number DESC, assessments.name ASC, assessments.number_as_string::BigInt ASC, assessments.column_with_number_123 ASC"
|
23
|
-
sorter.includes.size.should == 2
|
24
|
-
end
|
25
|
-
end
|
26
|
-
|
27
|
-
describe Sorted::Sorter, "logic:" do
|
28
|
-
it "should not toggle the sort order and include any sql orders not in sort params" do
|
29
|
-
sorter = Sorted::Sorter.new("email ASC, phone ASC, name DESC", {:sort => "email_desc!name_desc"})
|
30
|
-
sorter.to_a.should == [["email", "desc"], ["name", "desc"], ["phone", "asc"]]
|
31
|
-
sorter.includes.size.should == 0
|
32
|
-
end
|
33
|
-
|
34
|
-
it "should return an sql sort string" do
|
35
|
-
Sorted::Sorter.new(:email).to_sql.should == "email ASC"
|
36
|
-
Sorted::Sorter.new(:email, {:sort => "name_desc!email_desc"}).to_sql.should == "name DESC, email DESC"
|
37
|
-
end
|
38
|
-
|
39
|
-
it "should handle a large initial order string" do
|
40
|
-
sorter = Sorted::Sorter.new('email ASC, name DESC, phone ASC', {:sort => "email_desc!name_desc"})
|
41
|
-
sorter.to_sql.should == "email DESC, name DESC, phone ASC"
|
42
|
-
end
|
43
|
-
|
44
|
-
it "should handle a large initial order string" do
|
45
|
-
sorter = Sorted::Sorter.new('email ASC, phone DESC, name ASC', {:sort => "email_desc!name_desc"})
|
46
|
-
sorter.to_sql.should == "email DESC, name DESC, phone DESC"
|
47
|
-
end
|
48
|
-
|
49
|
-
it "should substitute symbolic sorts" do
|
50
|
-
sorter = Sorted::Sorter.new('ip_address', :symbolic_sorts => {:ip_address => 'inet_aton(`ip_address`)'})
|
51
|
-
sorter.to_sql.should == "inet_aton(`ip_address`) ASC"
|
52
|
-
end
|
53
|
-
end
|
54
|
-
|
55
|
-
describe Sorted::Sorter, "to_css" do
|
56
|
-
it "should return css base class for to_css if not in sort params" do
|
57
|
-
sorter = Sorted::Sorter.new(:email)
|
58
|
-
sorter.to_css.should == "sorted"
|
59
|
-
end
|
60
|
-
|
61
|
-
it "should return css class for to_css" do
|
62
|
-
sorter = Sorted::Sorter.new(:email, {:sort => "email_desc"})
|
63
|
-
sorter.to_css.should == "sorted desc"
|
64
|
-
end
|
65
|
-
end
|
data/spec/toggler_spec.rb
DELETED
@@ -1,39 +0,0 @@
|
|
1
|
-
require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
|
2
|
-
require 'action_controller'
|
3
|
-
require 'sorted'
|
4
|
-
|
5
|
-
describe Sorted::Toggler, "toggle sorts" do
|
6
|
-
it "should should fail becasue the sort order is incorect" do
|
7
|
-
sorter = Sorted::Sorter.new(:jsci_complete, {:sort => "parent_id_desc!non_vocational_complete_desc!jsci_complete_desc"})
|
8
|
-
sorter.toggle
|
9
|
-
sorter.to_s.should_not == "parent_id_desc!non_vocational_complete_desc!jsci_complete_desc"
|
10
|
-
end
|
11
|
-
|
12
|
-
it "should toggle two order params at once" do
|
13
|
-
first = Sorted::Sorter.new("email ASC, phone ASC")
|
14
|
-
first.toggle.to_a.should == [["email", "asc"],["phone", "asc"]]
|
15
|
-
second = Sorted::Sorter.new(:name, {:sort => first.to_s})
|
16
|
-
second.toggle.to_a.should == [["name", "asc"], ["email", "asc"],["phone", "asc"]]
|
17
|
-
third = Sorted::Sorter.new("email ASC, phone ASC", {:sort => second.to_s})
|
18
|
-
third.toggle.to_a.should == [["email", "asc"],["phone", "asc"], ["name", "asc"]]
|
19
|
-
end
|
20
|
-
end
|
21
|
-
|
22
|
-
describe Sorted::Toggler, "add remaining orders" do
|
23
|
-
it "should toggle the sort order and include any sql orders not in sort params" do
|
24
|
-
sorter = Sorted::Sorter.new("email DESC, phone ASC, name DESC", {:sort => "email_desc!name_desc"})
|
25
|
-
sorter.toggle.to_a.should == [["email", "desc"], ["name", "desc"], ["phone", "asc"]]
|
26
|
-
end
|
27
|
-
|
28
|
-
it "should toggle the sort order and include any sql orders not in sort params" do
|
29
|
-
sorter = Sorted::Sorter.new("email DESC, phone ASC, name DESC", {:sort => "mobile_asc!email_desc!phone_asc!name_desc"})
|
30
|
-
sorter.toggle.to_a.should == [["email", "desc"], ["phone", "asc"], ["name", "desc"], ["mobile", "asc"]]
|
31
|
-
end
|
32
|
-
end
|
33
|
-
|
34
|
-
describe Sorted::Toggler, "add remaining sorts" do
|
35
|
-
it "should toggle the sort order and include any sort orders not in order params" do
|
36
|
-
sorter = Sorted::Sorter.new("email DESC", {:sort => "email_desc!name_desc"})
|
37
|
-
sorter.toggle.to_a.should == [["email", "asc"], ["name", "desc"]]
|
38
|
-
end
|
39
|
-
end
|