sorted 1.1.1 → 2.0.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 1b665b8a96ecf9464b3c3845dae2edbdf3a8fef8
4
- data.tar.gz: f698bb91b0fa131eef2928a89d8125f19813dde9
3
+ metadata.gz: 24619b1bb18184b31fed12d6dc314cea988201f7
4
+ data.tar.gz: 5b31c5ef8375ca83aa0853e2fe219477fa40afe5
5
5
  SHA512:
6
- metadata.gz: d4cd81b4bde74202c5ab1a6e4f6bce6696fc882c78392dcba6a59539e658819dcc8080683a2da19b939028a55f4c76be7f3533e35092944278151b4bde1c25b6
7
- data.tar.gz: a5e122727f4e42a6756b5b08685e8cff49db754446bcd95f8e00d205fdf289a4699a46ee81d5d3e2d36846411532771b32a7b0d21b545f8a1a6a1b3dc1946474
6
+ metadata.gz: 2a285ff4a99085d9ca9740a6e4c5187a594b14a6698750b03ec2e8846473d6f93145aedff4f1c98bfdd4aa4b32c28d395d3908ed428bbf4b62818f52f9461ff2
7
+ data.tar.gz: f77377cd895a964111ff98edf7fe62e16193a8ee5f397b9613fa1db66f7a6631f861f1a0cab2fbcb622fec21cec8ec833b25b2a3b1dad528b5d3de50418b9c2e
data/README.md CHANGED
@@ -1,7 +1,6 @@
1
1
  # sorted
2
2
 
3
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)
5
4
 
6
5
  Sorted at it's core is a set of objects that let you sort many different
7
6
  attributes in weird and wonderful ways.
@@ -16,7 +15,7 @@ b = Sorted::Set.new([['email', 'asc'], ['phone', 'asc']])
16
15
 
17
16
  s = a.direction_intersect(b)
18
17
 
