seek 0.0.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.
- data/README.md +32 -0
- data/lib/seek.rb +36 -0
- data/lib/seek/configuration.rb +40 -0
- data/lib/seek/pagination.rb +25 -0
- data/lib/seek/sorting.rb +57 -0
- data/lib/seek/tools.rb +13 -0
- data/lib/seek/version.rb +9 -0
- data/spec/lib/seek/tools_spec.rb +14 -0
- data/spec/lib/seek_spec.rb +116 -0
- data/spec/spec_helper.rb +1 -0
- metadata +122 -0
data/README.md
ADDED
@@ -0,0 +1,32 @@
|
|
1
|
+
[](https://travis-ci.org/bukowskis/seek)
|
2
|
+
|
3
|
+
# Seek
|
4
|
+
|
5
|
+
Sanitizes pagination and sorting options in a reusable and serializable way.
|
6
|
+
|
7
|
+
# Installation
|
8
|
+
|
9
|
+
```ruby
|
10
|
+
gem install seek
|
11
|
+
```
|
12
|
+
|
13
|
+
# Examples
|
14
|
+
|
15
|
+
```ruby
|
16
|
+
params = { page: '4', sort_order: 'desc', per_page: '1000' }
|
17
|
+
|
18
|
+
seek = Seek.new params,
|
19
|
+
valid_sort_bys: %w{ first_name, last_name, age },
|
20
|
+
max_per_page: 50,
|
21
|
+
default_sort_by: :age,
|
22
|
+
default_sort_order: :asc
|
23
|
+
|
24
|
+
seek.page #=> 4
|
25
|
+
seek.per_page #=> 50
|
26
|
+
seek.sort_by #=> 'age'
|
27
|
+
seek.sort_order #=> 'desc
|
28
|
+
seek.order #=> 'age desc'
|
29
|
+
|
30
|
+
seek.to_hash
|
31
|
+
#=> Returns a Hash with all the parameters listed above.
|
32
|
+
```
|
data/lib/seek.rb
ADDED
@@ -0,0 +1,36 @@
|
|
1
|
+
require 'seek/configuration'
|
2
|
+
require 'seek/pagination'
|
3
|
+
require 'seek/sorting'
|
4
|
+
require 'seek/tools'
|
5
|
+
require 'seek/version'
|
6
|
+
|
7
|
+
class Seek
|
8
|
+
include Pagination
|
9
|
+
include Sorting
|
10
|
+
|
11
|
+
attr_reader :options
|
12
|
+
|
13
|
+
def initialize(params = {}, options = {})
|
14
|
+
params = params ? Tools.symbolize_keys(params) : {}
|
15
|
+
options = options ? Tools.symbolize_keys(options) : {}
|
16
|
+
self.page = params[:page]
|
17
|
+
self.per_page = params[:per_page]
|
18
|
+
self.sort_by = params[:sort_by]
|
19
|
+
self.sort_order = params[:sort_order]
|
20
|
+
self.max_per_page = options[:max_per_page]
|
21
|
+
self.valid_sort_bys = options[:valid_sort_bys]
|
22
|
+
self.default_sort_by = options[:default_sort_by]
|
23
|
+
self.default_sort_order = options[:default_sort_order]
|
24
|
+
end
|
25
|
+
|
26
|
+
def to_hash
|
27
|
+
{
|
28
|
+
page: page,
|
29
|
+
per_page: per_page,
|
30
|
+
sort_by: sort_by,
|
31
|
+
sort_order: sort_order,
|
32
|
+
order: order,
|
33
|
+
}
|
34
|
+
end
|
35
|
+
|
36
|
+
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
class Seek
|
2
|
+
class Configuration
|
3
|
+
|
4
|
+
attr_writer :default_per_page, :default_max_per_page
|
5
|
+
|
6
|
+
def default_per_page
|
7
|
+
Positify.it {
|
8
|
+
@default_per_page ||= 20
|
9
|
+
}
|
10
|
+
end
|
11
|
+
|
12
|
+
def default_max_per_page
|
13
|
+
Positify.it {
|
14
|
+
@default_max_per_page ||= 100
|
15
|
+
}
|
16
|
+
end
|
17
|
+
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
class Seek
|
22
|
+
|
23
|
+
# Public: Returns the the configuration instance.
|
24
|
+
#
|
25
|
+
def self.config
|
26
|
+
@config ||= Configuration.new
|
27
|
+
end
|
28
|
+
|
29
|
+
# Public: Yields the configuration instance.
|
30
|
+
#
|
31
|
+
def self.configure(&block)
|
32
|
+
yield config
|
33
|
+
end
|
34
|
+
|
35
|
+
# Public: Reset the configuration (useful for testing)
|
36
|
+
#
|
37
|
+
def self.reset!
|
38
|
+
@config = nil
|
39
|
+
end
|
40
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
require 'positify'
|
2
|
+
|
3
|
+
class Seek
|
4
|
+
module Pagination
|
5
|
+
|
6
|
+
attr_writer :page, :per_page, :max_per_page
|
7
|
+
|
8
|
+
def page
|
9
|
+
Positify.it @page
|
10
|
+
end
|
11
|
+
|
12
|
+
def per_page
|
13
|
+
Positify.it @per_page, max: max_per_page
|
14
|
+
end
|
15
|
+
|
16
|
+
def max_per_page
|
17
|
+
if @max_per_page.to_i > 0
|
18
|
+
@max_per_page.to_i
|
19
|
+
else
|
20
|
+
self.class.config.default_max_per_page
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
end
|
25
|
+
end
|
data/lib/seek/sorting.rb
ADDED
@@ -0,0 +1,57 @@
|
|
1
|
+
class Seek
|
2
|
+
module Sorting
|
3
|
+
|
4
|
+
attr_writer :sort_by, :sort_order, :valid_sort_bys, :default_sort_by, :default_sort_order
|
5
|
+
|
6
|
+
# Returns true if sort_by and sort_order are present.
|
7
|
+
#
|
8
|
+
def sortable?
|
9
|
+
!!order
|
10
|
+
end
|
11
|
+
|
12
|
+
# Returns a String or nil.
|
13
|
+
#
|
14
|
+
def sort_by
|
15
|
+
result = @sort_by.to_s.downcase
|
16
|
+
return result if !result.empty? && (valid_sort_bys.empty? || valid_sort_bys.include?(result))
|
17
|
+
default_sort_by
|
18
|
+
end
|
19
|
+
|
20
|
+
def sort_order
|
21
|
+
result = @sort_order.to_s.downcase
|
22
|
+
valid_sort_orders.include?(result) ? result : valid_sort_orders.first
|
23
|
+
end
|
24
|
+
|
25
|
+
# Useful for queries that require the format "first_name desc" (such as SQL or lucene)
|
26
|
+
#
|
27
|
+
# Returns a String or nil
|
28
|
+
#
|
29
|
+
def order
|
30
|
+
return if sort_by.to_s.empty?
|
31
|
+
[sort_by, sort_order].join(' ')
|
32
|
+
end
|
33
|
+
|
34
|
+
def valid_sort_bys
|
35
|
+
Array(@valid_sort_bys).map(&:to_s).map(&:downcase)
|
36
|
+
end
|
37
|
+
|
38
|
+
# Returns a String or nil.
|
39
|
+
#
|
40
|
+
def default_sort_by
|
41
|
+
result = @default_sort_by.to_s.downcase
|
42
|
+
valid_sort_bys.include?(result) ? result : valid_sort_bys.first
|
43
|
+
end
|
44
|
+
|
45
|
+
def default_sort_order
|
46
|
+
result = @default_sort_order.to_s.downcase
|
47
|
+
valid_sort_orders.include?(result) ? result : valid_sort_orders.first
|
48
|
+
end
|
49
|
+
|
50
|
+
private
|
51
|
+
|
52
|
+
def valid_sort_orders
|
53
|
+
%w{ asc desc }
|
54
|
+
end
|
55
|
+
|
56
|
+
end
|
57
|
+
end
|
data/lib/seek/tools.rb
ADDED
data/lib/seek/version.rb
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Seek::Tools do
|
4
|
+
|
5
|
+
let(:original) { { 'one' => 1, two: 2 } }
|
6
|
+
|
7
|
+
describe '.symbolize_keys' do
|
8
|
+
it 'symbolizes String keys in a hash' do
|
9
|
+
Seek::Tools.symbolize_keys(original).should == { one: 1, two: 2 }
|
10
|
+
original.should == { 'one' => 1, two: 2 }
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
end
|
@@ -0,0 +1,116 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Seek do
|
4
|
+
|
5
|
+
let(:params) { { page: 4, per_page: 20, 'sort_by' => :first_name, sort_order: 'DESC' } }
|
6
|
+
let(:options) { { 'max_per_page' => 30, valid_sort_bys: %w{ age first_name last_name } } }
|
7
|
+
|
8
|
+
let(:seek) { Seek.new params, options }
|
9
|
+
|
10
|
+
context 'pagination' do
|
11
|
+
describe 'page' do
|
12
|
+
it 'comes from the params' do
|
13
|
+
seek.page.should == 4
|
14
|
+
end
|
15
|
+
|
16
|
+
it 'is has a positive attitude' do
|
17
|
+
seek = Seek.new params.merge page: 'what?'
|
18
|
+
seek.page.should == 1
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
describe '#per_page' do
|
23
|
+
it 'comes from the params' do
|
24
|
+
seek.per_page.should == 20
|
25
|
+
end
|
26
|
+
|
27
|
+
it 'limits the maximum' do
|
28
|
+
seek = Seek.new params, max_per_page: 15
|
29
|
+
seek.per_page.should == 15
|
30
|
+
end
|
31
|
+
|
32
|
+
it 'does not become negative on weird values' do
|
33
|
+
seek = Seek.new params.merge(per_page: 'what?')
|
34
|
+
seek.per_page.should == 1
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
describe '#max_per_page' do
|
39
|
+
it 'defaults to the global configuration' do
|
40
|
+
Seek.new.max_per_page.should == 100
|
41
|
+
end
|
42
|
+
|
43
|
+
it 'prefers the options' do
|
44
|
+
seek.max_per_page.should == 30
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
context 'sorting' do
|
50
|
+
describe '#sort_by' do
|
51
|
+
it 'comes from the params and is a String' do
|
52
|
+
seek.sort_by.should == 'first_name'
|
53
|
+
end
|
54
|
+
|
55
|
+
it 'defaults to the first valid sort_by' do
|
56
|
+
seek = Seek.new nil, options
|
57
|
+
seek.sort_by.should == 'age'
|
58
|
+
end
|
59
|
+
|
60
|
+
it 'accepts only valid values if the valid ones are specified' do
|
61
|
+
seek = Seek.new({ sort_by: 'size'} , options)
|
62
|
+
seek.sort_by.should == 'age'
|
63
|
+
end
|
64
|
+
|
65
|
+
it 'accepts invalid values if no valid ones are specified' do
|
66
|
+
seek = Seek.new sort_by: 'width'
|
67
|
+
seek.sort_by.should == 'width'
|
68
|
+
end
|
69
|
+
|
70
|
+
it 'is nil if there is no sort_by' do
|
71
|
+
Seek.new.sort_by.should be_nil
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
describe '#sort_order' do
|
76
|
+
it 'comes from the params and is a String' do
|
77
|
+
seek.sort_order.should == 'desc'
|
78
|
+
end
|
79
|
+
|
80
|
+
it 'is ascending if nothing is specified' do
|
81
|
+
Seek.new.sort_order.should == 'asc'
|
82
|
+
end
|
83
|
+
|
84
|
+
it 'is ascending if something invalid is specified' do
|
85
|
+
Seek.new(sort_order: 'vertically').sort_order.should == 'asc'
|
86
|
+
end
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
describe '#order' do
|
91
|
+
it 'is sort_by and sort_order separated by a space' do
|
92
|
+
seek.order.should == 'first_name desc'
|
93
|
+
end
|
94
|
+
|
95
|
+
it 'is nil if there is no sort_by' do
|
96
|
+
Seek.new.order.should be_nil
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
describe '#sortable?' do
|
101
|
+
it 'is true if there is sort_by and sort_order' do
|
102
|
+
seek.should be_sortable
|
103
|
+
end
|
104
|
+
|
105
|
+
it 'is nil if there is no sort_by' do
|
106
|
+
Seek.new.should_not be_sortable
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
110
|
+
describe '#to_hash' do
|
111
|
+
it 'contains all params' do
|
112
|
+
seek.to_hash.should == { page: 4, per_page: 20, sort_by: 'first_name', sort_order: 'desc', order: 'first_name desc' }
|
113
|
+
end
|
114
|
+
end
|
115
|
+
|
116
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require 'seek'
|
metadata
ADDED
@@ -0,0 +1,122 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: seek
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- bukowskis
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2013-04-24 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: positify
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
18
|
+
requirements:
|
19
|
+
- - ~>
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: 0.0.1
|
22
|
+
type: :runtime
|
23
|
+
prerelease: false
|
24
|
+
version_requirements: !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
26
|
+
requirements:
|
27
|
+
- - ~>
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
version: 0.0.1
|
30
|
+
- !ruby/object:Gem::Dependency
|
31
|
+
name: rspec
|
32
|
+
requirement: !ruby/object:Gem::Requirement
|
33
|
+
none: false
|
34
|
+
requirements:
|
35
|
+
- - ! '>='
|
36
|
+
- !ruby/object:Gem::Version
|
37
|
+
version: '0'
|
38
|
+
type: :development
|
39
|
+
prerelease: false
|
40
|
+
version_requirements: !ruby/object:Gem::Requirement
|
41
|
+
none: false
|
42
|
+
requirements:
|
43
|
+
- - ! '>='
|
44
|
+
- !ruby/object:Gem::Version
|
45
|
+
version: '0'
|
46
|
+
- !ruby/object:Gem::Dependency
|
47
|
+
name: guard-rspec
|
48
|
+
requirement: !ruby/object:Gem::Requirement
|
49
|
+
none: false
|
50
|
+
requirements:
|
51
|
+
- - ! '>='
|
52
|
+
- !ruby/object:Gem::Version
|
53
|
+
version: '0'
|
54
|
+
type: :development
|
55
|
+
prerelease: false
|
56
|
+
version_requirements: !ruby/object:Gem::Requirement
|
57
|
+
none: false
|
58
|
+
requirements:
|
59
|
+
- - ! '>='
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
62
|
+
- !ruby/object:Gem::Dependency
|
63
|
+
name: rb-fsevent
|
64
|
+
requirement: !ruby/object:Gem::Requirement
|
65
|
+
none: false
|
66
|
+
requirements:
|
67
|
+
- - ! '>='
|
68
|
+
- !ruby/object:Gem::Version
|
69
|
+
version: '0'
|
70
|
+
type: :development
|
71
|
+
prerelease: false
|
72
|
+
version_requirements: !ruby/object:Gem::Requirement
|
73
|
+
none: false
|
74
|
+
requirements:
|
75
|
+
- - ! '>='
|
76
|
+
- !ruby/object:Gem::Version
|
77
|
+
version: '0'
|
78
|
+
description: A sanitizer for pagination and sorting options. It is supposed to help
|
79
|
+
unify passing search options via cross-application APIs.
|
80
|
+
email:
|
81
|
+
executables: []
|
82
|
+
extensions: []
|
83
|
+
extra_rdoc_files: []
|
84
|
+
files:
|
85
|
+
- lib/seek/configuration.rb
|
86
|
+
- lib/seek/pagination.rb
|
87
|
+
- lib/seek/sorting.rb
|
88
|
+
- lib/seek/tools.rb
|
89
|
+
- lib/seek/version.rb
|
90
|
+
- lib/seek.rb
|
91
|
+
- spec/lib/seek/tools_spec.rb
|
92
|
+
- spec/lib/seek_spec.rb
|
93
|
+
- spec/spec_helper.rb
|
94
|
+
- README.md
|
95
|
+
homepage: https://github.com/bukowskis/seek
|
96
|
+
licenses:
|
97
|
+
- MIT
|
98
|
+
post_install_message:
|
99
|
+
rdoc_options:
|
100
|
+
- --encoding
|
101
|
+
- UTF-8
|
102
|
+
require_paths:
|
103
|
+
- lib
|
104
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
105
|
+
none: false
|
106
|
+
requirements:
|
107
|
+
- - ! '>='
|
108
|
+
- !ruby/object:Gem::Version
|
109
|
+
version: '0'
|
110
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
111
|
+
none: false
|
112
|
+
requirements:
|
113
|
+
- - ! '>='
|
114
|
+
- !ruby/object:Gem::Version
|
115
|
+
version: '0'
|
116
|
+
requirements: []
|
117
|
+
rubyforge_project:
|
118
|
+
rubygems_version: 1.8.23
|
119
|
+
signing_key:
|
120
|
+
specification_version: 3
|
121
|
+
summary: A sanitizer for pagination and sorting options.
|
122
|
+
test_files: []
|