seek 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,32 @@
1
+ [![Build Status](https://travis-ci.org/bukowskis/seek.png)](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
+ ```
@@ -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
@@ -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
@@ -0,0 +1,13 @@
1
+ class Seek
2
+ module Tools
3
+
4
+ def self.symbolize_keys(hash)
5
+ result = hash.dup
6
+ result.keys.each do |key|
7
+ result[(key.to_sym rescue key) || key] = result.delete(key)
8
+ end
9
+ result
10
+ end
11
+
12
+ end
13
+ end
@@ -0,0 +1,9 @@
1
+ class Seek
2
+ module VERSION
3
+ MAJOR = 0
4
+ MINOR = 0
5
+ TINY = 1
6
+
7
+ STRING = [MAJOR, MINOR, TINY].join('.')
8
+ end
9
+ end
@@ -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
@@ -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: []