19
- s.uniq.to_a #=> [['email', 'desc'], ['phone', 'asc'], ['name', 'asc']]
18
+ s.to_a #=> [['email', 'desc'], ['phone', 'asc'], ['name', 'asc']]
20
19
  ```
21
20
 
22
21
  The best way to think about this is to imagine a spreed sheet and what happens
@@ -35,46 +34,10 @@ Currently implemented:
35
34
 
36
35
  * `Sorted::SQLQuery`
37
36
  * `Sorted::URIQuery`
37
+ * `Sorted::JSONQuery`
38
38
 
39
- TODO:
39
+ ## Projects
40
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
48
- [will_paginate](https://github.com/mislav/will_paginate) or
49
- [kaminari](https://github.com/amatsuda/kaminari)) without losing state.
50
-
51
- ### View
52
-
53
- Generate a sorted link with the email attribute:
54
-
55
- ```ruby
56
- link_to_sorted "Email", :email
57
- ```
58
-
59
- Works the same as the `link_to` method except a second argument for the
60
- sort attribute is needed.
61
-
62
- ### Model
63
-
64
- Using the `sorted` method with the optional default order argument:
65
-
66
- ```ruby
67
- @users = User.sorted(params[:sort], "email ASC").page(params[:page])
68
- ```
69
-
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:
72
-
73
- ```ruby
74
- @users = User.order(:id).sorted(nil, 'name DESC').resorted(params[:sort], 'email ASC')
75
- ```
76
-
77
- ## Supported ORMs
78
-
79
- * ActiveRecord
80
- * Mongoid
41
+ * Mongoid https://github.com/dleavitt/sorted-mongoid
42
+ * ActiveRecord https://github.com/mynameisrufus/sorted-activerecord
43
+ * ActionView https://github.com/mynameisrufus/sorted-actionview
data/Rakefile CHANGED
@@ -19,30 +19,24 @@ Rake::RDocTask.new do |rdoc|
19
19
  rdoc.rdoc_files.include('lib/**/*.rb')
20
20
  end
21
21
 
22
- namespace :spec do
23
- desc 'Run Tests against all ORMs'
24
- task :all do
25
- %w(active_record_40 mongoid_30).each do |gemfile|
26
- sh "BUNDLE_GEMFILE='gemfiles/#{gemfile}.gemfile' bundle --quiet"
27
- sh "BUNDLE_GEMFILE='gemfiles/#{gemfile}.gemfile' bundle exec rake -t spec"
28
- end
29
- end
30
- end
31
-
32
22
  task :benchmark do
33
23
  require 'benchmark'
34
24
 
35
- sort = 'email_desc!name_desc'
36
- order = 'email ASC, phone ASC, name DESC'
25
+ uri = 'email_desc!name_desc'
26
+ sql = 'email ASC, phone ASC, name DESC'
27
+
28
+ uri_set = Sorted::SQLQuery.parse(uri)
29
+ sql_set = Sorted::SQLQuery.parse(sql)
37
30
 
38
31
  n = 50_000
39
32
  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 }
33
+ # Query
34
+ x.report(:uri_parse) { for i in 1..n; Sorted::URIQuery.parse(uri); end }
35
+ x.report(:sql_parse) { for i in 1..n; Sorted::SQLQuery.parse(sql); end }
36
+
37
+ # Set
38
+ x.report(:direction_intersect) { for i in 1..n; sql_set.direction_intersect(uri_set); end }
45
39
  end
46
40
  end
47
41
 
48
- task default: ['rubocop', 'spec:all']
42
+ task default: ['rubocop', 'spec']
data/lib/sorted.rb CHANGED
@@ -1,8 +1,7 @@
1
- require 'sorted/parser'
2
-
3
1
  module Sorted
4
2
  class Set
5
3
  include Enumerable
4
+ include Comparable
6
5
 
7
6
  def initialize(set = [])
8
7
  @set = set
@@ -60,6 +59,10 @@ module Sorted
60
59
  self.class.new(@set << a)
61
60
  end
62
61
 
62
+ def <=>(other)
63
+ @set <=> other.to_a
64
+ end
65
+
63
66
  def uniq
64
67
  self.class.new(@set.uniq)
65
68
  end
@@ -181,9 +184,19 @@ module Sorted
181
184
  end
182
185
  private_class_method :column
183
186
  end
184
- end
185
187
 
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.')
188
- require 'sorted/railtie'
188
+ class JSONQuery
189
+ extend Parse
190
+
191
+ JSON_TO_SORTED = { 1 => 'asc', -1 => 'desc' }
192
+ SORTED_TO_JSON = { 'asc' => 1, 'desc' => -1 }
193
+
194
+ def self.parse(raw)
195
+ Set.new(raw.map { |key, val| [key, JSON_TO_SORTED[val]] })
196
+ end
197
+
198
+ def self.encode(set)
199
+ set.inject({}) { |a, e| a.merge(Hash[e[0], SORTED_TO_JSON[e[1]]]) }
200
+ end
201
+ end
189
202
  end
@@ -1,3 +1,3 @@
1
1
  module Sorted
2
- VERSION = '1.1.1'
2
+ VERSION = '2.0.0'
3
3
  end
data/sorted.gemspec CHANGED
@@ -5,11 +5,11 @@ Gem::Specification.new do |s|
5
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']
8
+ s.authors = ['Rufus Post']
9
+ s.email = ['rufuspost@gmail.com']
10
10
  s.homepage = 'http://rubygems.org/gems/sorted'
11
11
  s.summary = 'Data sorting library'
12
- s.description = 'Allows you to sort large datasets over many pages, without losing state.'
12
+ s.description = 'Data sorting library, used by other libs to construct queries and more'
13
13
  s.license = 'MIT'
14
14
 
15
15
  s.required_rubygems_version = '>= 1.3.6'
@@ -18,8 +18,6 @@ Gem::Specification.new do |s|
18
18
  s.add_development_dependency 'rake', '>= 0'
19
19
  s.add_development_dependency 'bundler', '>= 1.0.0'
20
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
21
  s.add_development_dependency 'rubocop', '>= 0.28'
24
22
 
25
23
  s.files = `git ls-files`.split("\n")
@@ -0,0 +1,20 @@
1
+ require 'spec_helper'
2
+
3
+ describe Sorted::JSONQuery, 'decode' do
4
+ it 'should return a nice array from the order sql' do
5
+ json = { 'email' => 1, 'phone' => 1, 'name' => -1 }
6
+ set = Sorted::JSONQuery.parse(json)
7
+ result = Sorted::Set.new([['email', 'asc'], ['phone', 'asc'], ['name', 'desc']])
8
+
9
+ expect(set).to eq(result)
10
+ end
11
+ end
12
+
13
+ describe Sorted::JSONQuery, 'encode' do
14
+ it 'should return an sql sort string' do
15
+ set = Sorted::Set.new([['email', 'desc'], ['name', 'desc'], ['phone', 'asc']])
16
+ result = { 'email' => -1, 'phone' => 1, 'name' => -1 }
17
+
18
+ expect(Sorted::JSONQuery.encode(set)).to eq(result)
19
+ end
20
+ end
data/spec/set_spec.rb ADDED
@@ -0,0 +1,74 @@
1
+ require 'spec_helper'
2
+
3
+ describe Sorted::Set do
4
+ it 'should bring phone to first order importance but not toggle ascendance' do
5
+ orders = Sorted::Set.new([['email', 'asc'], ['phone', 'asc']])
6
+ sorts = Sorted::Set.new([['phone', 'asc']])
7
+ result = Sorted::Set.new([['phone', 'asc'], ['email', 'asc']])
8
+
9
+ expect(orders.direction_intersect(sorts)).to eq(result)
10
+ end
11
+
12
+ it 'should toggle ascendance of email' do
13
+ orders = Sorted::Set.new([['email', 'desc']])
14
+ sorts = Sorted::Set.new([['email', 'asc']])
15
+ result = Sorted::Set.new([['email', 'desc']])
16
+
17
+ expect(orders.direction_intersect(sorts)).to eq(result)
18
+ end
19
+
20
+ it 'should return both order params un-toggled with no sort param' do
21
+ orders = Sorted::Set.new([['email', 'asc'], ['phone', 'asc']])
22
+ sorts = Sorted::Set.new([])
23
+ result = Sorted::Set.new([['email', 'asc'], ['phone', 'asc']])
24
+
25
+ expect(orders.direction_intersect(sorts)).to eq(result)
26
+ end
27
+
28
+ it 'should toggle the email ascendance' do
29
+ orders = Sorted::Set.new([['email', 'asc']])
30
+ sorts = Sorted::Set.new([['email', 'asc'], ['phone', 'asc']])
31
+ result = Sorted::Set.new([['email', 'desc'], ['phone', 'asc']])
32
+
33
+ expect(orders.direction_intersect(sorts)).to eq(result)
34
+ end
35
+
36
+ it 'should toggle the email ascendance' do
37
+ orders = Sorted::Set.new([['email', 'desc']])
38
+ sorts = Sorted::Set.new([['email', 'asc'], ['phone', 'asc']])
39
+ result = Sorted::Set.new([['email', 'desc'], ['phone', 'asc']])
40
+
41
+ expect(orders.direction_intersect(sorts)).to eq(result)
42
+ end
43
+
44
+ it 'should toggle two 1..n sort values' do
45
+ orders = Sorted::Set.new([['email', 'asc'], ['phone', 'asc']])
46
+ sorts = Sorted::Set.new([['email', 'asc'], ['phone', 'asc']])
47
+ result = Sorted::Set.new([['email', 'desc'], ['phone', 'desc']])
48
+
49
+ expect(orders.direction_intersect(sorts)).to eq(result)
50
+ end
51
+
52
+ it 'should toggle based on sorts and not orders' do
53
+ orders = Sorted::Set.new([['email', 'desc'], ['phone', 'desc']])
54
+ sorts = Sorted::Set.new([['email', 'asc'], ['phone', 'asc']])
55
+ result = Sorted::Set.new([['email', 'desc'], ['phone', 'desc']])
56
+
57
+ expect(orders.direction_intersect(sorts)).to eq(result)
58
+ end
59
+
60
+ it 'should toggle based on sorts and not orders' do
61
+ orders = Sorted::Set.new([['email', 'asc']])
62
+ sorts = Sorted::Set.new([['name', 'asc']])
63
+ result = Sorted::Set.new([['email', 'asc'], ['name', 'asc']])
64
+
65
+ expect(orders.direction_intersect(sorts)).to eq(result)
66
+ end
67
+
68
+ it 'should return a hash' do
69
+ set = Sorted::Set.new([['email', 'asc']])
70
+ result = { 'email' => 'asc' }
71
+
72
+ expect(set.to_hash).to eq(result)
73
+ end
74
+ end
data/spec/spec_helper.rb CHANGED
@@ -1,8 +1,5 @@
1
1
  $LOAD_PATH.unshift(File.dirname(__FILE__))
2
2
  $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
3
3
 
4
- require 'sorted'
5
- require 'sorted/orms/mongoid'
6
- require 'sorted/orms/active_record'
7
- require 'sorted/view_helpers/action_view'
8
4
  require 'rspec'
5
+ require 'sorted'
@@ -0,0 +1,61 @@
1
+ require 'spec_helper'
2
+
3
+ describe Sorted::SQLQuery, 'decode' do
4
+ it 'should return a nice array from the order sql' do
5
+ sql = 'email ASC, phone ASC, name DESC'
6
+ set = Sorted::SQLQuery.parse(sql)
7
+ result = Sorted::Set.new([['email', 'asc'], ['phone', 'asc'], ['name', 'desc']])
8
+
9
+ expect(set).to eq(result)
10
+ end
11
+
12
+ it 'should allow numbers, underscores and full stops in order params' do
13
+ sql = 'assessmentsTable.name ASC, users_300.name_5 ASC'
14
+ set = Sorted::SQLQuery.parse(sql)
15
+ result = Sorted::Set.new([['assessmentsTable.name', 'asc'], ['users_300.name_5', 'asc']])
16
+
17
+ expect(set).to eq(result)
18
+ end
19
+
20
+ it 'should default to asc if sort params order is ommited' do
21
+ sql = :email
22
+ set = Sorted::SQLQuery.parse(sql)
23
+ result = [['email', 'asc']]
24
+
25
+ expect(set).to eq(result)
26
+ end
27
+
28
+ it 'sql injection using order by clause should not work' do
29
+ sql = '(case+when+((ASCII(SUBSTR((select+table_name+from+all_tables+where+rownum%3d1),1))>%3D128))+then+id+else+something+end)'
30
+ set = Sorted::SQLQuery.parse(sql)
31
+ result = Sorted::Set.new([['case', 'asc'], ['1', 'asc']])
32
+
33
+ expect(set).to eq(result)
34
+ end
35
+ end
36
+
37
+ describe Sorted::SQLQuery, 'encode' do
38
+ module FakeConnection
39
+ def self.quote_column_name(column_name)
40
+ "`#{column_name}`"
41
+ end
42
+ end
43
+
44
+ let(:quoter) {
45
+ ->(frag) { FakeConnection.quote_column_name(frag) }
46
+ }
47
+
48
+ it 'should properly escape sql column names' do
49
+ set = Sorted::Set.new([['users.name', 'desc']])
50
+ result = '`users`.`name` DESC'
51
+
52
+ expect(Sorted::SQLQuery.encode(set, quoter)).to eq(result)
53
+ end
54
+
55
+ it 'should return an sql sort string' do
56
+ set = Sorted::Set.new([['email', 'desc'], ['name', 'desc'], ['phone', 'asc']])
57
+ result = '`email` DESC, `name` DESC, `phone` ASC'
58
+
59
+ expect(Sorted::SQLQuery.encode(set, quoter)).to eq(result)
60
+ end
61
+ end
@@ -0,0 +1,20 @@
1
+ require 'spec_helper'
2
+
3
+ describe Sorted::URIQuery, 'decode' do
4
+ it 'should allow numbers, underscores and full stops in sort params' do
5
+ uri = 'assessmentsTable.name_desc!users_300.name_5_desc'
6
+ set = Sorted::URIQuery.parse(uri)
7
+ result = [['assessmentsTable.name', 'desc'], ['users_300.name_5', 'desc']]
8
+
9
+ expect(set).to eq(result)
10
+ end
11
+ end
12
+
13
+ describe Sorted::URIQuery, 'encode' do
14
+ it 'should return a nice array from the sort params' do
15
+ set = Sorted::Set.new([['email', 'desc'], ['name', 'desc'], ['phone', 'asc']])
16
+ result = 'email_desc!name_desc!phone_asc'
17
+
18
+ expect(Sorted::URIQuery.encode(set)).to eq(result)
19
+ end
20
+ end
metadata CHANGED
@@ -1,15 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: sorted
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.1.1
4
+ version: 2.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Rufus Post
8
- - Daniel Leavitt
9
8
  autorequire:
