sorted 1.0.1 → 1.1.1

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: cc893cb851e4226ef3548dcba99ae5e44592d9c6
4
- data.tar.gz: 9ee8b89780d7f29798643338f186846e58756508
3
+ metadata.gz: 1b665b8a96ecf9464b3c3845dae2edbdf3a8fef8
4
+ data.tar.gz: f698bb91b0fa131eef2928a89d8125f19813dde9
5
5
  SHA512:
6
- metadata.gz: 1f0d30cbf53dfabf7d54f46c391218dd81674758655decf875531c014111ec2f1c6841c0a6e73af56249b41d8538525f064744574ece3e4e717b96d59eb5de86
7
- data.tar.gz: 3f95d6fb84711892c6838a529f9caef5c006279322576c7dacd3ac2b0eb2e9167642880974f95983e82ebf64d8895828c3b303435fc22464610b68fac3148fca
6
+ metadata.gz: d4cd81b4bde74202c5ab1a6e4f6bce6696fc882c78392dcba6a59539e658819dcc8080683a2da19b939028a55f4c76be7f3533e35092944278151b4bde1c25b6
7
+ data.tar.gz: a5e122727f4e42a6756b5b08685e8cff49db754446bcd95f8e00d205fdf289a4699a46ee81d5d3e2d36846411532771b32a7b0d21b545f8a1a6a1b3dc1946474
data/.rubocop.yml ADDED
@@ -0,0 +1,7 @@
1
+ inherit_from: .rubocop_todo.yml
2
+
3
+ Style/Blocks:
4
+ Enabled: false
5
+
6
+ Style/WordArray:
7
+ MinSize: 2
data/.rubocop_todo.yml ADDED
@@ -0,0 +1,50 @@
1
+ # This configuration was generated by `rubocop --auto-gen-config`
2
+ # on 2014-12-14 20:28:26 +1100 using RuboCop version 0.28.0.
3
+ # The point is for the user to remove these configuration records
4
+ # one by one as the offenses are removed from the code base.
5
+ # Note that changes in the inspected code, or installation of new
6
+ # versions of RuboCop, may require this file to be generated again.
7
+
8
+ # Offense count: 5
9
+ Lint/UselessAssignment:
10
+ Enabled: false
11
+
12
+ # Offense count: 2
13
+ Lint/Void:
14
+ Enabled: false
15
+
16
+ # Offense count: 2
17
+ Metrics/AbcSize:
18
+ Max: 29
19
+
20
+ # Offense count: 1
21
+ Metrics/CyclomaticComplexity:
22
+ Max: 8
23
+
24
+ # Offense count: 22
25
+ # Configuration parameters: AllowURI, URISchemes.
26
+ Metrics/LineLength:
27
+ Max: 177
28
+
29
+ # Offense count: 2
30
+ # Configuration parameters: CountComments.
31
+ Metrics/MethodLength:
32
+ Max: 18
33
+
34
+ # Offense count: 1
35
+ Metrics/PerceivedComplexity:
36
+ Max: 9
37
+
38
+ # Offense count: 14
39
+ Style/Documentation:
40
+ Enabled: false
41
+
42
+ # Offense count: 5
43
+ # Configuration parameters: EnforcedStyle, SupportedStyles.
44
+ Style/For:
45
+ Enabled: false
46
+
47
+ # Offense count: 1
48
+ # Configuration parameters: MaxLineLength.
49
+ Style/IfUnlessModifier:
50
+ Enabled: false
data/.travis.yml CHANGED
@@ -2,6 +2,7 @@ language: ruby
2
2
  rvm:
3
3
  - 1.9.3
4
4
  - 2.0.0
5
+ - 2.1.5
5
6
  - jruby-19mode
6
7
  - ruby-head
7
8
 
data/README.md CHANGED
@@ -1,9 +1,50 @@
1
1
  # sorted
2
2
 
