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.
@@ -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: []