10
9
  bindir: bin
11
10
  cert_chain: []
12
- date: 2015-01-27 00:00:00.000000000 Z
11
+ date: 2015-01-31 00:00:00.000000000 Z
13
12
  dependencies:
14
13
  - !ruby/object:Gem::Dependency
15
14
  name: rake
@@ -53,34 +52,6 @@ dependencies:
53
52
  - - ">="
54
53
  - !ruby/object:Gem::Version
55
54
  version: 2.0.0
56
- - !ruby/object:Gem::Dependency
57
- name: activesupport
58
- requirement: !ruby/object:Gem::Requirement
59
- requirements:
60
- - - ">="
61
- - !ruby/object:Gem::Version
62
- version: 3.0.0
63
- type: :development
64
- prerelease: false
65
- version_requirements: !ruby/object:Gem::Requirement
66
- requirements:
67
- - - ">="
68
- - !ruby/object:Gem::Version
69
- version: 3.0.0
70
- - !ruby/object:Gem::Dependency
71
- name: actionpack
72
- requirement: !ruby/object:Gem::Requirement
73
- requirements:
74
- - - ">="
75
- - !ruby/object:Gem::Version
76
- version: 3.0.0
77
- type: :development
78
- prerelease: false
79
- version_requirements: !ruby/object:Gem::Requirement
80
- requirements:
81
- - - ">="
82
- - !ruby/object:Gem::Version
83
- version: 3.0.0
84
55
  - !ruby/object:Gem::Dependency