3
- [![Build Status](https://travis-ci.org/mynameisrufus/sorted.png?branch=master)](https://travis-ci.org/mynameisrufus/sorted)
3
+ [![Build Status](https://travis-ci.org/mynameisrufus/sorted.svg?branch=master)](https://travis-ci.org/mynameisrufus/sorted)
4
+ [![Gem Version](https://badge.fury.io/rb/sorted.svg)](http://badge.fury.io/rb/sorted)
4
5
 
5
- Sorted is a simple object that will take an sql order string and a url
6
- sort string to let you sort large datasets over many pages (using
6
+ Sorted at it's core is a set of objects that let you sort many different
7
+ attributes in weird and wonderful ways.
8
+
9
+ ## Example
10
+
11
+ The secret sauce is the `Sorted::Set` object, in this example we 'toggle' email:
12
+
13
+ ```ruby
14
+ a = Sorted::Set.new([['email', 'asc'], ['name', 'asc']])
15
+ b = Sorted::Set.new([['email', 'asc'], ['phone', 'asc']])
16
+
17
+ s = a.direction_intersect(b)
18
+
19
+ s.uniq.to_a #=> [['email', 'desc'], ['phone', 'asc'], ['name', 'asc']]
20
+ ```
21
+
22
+ The best way to think about this is to imagine a spreed sheet and what happens
23
+ when you sort by various columns, `Sorted::Set` pretty much just does that.
24
+
25
+ ## Parsers/Encoders
26
+
27
+ Parsers return a `Sorted::Set` that can then be used by an encoder:
28
+
29
+ ```ruby
30
+ set = Sorted::URIQuery.parse('name_asc!email_asc')
31
+ Sorted::SQLQuery.encode(set) #=> 'name ASC email ASC'
32
+ ```
33
+
34
+ Currently implemented:
35
+
36
+ * `Sorted::SQLQuery`
37
+ * `Sorted::URIQuery`
38
+
39
+ TODO:
40
+
41
+ * `Sorted::JSONQuery` (Mongoid)
42
+
43
+ ## Rails
44
+
45
+ Sorted comes with `ActionView` helpers and ORM scopes out of the box.
46
+
47
+ The ORM scopes will let you sort large datasets over many pages (using
7
48
  [will_paginate](https://github.com/mislav/will_paginate) or
8
49
  [kaminari](https://github.com/amatsuda/kaminari)) without losing state.
9
50
 
@@ -18,12 +59,6 @@ link_to_sorted "Email", :email
18
59
  Works the same as the `link_to` method except a second argument for the
19
60
  sort attribute is needed.
20
61
 
21
- ### Ruby 1.8.7 Rails 3.x
22
-
23
- ```ruby
24
- gem 'sorted', '~> 0.4.3'
25
- ```
26
-
27
62
  ### Model
28
63
 
29
64
  Using the `sorted` method with the optional default order argument:
@@ -32,12 +67,14 @@ Using the `sorted` method with the optional default order argument:
32
67
  @users = User.sorted(params[:sort], "email ASC").page(params[:page])
33
68
  ```
34
69
 
35
- ### Rubies
70
+ A `resorted` method is also available and works the same way as the `reorder` method in Rails.
71
+ It forces the order to be the one passed in:
36
72
 
37
- * MRI 1.9.3, 2.0.0.
38
- * JRuby 1.9 mode
73
+ ```ruby
74
+ @users = User.order(:id).sorted(nil, 'name DESC').resorted(params[:sort], 'email ASC')
75
+ ```
39
76
 
40
- ### ORMs
77
+ ## Supported ORMs
41
78
 
42
79
  * ActiveRecord
43
80
  * Mongoid
data/Rakefile CHANGED
@@ -1,18 +1,18 @@
1
- require 'bundler'
2
- Bundler::GemHelper.install_tasks
3
-
1
+ require 'bundler/gem_tasks'
2
+ require 'bundler/setup'
3
+ require 'rubocop/rake_task'
4
4
  require 'rspec/core'
5
5
  require 'rspec/core/rake_task'
6
+ require 'rdoc/task'
7
+ require 'sorted'
8
+
6
9
  RSpec::Core::RakeTask.new(:spec) do |spec|
7
10
  spec.pattern = FileList['spec/**/*_spec.rb']
8
11
  end
9
12
 
10
- task :default => "spec:all"
13
+ RuboCop::RakeTask.new
11
14
 
12
- require 'rdoc/task'
13
15
  Rake::RDocTask.new do |rdoc|
14
- require 'sorted/version'
15
-
16
16
  rdoc.rdoc_dir = 'rdoc'
17
17
  rdoc.title = "sorted #{Sorted::VERSION}"
18
18
  rdoc.rdoc_files.include('README*')
@@ -20,7 +20,7 @@ Rake::RDocTask.new do |rdoc|
20
20
  end
21
21
 
22
22
  namespace :spec do
23
- desc "Run Tests against all ORMs"
23
+ desc 'Run Tests against all ORMs'
24
24
  task :all do
25
25
  %w(active_record_40 mongoid_30).each do |gemfile|
26
26
  sh "BUNDLE_GEMFILE='gemfiles/#{gemfile}.gemfile' bundle --quiet"
@@ -28,3 +28,21 @@ namespace :spec do
28
28
  end
29
29
  end
30
30
  end
31
+
32
+ task :benchmark do
33
+ require 'benchmark'
34
+
35
+ sort = 'email_desc!name_desc'
36
+ order = 'email ASC, phone ASC, name DESC'
37
+
38
+ n = 50_000
39
+ Benchmark.bm do |x|
40
+ x.report(:lazy) { for i in 1..n; Sorted::Parser.new(sort, order); end }
41
+ x.report(:to_hash) { for i in 1..n; Sorted::Parser.new(sort, order).to_hash; end }
42
+ x.report(:to_sql) { for i in 1..n; Sorted::Parser.new(sort, order).to_sql; end }
43
+ x.report(:to_a) { for i in 1..n; Sorted::Parser.new(sort, order).to_a; end }
44
+ x.report(:toggle) { for i in 1..n; Sorted::Parser.new(sort, order).toggle; end }
45
+ end
46
+ end
47
+
48
+ task default: ['rubocop', 'spec:all']
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: /Users/rufuspost/Projects/ruby/gems/sorted
3
3
  specs:
4
- sorted (1.0.0)
4
+ sorted (1.1.1)
5
5
 
6
6
  GEM
7
7
  remote: https://rubygems.org/
@@ -33,6 +33,9 @@ GEM
33
33
  thread_safe (~> 0.1)
34
34
  tzinfo (~> 0.3.37)
35
35
  arel (4.0.1)
36
+ ast (2.0.0)
37
+ astrolabe (1.3.0)
38
+ parser (>= 2.2.0.pre.3, < 3.0)
36
39
  atomic (1.1.14)
37
40
  atomic (1.1.14-java)
38
41
  builder (3.1.4)
@@ -42,6 +45,10 @@ GEM
42
45
  jdbc-sqlite3 (3.7.2.1)
43
46
  minitest (4.7.5)
44
47
  multi_json (1.8.2)
48
+ parser (2.2.0.pre.8)
49
+ ast (>= 1.1, < 3.0)
50
+ slop (~> 3.4, >= 3.4.5)
51
+ powerpack (0.0.9)
45
52
  rack (1.5.2)
46
53
  rack-test (0.6.2)
47
54
  rack (>= 1.0)
@@ -50,6 +57,7 @@ GEM
50
57
  activesupport (= 4.0.0)
51
58
  rake (>= 0.8.7)
52
59
  thor (>= 0.18.1, < 2.0)
60
+ rainbow (2.0.0)
53
61
  rake (10.1.0)
54
62
  rspec (2.14.1)
55
63
  rspec-core (~> 2.14.0)
@@ -66,6 +74,14 @@ GEM
66
74
  rspec-core (~> 2.14.0)
67
75
  rspec-expectations (~> 2.14.0)
68
76
  rspec-mocks (~> 2.14.0)
77
+ rubocop (0.28.0)
78
+ astrolabe (~> 1.3)
79
+ parser (>= 2.2.0.pre.7, < 3.0)
80
+ powerpack (~> 0.0.6)
81
+ rainbow (>= 1.99.1, < 3.0)
82
+ ruby-progressbar (~> 1.4)
83
+ ruby-progressbar (1.7.0)
84
+ slop (3.6.0)
69
85
  sqlite3 (1.3.8)
70
86
  thor (0.18.1)
71
87
  thread_safe (0.1.3)
@@ -88,5 +104,6 @@ DEPENDENCIES
88
104
  rake
89
105
  rspec (>= 2.0.0)
90
106
  rspec-rails (>= 2.0)
107
+ rubocop (>= 0.28)
91
108
  sorted!
92
109
  sqlite3 (>= 1.3.5)
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: ../
3
3
  specs:
4
- sorted (1.0.0)
4
+ sorted (1.1.1)
5
5
 
6
6
  GEM
7
7
  remote: https://rubygems.org/
@@ -24,6 +24,9 @@ GEM
24
24
  minitest (~> 5.1)
25
25
  thread_safe (~> 0.1)
26
26
  tzinfo (~> 1.1)
27
+ ast (2.0.0)
28
+ astrolabe (1.3.0)
29
+ parser (>= 2.2.0.pre.3, < 3.0)
27
30
  bson (2.3.0)
28
31
  bson (2.3.0-java)
29
32
  builder (3.2.2)
@@ -45,6 +48,10 @@ GEM
45
48
  optionable (~> 0.2.0)
46
49
  optionable (0.2.0)
47
50
  origin (2.1.1)
51
+ parser (2.2.0.pre.8)
52
+ ast (>= 1.1, < 3.0)
53
+ slop (~> 3.4, >= 3.4.5)
54
+ powerpack (0.0.9)
48
55
  rack (1.5.2)
49
56
  rack-test (0.6.2)
50
57
  rack (>= 1.0)
@@ -53,6 +60,7 @@ GEM
53
60
  activesupport (= 4.1.4)
54
61
  rake (>= 0.8.7)
55
62
  thor (>= 0.18.1, < 2.0)
63
+ rainbow (2.0.0)
56
64
  rake (10.3.2)
57
65
  rspec (3.0.0)
58
66
  rspec-core (~> 3.0.0)
@@ -74,6 +82,14 @@ GEM
74
82
  rspec-mocks (~> 3.0.0)
75
83
  rspec-support (~> 3.0.0)
76
84
  rspec-support (3.0.2)
85
+ rubocop (0.28.0)
86
+ astrolabe (~> 1.3)
87
+ parser (>= 2.2.0.pre.7, < 3.0)
88
+ powerpack (~> 0.0.6)
89
+ rainbow (>= 1.99.1, < 3.0)
90
+ ruby-progressbar (~> 1.4)
91
+ ruby-progressbar (1.7.0)
92
+ slop (3.6.0)
77
93
  thor (0.19.1)
78
94
  thread_safe (0.3.4)
79
95
  thread_safe (0.3.4-java)
@@ -93,4 +109,5 @@ DEPENDENCIES
93
109
  rake
94
110
  rspec (>= 2.0.0)
95
111
  rspec-rails (>= 2.0)
112
+ rubocop (>= 0.28)
96
113
  sorted!
data/lib/sorted.rb CHANGED
@@ -1,8 +1,189 @@
1
1
  require 'sorted/parser'
2
2
 
3
3
  module Sorted
4
+ class Set
5
+ include Enumerable
6
+
7
+ def initialize(set = [])
8
+ @set = set
9
+ end
10
+
11
+ def each(&block)
12
+ @set.each(&block)
13
+ end
14
+
15
+ ##
16
+ # Gets the keys from the array pairs
17
+ #
18
+ # set = [["email", "name"], ["desc", "desc"]]
19
+ # set.transpose #=> [["email", "name"], ["desc", "desc"]]
20
+ # set.transpose.first #=> ["email", "name"]
21
+
22
+ def keys
23
+ @set.transpose.first || []
24
+ end
25
+
26
+ ##
27
+ # Returns a resulting set with specific keys flipped
28
+ #
29
+ # a = Sorted::Set.new([['email', 'asc'], ['name', 'asc']])
30
+ # b = Sorted::Set.new([['email', 'asc'], ['phone', 'asc']])
31
+ # s = a.direction_intersect(b)
32
+ # s.to_a #=> [['email', 'desc'], ['phone', 'asc'], ['name', 'asc']]
33
+
34
+ def direction_intersect(other)
35
+ self.class.new.tap do |memo|
36
+ unless other.keys.empty?
37
+ a(memo, other)
38
+ b(memo, other)
39
+ end
40
+ c(memo)
41
+ d(memo, other)
42
+ end
43
+ end
44
+
45
+ def -(other)
46
+ self.class.new.tap do |memo|
47
+ each do |a|
48
+ b = other.assoc(a.first)
49
+ next if b
50
+ memo << a
51
+ end
52
+ end
53
+ end
54
+
55
+ def +(other)
56
+ self.class.new(@set + other.to_a)
57
+ end
58
+
59
+ def <<(a)
60
+ self.class.new(@set << a)
61
+ end
62
+
63
+ def uniq
64
+ self.class.new(@set.uniq)
65
+ end
66
+
67
+ def assoc(o)
68
+ @set.assoc(o)
69
+ end
70
+
71
+ def at(i)
72
+ @set.at(i)
73
+ end
74
+
75
+ def to_a
76
+ @set
77
+ end
78
+
79
+ def to_hash
80
+ @set.inject({}) { |a, e| a.merge(Hash[e[0], e[1]]) }
81
+ end
82
+
83
+ private
84
+
85
+ # If the order of keys match upto the size of the set then flip them
86
+ def a(memo, other)
87
+ if keys == other.keys.take(keys.size)
88
+ keys.each do |order|
89
+ if other.keys.include?(order)
90
+ memo << [order, flip_direction(other.assoc(order).last)]
91
+ end
92
+ end
93
+ else
94
+ keys.each do |order|
95
+ if other.keys.include?(order)
96
+ memo << other.assoc(order)
97
+ end
98
+ end
99
+ end
100
+ end
101
+
102
+ # Add items from other that are common and not already added
103
+ def b(memo, other)
104
+ other.keys.each do |sort|
105
+ if keys.include?(sort) && !memo.keys.include?(sort)
106
+ memo << other.assoc(sort)
107
+ end
108
+ end
109
+ end
110
+
111
+ # Add items not in memo
112
+ def c(memo)
113
+ each do |order|
114
+ unless memo.keys.include?(order[0])
115
+ memo << order
116
+ end
117
+ end
118
+ end
119
+
120
+ # Add items from other not in memo
121
+ def d(memo, other)
122
+ other.each do |sort|
123
+ unless memo.keys.include?(sort[0])
124
+ memo << sort
125
+ end
126
+ end
127
+ end
128
+
129
+ def flip_direction(direction)
130
+ case direction
131
+ when 'asc' then 'desc'
132
+ when 'desc'then 'asc'
133
+ end
134
+ end
135
+ end
136
+
137
+ module Parse
138
+ def split(raw, delim, &block)
139
+ return Set.new if raw.nil?
140
+ raw.to_s.split(delim).inject(Set.new, &block)
141
+ end
142
+ end
143
+
144
+ class URIQuery
145
+ extend Parse
146
+
147
+ REGEXP = /([a-zA-Z0-9._]+)_(asc|desc)$/
148
+
149
+ def self.parse(raw)
150
+ split(raw, /!/) do |set, part|
151
+ m = part.match(REGEXP)
152
+ return set unless m
153
+ set << [m[1], m[2].downcase]
154
+ end
155
+ end
156
+
157
+ def self.encode(set)
158
+ set.map { |a| a.join('_') }.join('!')
159
+ end
160
+ end
161
+
162
+ class SQLQuery
163
+ extend Parse
164
+
165
+ REGEXP = /(([a-z0-9._]+)\s([asc|desc]+)|[a-z0-9._]+)/i
166
+
167
+ def self.parse(raw)
168
+ split(raw, /,/) do |set, part|
169
+ m = part.match(REGEXP)
170
+ return set unless m
171
+ set << [(m[2].nil? ? m[1] : m[2]), (m[3].nil? ? 'asc' : m[3].downcase)]
172
+ end
173
+ end
174
+
175
+ def self.encode(set, quote_proc = ->(f) { f })
176
+ set.map { |a| "#{column(a[0], quote_proc)} #{a[1].upcase}" }.join(', ')
177
+ end
178
+
179
+ def self.column(parts, quote_proc)
180
+ parts.split('.').map { |frag| quote_proc.call(frag) }.join('.')
181
+ end
182
+ private_class_method :column
183
+ end
4
184
  end
5
185
 
6
186
  if defined?(::Rails::Railtie)
187
+ ActiveSupport::Deprecation.warn('Rails helpers will be removed in version 2.0 of the sorted gem, use sorted-rails instead.')
7
188
  require 'sorted/railtie'
8
189
  end
@@ -5,12 +5,12 @@ module Sorted
5
5
  module Orms
6
6
  module Mongoid
7
7
  extend ActiveSupport::Concern
8
- SQL_TO_MONGO = { "asc" => 1, "desc" => -1 }
8
+ SQL_TO_MONGO = { 'asc' => 1, 'desc' => -1 }
9
9
 
10
10
  included do
11
11
  def self.sorted(sort, default_order = nil)
12
12
  sorter = ::Sorted::Parser.new(sort, default_order)
13
- order_by sorter.to_hash.merge(sorter) { |key, val| SQL_TO_MONGO[val] }
13
+ order_by sorter.to_hash.merge(sorter) { |_key, val| SQL_TO_MONGO[val] }
14
14
  end
15
15
  end
16
16
  end
data/lib/sorted/parser.rb CHANGED
@@ -1,82 +1,68 @@
1
1
  require 'sorted/toggler'
2
2
 
3
3
  module Sorted
4
+ ##
4
5
  # Takes a sort query string and an SQL order string and parses the
6
+ #
5
7
  # values to produce key value pairs.
6
8
  #
7
9
  # 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
10
+ # Sorted::Parser.new('phone_desc', 'name ASC').to_s #=> "phone_desc!name_asc"
11
+ #
12
+ # TODO A more helpfull name than `Parser` because it only deals with URI and
13
+ # SQL. Shoud be refactored before 2.x
11
14
 
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
+ Parser = Struct.new(:sort, :order) do
16
+ def uri
17
+ URIQuery.parse(sort)
18
+ end
15
19
 
16
- def initialize(sort, order = nil)
17
- @sort = sort
18
- @order = order
19
- @sorts = parse_sort
20
- @orders = parse_order
20
+ def sql
21
+ SQLQuery.parse(order)
21
22
  end
22
23
 
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
24
+ def sorts
25
+ uri.to_a
29
26
  end
30
27
 
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
28
+ def orders
29
+ sql.to_a
37
30
  end
38
31
 
39
32
  def to_hash
40
- array.inject({}){|h,a| h.merge(Hash[a[0],a[1]])}
33
+ set.to_hash
41
34
  end
42
35
 
43
- def to_sql(quoter = ->(frag) { frag })
44
- array.map do |a|
45
- column = a[0].split('.').map{ |frag| quoter.call(frag) }.join('.')
46
- "#{column} #{a[1].upcase}"
47
- end.join(', ')
36
+ def to_sql(quote_proc = ->(f) { f })
37
+ SQLQuery.encode(set, quote_proc)
48
38
  end
49
39
 
50
40
  def to_s
51
- array.map{|a| a.join('_') }.join('!')
41
+ URIQuery.encode(set)
52
42
  end
53
43
 
54
44
  def to_a
55
- array
45
+ set.to_a
56
46
  end
57
47
 
58
48
  def toggle
59
- @array = Toggler.new(sorts, orders).to_a
49
+ @set = Toggler.new(sorts, orders).toggle
60
50
  self
61
51
  end
62
52
 
63
53
  def reset
64
- @array = default
54
+ @set = default
65
55
  self
66
56
  end
67
57
 
68
58
  private
69
59
 
70
- def array
71
- @array ||= default
60
+ def set
61
+ @set ||= default
72
62
  end
73
63
 
74
64
  def default
75
- sorts_new = sorts.dup
76
- orders.each do |o|
77
- sorts_new << o unless sorts_new.flatten.include?(o[0])
78
- end
79
- sorts_new
65
+ uri + (sql - uri)
80
66
  end
81
67
  end
82
68
  end
@@ -2,7 +2,7 @@ require 'sorted'
2
2
 
3
3
  module Sorted
4
4
  class Railtie < Rails::Railtie
5
- initializer "sorted.configure" do |app|
5
+ initializer 'sorted.configure' do |_app|
6
6
  if defined? ::ActiveRecord
7
7
  ActiveSupport.on_load :active_record do
8
8
  require 'sorted/orms/active_record'
@@ -1,62 +1,27 @@
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.
2
+ ##
3
+ # Takes a parsed arrays of sorts and orders, it then will reorder the pairs
4
+ # and flip the ascendance of the first sort pair.
4
5
  #
5
6
  # Example:
6
7
  # sorts = [['name', 'asc'], ['phone', 'desc']]
7
8
  # orders = [['name', 'asc']]
8
- # Sorted::Toggler.new(sorts, orders).to_a #-> [['name', 'desc'], ['phone', 'desc']]
9
+ # Sorted::Toggler.new(sorts, orders).to_a
10
+ #
11
+ # TODO Remove this in 2.x, it's only here for backwards compatibility.
12
+
9
13
  class Toggler
10
14
  def initialize(sorts, orders)
11
- @array = []
12
- @sorts = sorts
13
- @orders = orders
14
- @sort_keys = sorts.transpose.first
15
- @order_keys = orders.transpose.first
16
- toggle_sorts unless @sort_keys.nil?
17
- add_remaining_orders
18
- add_remaining_sorts
19
- end
20
-
21
- def to_a
22
- @array
23
- end
24
-
25
- def toggle_sorts
26
- if @order_keys == @sort_keys.take(@order_keys.size)
27
- @order_keys.select do |order|
28
- @sort_keys.include?(order)
29
- end.each do |order|
30
- @array << [order, (case @sorts.assoc(order).last; when "asc"; "desc"; when "desc"; "asc" end)]
31
- end
32
- else
33
- @order_keys.select do |order|
34
- @sort_keys.include?(order)
35
- end.each do |order|
36
- @array << [order, @sorts.assoc(order).last]
37
- end
38
- end
39
- @sort_keys.select do |sort|
40
- @order_keys.include?(sort) && !@array.flatten.include?(sort)
41
- end.each do |sort|
42
- @array << [sort, @sorts.assoc(sort).last]
43
- end
15
+ @sorts = Set.new(sorts)
16
+ @orders = Set.new(orders)
44
17
  end
45
18
 
46
- def add_remaining_orders
47
- @orders.select do |order|
48
- !@array.flatten.include?(order[0])
49
- end.each do |order|
50
- @array << order
51
- end
19
+ def toggle
20
+ @orders.direction_intersect(@sorts)
52
21
  end
53
22
 
54
- def add_remaining_sorts
55
- @sorts.select do |sort|
56
- !@array.flatten.include?(sort[0])
57
- end.each do |sort|
58
- @array << sort
59
- end
23
+ def to_a
24
+ toggle.to_a
60
25
  end
61
26
  end
62
27
  end
@@ -1,3 +1,3 @@
1
1
  module Sorted
2
- VERSION = "1.0.1"
2
+ VERSION = '1.1.1'
3
3
  end
@@ -18,7 +18,7 @@ module Sorted
18
18
  if @parser.sorts.flatten.include? @parser.orders[0][0]
19
19
  "sorted #{@parser.sorts.assoc(@parser.orders[0][0]).last}"
20
20
  else
21
- "sorted"
21
+ 'sorted'
22
22
  end
23
23
  end
24
24
  end
@@ -71,10 +71,10 @@ module Sorted
71
71
  # sortable_by :author_name, :title, ["Date of Publication", :published_at]
72
72
  #
73
73
  def sortable_by(*columns)
74
- links = content_tag :span, "Sort by: "
74
+ links = content_tag :span, 'Sort by: '
75
75
  columns.each do |c|
76
76
  if c.is_a? Array
77
- links += link_to_sorted(c[0],c[1].to_sym)
77
+ links += link_to_sorted(c[0], c[1].to_sym)
78
78
  else
79
79
  links += link_to_sorted(c.to_s.titleize, c.to_sym)
80
80
  end
data/sorted.gemspec CHANGED
@@ -1,27 +1,28 @@
1
1
  # -*- encoding: utf-8 -*-
2
- require File.expand_path("../lib/sorted/version", __FILE__)
2
+ require File.expand_path('../lib/sorted/version', __FILE__)
3
3
 
4
4
  Gem::Specification.new do |s|
5
- s.name = "sorted"
5
+ s.name = 'sorted'
6
6
  s.version = Sorted::VERSION
7
7
  s.platform = Gem::Platform::RUBY
8
- s.authors = ["Rufus Post", "Daniel Leavitt"]
9
- s.email = ["rufuspost@gmail.com", "daniel.leavitt@gmail.com"]
10
- s.homepage = "http://rubygems.org/gems/sorted"
11
- s.summary = %q{Data sorting library}
12
- s.description = %q{Allows you to sort large datasets over many pages, without losing state.}
13
- s.license = "MIT"
8
+ s.authors = ['Rufus Post', 'Daniel Leavitt']
9
+ s.email = ['rufuspost@gmail.com', 'daniel.leavitt@gmail.com']
10
+ s.homepage = 'http://rubygems.org/gems/sorted'
11
+ s.summary = 'Data sorting library'
12
+ s.description = 'Allows you to sort large datasets over many pages, without losing state.'
13
+ s.license = 'MIT'
14
14
 
15
- s.required_rubygems_version = ">= 1.3.6"
16
- s.rubyforge_project = "sorted"
15
+ s.required_rubygems_version = '>= 1.3.6'
16
+ s.rubyforge_project = 'sorted'
17
17
 
18
- s.add_development_dependency "rake", ">= 0"
19
- s.add_development_dependency "bundler", ">= 1.0.0"
20
- s.add_development_dependency "rspec", ">= 2.0.0"
21
- s.add_development_dependency "activesupport", ">= 3.0.0"
22
- s.add_development_dependency "actionpack", ">= 3.0.0"
18
+ s.add_development_dependency 'rake', '>= 0'
19
+ s.add_development_dependency 'bundler', '>= 1.0.0'
20
+ s.add_development_dependency 'rspec', '>= 2.0.0'
21
+ s.add_development_dependency 'activesupport', '>= 3.0.0'
22
+ s.add_development_dependency 'actionpack', '>= 3.0.0'
23
+ s.add_development_dependency 'rubocop', '>= 0.28'
23
24
 
24
25
  s.files = `git ls-files`.split("\n")
25
- s.executables = `git ls-files`.split("\n").map{|f| f =~ /^bin\/(.*)/ ? $1 : nil}.compact
26
+ s.executables = `git ls-files`.split("\n").map { |f| f =~ /^bin\/(.*)/ ? Regexp.last_match[1] : nil }.compact
26
27
  s.require_path = 'lib'
27
28
  end
@@ -14,20 +14,20 @@ if defined? ActiveRecord
14
14
  scope :page, -> { limit(50) }
15
15
  end
16
16
 
17
- it "should integrate with ActiveRecord::Base" do
17
+ it 'should integrate with ActiveRecord::Base' do
18
18
  SortedActiveRecordTest.should respond_to(:sorted)
19
19
  SortedActiveRecordTest.should respond_to(:resorted)
20
20
  end
21
21
 
22
- it "should play nice with other scopes" do
22
+ it 'should play nice with other scopes' do
23
23
  sql = "SELECT \"sorted_active_record_tests\".* FROM \"sorted_active_record_tests\" WHERE \"sorted_active_record_tests\".\"name\" = 'bob' ORDER BY \"name\" ASC LIMIT 50"
24
- SortedActiveRecordTest.where(:name => 'bob').page.sorted(nil, 'name ASC').to_sql.should == sql
25
- SortedActiveRecordTest.page.sorted(nil, 'name ASC').where(:name => 'bob').to_sql.should == sql
24
+ SortedActiveRecordTest.where(name: 'bob').page.sorted(nil, 'name ASC').to_sql.should == sql
25
+ SortedActiveRecordTest.page.sorted(nil, 'name ASC').where(name: 'bob').to_sql.should == sql
26
26
  end
27
27
 
28
- it "should override the provided order" do
28
+ it 'should override the provided order' do
29
29
  sql = "SELECT \"sorted_active_record_tests\".* FROM \"sorted_active_record_tests\" WHERE \"sorted_active_record_tests\".\"name\" = 'bob' ORDER BY \"name\" ASC LIMIT 50"
30
- SortedActiveRecordTest.page.where(:name => 'bob').order(:id).sorted(nil, 'name DESC').resorted(nil, 'name ASC').to_sql.should == sql
30
+ SortedActiveRecordTest.page.where(name: 'bob').order(:id).sorted(nil, 'name DESC').resorted(nil, 'name ASC').to_sql.should == sql
31
31
  end
32
32
  end
33
33
  end
@@ -15,16 +15,16 @@ if defined? Mongoid
15
15
  end
16
16
  end
17
17
 
18
- it "should integrate with Mongoid::Document" do
18
+ it 'should integrate with Mongoid::Document' do
19
19
  SortedMongoidTest.should respond_to(:sorted)
20
20
  end
21
21
 
22
- it "should integrate with Mongoid::Criteria" do
22
+ it 'should integrate with Mongoid::Criteria' do
23
23
  SortedMongoidTest.page.should respond_to(:sorted)
24
24
  end
25
25
 
26
- it "should play nice with other scopes" do
27
- query_options = { limit: 50, sort: { "name" => 1 } }
26
+ it 'should play nice with other scopes' do
27
+ query_options = { limit: 50, sort: { 'name' => 1 } }
28
28
  SortedMongoidTest.page.sorted(nil, 'name ASC').options.should == query_options
29
29
  SortedMongoidTest.page.sorted(nil, 'name ASC').options.should == query_options
30
30
  end
@@ -1,66 +1,66 @@
1
1
  require 'spec_helper'
2
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
3
+ describe Sorted::Parser, 'params parsing' do
4
+ it 'should not raise if pased nil arguments' do
5
+ -> { Sorted::Parser.new(nil, nil).toggle }.should_not raise_error
6
6
  end
7
7
 
8
- it "should return a nice array from the order sql" do
8
+ it 'should return a nice array from the order sql' do
9
9
  sort = nil
10
- order = "email ASC, phone ASC, name DESC"
11
- result = [["email", "asc"], ["phone", "asc"], ["name", "desc"]]
10
+ order = 'email ASC, phone ASC, name DESC'
11
+ result = [['email', 'asc'], ['phone', 'asc'], ['name', 'desc']]
12
12
 
13
13
  sorter = Sorted::Parser.new(sort, order)
14
14
  sorter.orders.should eq result
15
15
  end
16
16
 
17
- it "should return a nice array from the sort params" do
18
- sort = "email_desc!name_desc"
17
+ it 'should return a nice array from the sort params' do
18
+ sort = 'email_desc!name_desc'
19
19
  order = nil
20
- result = [["email", "desc"], ["name", "desc"]]
20
+ result = [['email', 'desc'], ['name', 'desc']]
21
21
 
22
22
  sorter = Sorted::Parser.new(sort, order)
23
23
  sorter.sorts.should eq result
24
24
  end
25
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"]]
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
30
 
31
31
  sorter = Sorted::Parser.new(sort, order)
32
32
  sorter.to_a.should eq result
33
33
  end
34
34
 
35
- it "should allow numbers, underscores and full stops in sort params" do
36
- sort = "assessmentsTable.name_desc!users_300.name_5_desc"
35
+ it 'should allow numbers, underscores and full stops in sort params' do
36
+ sort = 'assessmentsTable.name_desc!users_300.name_5_desc'
37
37
  order = nil
38
- result = [["assessmentsTable.name", "desc"], ["users_300.name_5", "desc"]]
38
+ result = [['assessmentsTable.name', 'desc'], ['users_300.name_5', 'desc']]
39
39
 
40
40
  sorter = Sorted::Parser.new(sort, order)
41
41
  sorter.sorts.should eq result
42
42
  end
43
43
 
44
- it "should allow numbers, underscores and full stops in order params" do
44
+ it 'should allow numbers, underscores and full stops in order params' do
45
45
  sort = nil
46
- order = "assessmentsTable.name ASC, users_300.name_5 ASC"
47
- result = [["assessmentsTable.name", "asc"], ["users_300.name_5", "asc"]]
46
+ order = 'assessmentsTable.name ASC, users_300.name_5 ASC'
47
+ result = [['assessmentsTable.name', 'asc'], ['users_300.name_5', 'asc']]
48
48
 
49
49
  sorter = Sorted::Parser.new(sort, order)
50
50
  sorter.orders.should eq result
51
51
  end
52
52
 
53
- it "should default to asc if sort params order is ommited" do
53
+ it 'should default to asc if sort params order is ommited' do
54
54
  sort = nil
55
55
  order = :email
56
- result = [["email", "asc"]]
56
+ result = [['email', 'asc']]
57
57
 
58
58
  sorter = Sorted::Parser.new(sort, order)
59
59
  sorter.orders.should eq result
60
60
  end
61
61
  end
62
62
 
63
- describe Sorted::Parser, "return types" do
63
+ describe Sorted::Parser, 'return types' do
64
64
  module FakeConnection
65
65
  def self.quote_column_name(column_name)
66
66
  "`#{column_name}`"
@@ -71,45 +71,45 @@ describe Sorted::Parser, "return types" do
71
71
  ->(frag) { FakeConnection.quote_column_name(frag) }
72
72
  }
73
73
 
74
- it "should properly escape sql column names" do
75
- order = "users.name DESC"
76
- result = "`users`.`name` DESC"
74
+ it 'should properly escape sql column names' do
75
+ order = 'users.name DESC'
76
+ result = '`users`.`name` DESC'
77
77
 
78
78
  sorter = Sorted::Parser.new(nil, order)
79
79
  sorter.to_sql(quoter).should eq result
80
80
  end
81
81
 
82
- it "should return an sql 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"
82
+ it 'should return an sql 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
86
 
87
87
  sorter = Sorted::Parser.new(sort, order)
88
88
  sorter.to_sql(quoter).should eq result
89
89
  end
90
90
 
91
- it "should return an hash" do
92
- sort = "email_desc!name_desc"
93
- order = "email ASC, phone ASC, name DESC"
94
- result = {"email" => "desc", "name" => "desc", "phone" => "asc"}
91
+ it 'should return an hash' do
92
+ sort = 'email_desc!name_desc'
93
+ order = 'email ASC, phone ASC, name DESC'
94
+ result = { 'email' => 'desc', 'name' => 'desc', 'phone' => 'asc' }
95
95
 
96
96
  sorter = Sorted::Parser.new(sort, order)
97
97
  sorter.to_hash.should eq result
98
98
  end
99
99
 
100
- it "should return an the encoded sort string" do
101
- sort = "email_desc!name_desc"
102
- order = "email ASC, phone ASC, name DESC"
103
- result = "email_desc!name_desc!phone_asc"
100
+ it 'should return an the encoded sort string' do
101
+ sort = 'email_desc!name_desc'
102
+ order = 'email ASC, phone ASC, name DESC'
103
+ result = 'email_desc!name_desc!phone_asc'
104
104
 
105
105
  sorter = Sorted::Parser.new(sort, order)
106
106
  sorter.to_s.should eq result
107
107
  end
108
108
 
109
- it "sql injection using order by clause should not work" do
110
- sort = "(case+when+((ASCII(SUBSTR((select+table_name+from+all_tables+where+rownum%3d1),1))>%3D128))+then+id+else+something+end)"
111
- order = "email ASC, phone ASC, name DESC"
112
- result = "`email` ASC, `phone` ASC, `name` DESC"
109
+ it 'sql injection using order by clause should not work' do
110
+ sort = '(case+when+((ASCII(SUBSTR((select+table_name+from+all_tables+where+rownum%3d1),1))>%3D128))+then+id+else+something+end)'
111
+ order = 'email ASC, phone ASC, name DESC'
112
+ result = '`email` ASC, `phone` ASC, `name` DESC'
113
113
 
114
114
  sorter = Sorted::Parser.new(sort, order)
115
115
  sorter.to_sql(quoter).should eq result
@@ -1,55 +1,73 @@
1
1
  require 'spec_helper'
2
2
 
3
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"]]
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
8
 
9
9
  toggler = Sorted::Toggler.new(sorts, orders)
10
10
  toggler.to_a.should eq result
11
11
  end
12
12
 
13
- it "should toggle ascendance of email" do
14
- orders = [["email", "desc"]]
15
- sorts = [["email", "asc"]]
16
- result = [["email", "desc"]]
13
+ it 'should toggle ascendance of email' do
14
+ orders = [['email', 'desc']]
15
+ sorts = [['email', 'asc']]
16
+ result = [['email', 'desc']]
17
17
 
18
18
  toggler = Sorted::Toggler.new(sorts, orders)
19
19
  toggler.to_a.should eq result
20
20
  end
21
21
 
22
- it "should return both order params un-toggled with no sort param" do
23
- orders = [["email", "asc"], ["phone", "asc"]]
22
+ it 'should return both order params un-toggled with no sort param' do
23
+ orders = [['email', 'asc'], ['phone', 'asc']]
24
24
  sorts = []
25
- result = [["email", "asc"], ["phone", "asc"]]
25
+ result = [['email', 'asc'], ['phone', 'asc']]
26
26
 
27
27
  toggler = Sorted::Toggler.new(sorts, orders)
28
28
  toggler.to_a.should eq result
29
29
  end
30
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"]]
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
35
 
36
36
  toggler = Sorted::Toggler.new(sorts, orders)
37
37
  toggler.to_a.should eq result
38
38
  end
39
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"]]
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
44
 
45
45
  toggler = Sorted::Toggler.new(sorts, orders)
46
46
  toggler.to_a.should eq result
47
47
  end
48
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"]]
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
+
58
+ it 'should toggle based on sorts and not orders' do
59
+ orders = [['email', 'desc'], ['phone', 'desc']]
60
+ sorts = [['email', 'asc'], ['phone', 'asc']]
61
+ result = [['email', 'desc'], ['phone', 'desc']]
62
+
63
+ toggler = Sorted::Toggler.new(sorts, orders)
64
+ toggler.to_a.should eq result
65
+ end
66
+
67
+ it 'should toggle based on sorts and not orders' do
68
+ orders = [['email', 'asc']]
69
+ sorts = [['name', 'asc']]
70
+ result = [['email', 'asc'], ['name', 'asc']]
53
71
 
54
72
  toggler = Sorted::Toggler.new(sorts, orders)
55
73
  toggler.to_a.should eq result
@@ -1,45 +1,63 @@
1
1
  require 'spec_helper'
2
2
 
3
3
  describe Sorted::ViewHelpers::ActionView do
4
- it "should integrate with ActiveRecord::Base" do
4
+ it 'should integrate with ActiveRecord::Base' do
5
5
  ActionView::Base.send(:include, Sorted::ViewHelpers::ActionView)
6
6
  ActionView::Base.new.should respond_to(:link_to_sorted)
7
7
  end
8
8
  end
9
9
 
10
10
  describe Sorted::ViewHelpers::ActionView::SortedViewHelper do
11
- it "should return the default sort order and preserve the existing params" do
11
+ it 'should return the default sort order and preserve the existing params' do
12
12
  order = :email
13
- params = { :page => 10 }
14
- result = { :page => 10, :sort => "email_asc" }
13
+ params = { page: 10 }
14
+ result = { page: 10, sort: 'email_asc' }
15
15
 
16
16
  sorter = Sorted::ViewHelpers::ActionView::SortedViewHelper.new order, params
17
17
  sorter.params.should eq result
18
18
  end
19
19
 
20
- it "should only return the sorted css class if email has not yet been sorted" do
20
+ it 'should only return the sorted css class if email has not yet been sorted' do
21
21
  order = :email
22
22
  params = {}
23
- result = "sorted"
23
+ result = 'sorted'
24
24
 
25
25
  sorter = Sorted::ViewHelpers::ActionView::SortedViewHelper.new order, params
26
26
  sorter.css.should eq result
27
27
  end
28
28
 
29
- it "should only return the sorted css class if email has not yet been sorted" do
29
+ it 'should only return the sorted css class if email has not yet been sorted' do
30
30
  order = :email
31
- params = { :sort => "email_asc" }
32
- result = "sorted asc"
31
+ params = { sort: 'email_asc' }
32
+ result = 'sorted asc'
33
33
 
34
34
  sorter = Sorted::ViewHelpers::ActionView::SortedViewHelper.new order, params
35
35
  sorter.css.should eq result
36
36
  end
37
37
 
38
- it "should return the default order when params are empty" do
38
+ it 'should return the default order when params are empty' do
39
39
  order = :email
40
- result = { :sort => "email_asc" }
40
+ result = { sort: 'email_asc' }
41
41
 
42
42
  sorter = Sorted::ViewHelpers::ActionView::SortedViewHelper.new order, {}
43
43
  sorter.params.should eq result
44
44
  end
45
+
46
+ it 'should correctly toggle multiple params' do
47
+ order = 'email DESC, name DESC'
48
+ params = { sort: 'email_asc!name_asc' }
49
+ result = { sort: 'email_desc!name_desc' }
50
+
51
+ sorter = Sorted::ViewHelpers::ActionView::SortedViewHelper.new order, params
52
+ sorter.params.should eq result
53
+ end
54
+
55
+ it 'should have sort order over existing params' do
56
+ order = :email
57
+ params = { sort: 'name_asc' }
58
+ result = { sort: 'email_asc!name_asc' }
59
+
60
+ sorter = Sorted::ViewHelpers::ActionView::SortedViewHelper.new order, params
61
+ sorter.params.should eq result
62
+ end
45
63
  end
data/spec/spec_helper.rb CHANGED
@@ -1,14 +1,6 @@
1
1
  $LOAD_PATH.unshift(File.dirname(__FILE__))
2
2
  $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
3
3
 
4
- begin
5
- require 'rails'
6
- rescue LoadError
7
- end
8
-
9
- require 'bundler/setup'
10
- Bundler.require
11
-
12
4
  require 'sorted'
13
5
  require 'sorted/orms/mongoid'
14
6
  require 'sorted/orms/active_record'
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: 1.0.1
4
+ version: 1.1.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Rufus Post
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2014-08-12 00:00:00.000000000 Z
12
+ date: 2015-01-27 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: rake
@@ -81,6 +81,20 @@ dependencies:
81
81
  - - ">="
82
82
  - !ruby/object:Gem::Version
83
83
  version: 3.0.0
84
+ - !ruby/object:Gem::Dependency
85
+ name: rubocop
86
+ requirement: !ruby/object:Gem::Requirement
87
+ requirements:
88
+ - - ">="
89
+ - !ruby/object:Gem::Version
90
+ version: '0.28'
91
+ type: :development
92
+ prerelease: false
93
+ version_requirements: !ruby/object:Gem::Requirement
94
+ requirements:
95
+ - - ">="
96
+ - !ruby/object:Gem::Version
97
+ version: '0.28'
84
98
  description: Allows you to sort large datasets over many pages, without losing state.
85
99
  email:
86
100
  - rufuspost@gmail.com
@@ -91,6 +105,8 @@ extra_rdoc_files: []
91
105
  files:
92
106
  - ".gitignore"
93
107
  - ".rspec"
108
+ - ".rubocop.yml"
109
+ - ".rubocop_todo.yml"
94
110
  - ".travis.yml"
95
111
  - Gemfile
96
112
  - LICENSE
@@ -135,7 +151,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
135
151
  version: 1.3.6
136
152
  requirements: []
137
153
  rubyforge_project: sorted
138
- rubygems_version: 2.2.0
154
+ rubygems_version: 2.4.5
139
155
  signing_key:
140
156
  specification_version: 4
141
157
  summary: Data sorting library