sorted 1.1.1 → 2.0.0

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: 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