85
56
  name: rubocop
86
57
  requirement: !ruby/object:Gem::Requirement
@@ -95,10 +66,9 @@ dependencies:
95
66
  - - ">="
96
67
  - !ruby/object:Gem::Version
97
68
  version: '0.28'
98
- description: Allows you to sort large datasets over many pages, without losing state.
69
+ description: Data sorting library, used by other libs to construct queries and more
99
70
  email:
100
71
  - rufuspost@gmail.com
101
- - daniel.leavitt@gmail.com
102
72
  executables: []
103
73
  extensions: []
104
74
  extra_rdoc_files: []
@@ -112,25 +82,14 @@ files:
112
82
  - LICENSE
113
83
  - README.md
114
84
  - Rakefile
115
- - gemfiles/active_record_40.gemfile
116
- - gemfiles/active_record_40.gemfile.lock
117
- - gemfiles/mongoid_30.gemfile
118
- - gemfiles/mongoid_30.gemfile.lock
119
85
  - lib/sorted.rb
120
- - lib/sorted/orms/active_record.rb
121
- - lib/sorted/orms/mongoid.rb
122
- - lib/sorted/parser.rb
123
- - lib/sorted/railtie.rb
124
- - lib/sorted/toggler.rb
125
86
  - lib/sorted/version.rb
126
- - lib/sorted/view_helpers/action_view.rb
127
87
  - sorted.gemspec
128
- - spec/sorted/orms/active_record_spec.rb
129
- - spec/sorted/orms/mongoid_spec.rb
130
- - spec/sorted/parser_spec.rb
131
- - spec/sorted/toggler_spec.rb
132
- - spec/sorted/view_helpers/action_view_spec.rb
88
+ - spec/json_query_spec.rb
89
+ - spec/set_spec.rb
133
90
  - spec/spec_helper.rb
91
+ - spec/sql_query_spec.rb
92
+ - spec/uri_query_spec.rb
134
93
  homepage: http://rubygems.org/gems/sorted
135
94
  licenses:
136
95
  - MIT