muster 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,126 @@
1
+ require 'spec_helper'
2
+
3
+ describe Muster::Strategies::FilterExpression do
4
+ let(:options) { {} }
5
+ subject { Muster::Strategies::FilterExpression.new(options) }
6
+
7
+ describe '#parse' do
8
+
9
+ context 'by default' do
10
+ it 'returns empty hash for empty query string' do
11
+ subject.parse('').should == {}
12
+ end
13
+
14
+ it 'returns hash of all key/value pairs' do
15
+ subject.parse('where=id:1&filter=name:foop').should == { 'where' => {'id' => '1'}, 'filter' => {'name' => 'foop'} }
16
+ end
17
+
18
+ it 'hash supports indifferent key access' do
19
+ hash = subject.parse('where=id:1')
20
+ hash[:where][:id].should eq '1'
21
+ hash['where']['id'].should eq '1'
22
+ end
23
+
24
+ it 'combines multiple expressions into an array' do
25
+ subject.parse('where=id:1&where=id:2').should == { 'where' => {'id' => ['1', '2']} }
26
+ end
27
+
28
+ it 'support for multiple values using |' do
29
+ subject.parse('where=id:1|2&where=id:3').should == { 'where' => {'id' => ['1', '2', '3']} }
30
+ end
31
+
32
+ it 'support for multiple expressions using ,' do
33
+ subject.parse('where=id:1,id:2,id:3').should == { 'where' => {'id' => ['1', '2', '3']} }
34
+ end
35
+
36
+ it 'discards non unique values' do
37
+ subject.parse('where=id:1&where=id:2&where=id:1').should == { 'where' => {'id' => ['1', '2']} }
38
+ end
39
+ end
40
+
41
+ context 'with :value_separator option' do
42
+ context 'as regex' do
43
+ before do
44
+ options[:expression_separator] = '|'
45
+ options[:value_separator] = /,\s*/
46
+ end
47
+
48
+ it 'converts comma separated value into Array' do
49
+ subject.parse('where=id:1,2').should == { 'where' => {'id' => ['1', '2']} }
50
+ end
51
+
52
+ it 'ignores spaces after commas' do
53
+ subject.parse('where=id:1,+2,%20 3').should == { 'where' => {'id' => ['1', '2', '3']} }
54
+ end
55
+ end
56
+
57
+ context 'as string' do
58
+ before do
59
+ options[:expression_separator] = '|'
60
+ options[:value_separator] = ','
61
+ end
62
+
63
+ it 'converts comma separated value into Array' do
64
+ subject.parse('where=id:1,2,3').should == { 'where' => {'id' => ['1', '2', '3']} }
65
+ end
66
+ end
67
+ end
68
+
69
+ context 'with :field_separator option' do
70
+ context 'as regex' do
71
+ before { options[:field_separator] = /\s*!\s*/ }
72
+
73
+ it 'splits field from values' do
74
+ subject.parse('where=id!1').should == { 'where' => {'id' => '1'} }
75
+ end
76
+
77
+ it 'ignores spaces after field' do
78
+ subject.parse('where=id ! 1').should == { 'where' => {'id' => '1'} }
79
+ end
80
+ end
81
+
82
+ context 'as string' do
83
+ before { options[:field_separator] = '!' }
84
+
85
+ it 'converts comma separated value into Array' do
86
+ subject.parse('where=id!1').should == { 'where' => {'id' => '1'} }
87
+ end
88
+ end
89
+ end
90
+
91
+ context 'with :fields option' do
92
+ context 'as symbol' do
93
+ before { options[:field] = :where }
94
+
95
+ it 'fields returns expressions for the key specified' do
96
+ subject.parse('where=id:1&filters=id:2').should == { 'where' => {'id' => '1'} }
97
+ end
98
+ end
99
+
100
+ context 'as Array of symbols' do
101
+ before { options[:fields] = [:where, :filter] }
102
+
103
+ it 'fields returns expressions for the keys specified' do
104
+ subject.parse('where=id:1&filter=id:2&attribute=id:3').should == { 'where' => {'id' => '1'}, 'filter' => {'id' => '2'} }
105
+ end
106
+ end
107
+
108
+ context 'as string' do
109
+ before { options[:field] = 'where' }
110
+
111
+ it 'fields returns expressions for the key specified' do
112
+ subject.parse('where=id:1&filter=id:2').should == { 'where' => {'id' => '1'} }
113
+ end
114
+ end
115
+
116
+ context 'as Array of strings' do
117
+ before { options[:fields] = ['where', 'filter'] }
118
+
119
+ it 'fields returns expressions for the keys specified' do
120
+ subject.parse('where=id:1&filter=id:2&attribute=id:3').should == { 'where' => {'id' => '1'}, 'filter' => {'id' => '2'} }
121
+ end
122
+ end
123
+ end
124
+
125
+ end
126
+ end
@@ -0,0 +1,90 @@
1
+ require 'spec_helper'
2
+
3
+ describe Muster::Strategies::Hash do
4
+ let(:options) { {} }
5
+ subject { Muster::Strategies::Hash.new(options) }
6
+
7
+ describe '#parse' do
8
+
9
+ context 'by default' do
10
+ it 'returns empty hash for empty query string' do
11
+ subject.parse('').should == {}
12
+ end
13
+
14
+ it 'returns hash of all key/value pairs' do
15
+ subject.parse('a=1&b=2').should == {'a' => '1', 'b' => '2'}
16
+ end
17
+
18
+ it 'hash supports indifferent key access' do
19
+ hash = subject.parse('a=1')
20
+ hash[:a].should eq '1'
21
+ hash['a'].should eq '1'
22
+ end
23
+
24
+ it 'combines multiple key values into an array' do
25
+ subject.parse('a=1&a=2').should == {'a' => ['1', '2']}
26
+ end
27
+
28
+ it 'discards non unique values' do
29
+ subject.parse('a=1&a=2&a=1').should == {'a' => ['1', '2']}
30
+ end
31
+ end
32
+
33
+ context 'with :value_separator option' do
34
+ context 'as regex' do
35
+ before { options[:value_separator] = /,\s*/ }
36
+
37
+ it 'converts comma separated value into Array' do
38
+ subject.parse('a=1,2&a=3').should == {'a' => ['1', '2', '3']}
39
+ end
40
+
41
+ it 'ignores spaces after commas' do
42
+ subject.parse('a=1,+2,%20 3').should == {'a' => ['1', '2', '3']}
43
+ end
44
+ end
45
+
46
+ context 'as string' do
47
+ before { options[:value_separator] = '|' }
48
+
49
+ it 'converts comma separated value into Array' do
50
+ subject.parse('a=1|2|3').should == {'a' => ['1', '2', '3']}
51
+ end
52
+ end
53
+ end
54
+
55
+ context 'with :fields option' do
56
+ context 'as symbol' do
57
+ before { options[:field] = :a }
58
+
59
+ it 'fields returns values for the key specified' do
60
+ subject.parse('a=1&b=2').should == {'a' => '1'}
61
+ end
62
+ end
63
+
64
+ context 'as Array of symbols' do
65
+ before { options[:fields] = [:a, :b] }
66
+
67
+ it 'fields returns values for the keys specified' do
68
+ subject.parse('a=1&b=2&c=3').should == {'a' => '1', 'b' => '2'}
69
+ end
70
+ end
71
+
72
+ context 'as string' do
73
+ before { options[:field] = 'a' }
74
+
75
+ it 'fields returns values for the key specified' do
76
+ subject.parse('a=1&b=2').should == {'a' => '1'}
77
+ end
78
+ end
79
+
80
+ context 'as Array of strings' do
81
+ before { options[:fields] = ['a', 'b'] }
82
+
83
+ it 'fields returns values for the keys specified' do
84
+ subject.parse('a=1&b=2&c=3').should == {'a' => '1', 'b' => '2'}
85
+ end
86
+ end
87
+ end
88
+
89
+ end
90
+ end
@@ -0,0 +1,74 @@
1
+ require 'spec_helper'
2
+
3
+ describe Muster::Strategies::Pagination do
4
+ let(:options) { {} }
5
+ subject { Muster::Strategies::Pagination.new(options) }
6
+
7
+ describe '#parse' do
8
+ context 'by default' do
9
+ it 'returns default hash for empty query string' do
10
+ subject.parse('').should == {'pagination' => {'page' => 1, 'per_page' => 30}, 'offset' => nil, 'limit' => 30}
11
+ end
12
+
13
+ it 'ensures page is positive integer' do
14
+ subject.parse('page=foop')[:pagination].should == {'page' => 1, 'per_page' => 30}
15
+ end
16
+
17
+ it 'ensures per_page is positive integer' do
18
+ subject.parse('per_page=foop')[:pagination].should == {'page' => 1, 'per_page' => 30}
19
+ end
20
+
21
+ it 'accepts page_size instead of per_page' do
22
+ subject.parse('page_size=10')[:pagination].should == {'page' => 1, 'per_page' => 10}
23
+ end
24
+
25
+ it 'calculates offset from pagination' do
26
+ subject.parse('page=1&per_page=5')[:offset].should eq nil
27
+ subject.parse('page=2&per_page=5')[:offset].should eq 5
28
+ subject.parse('page=3&per_page=5')[:offset].should eq 10
29
+ end
30
+ end
31
+
32
+ context 'with :default_page_size option' do
33
+ before { options[:default_page_size] = 5 }
34
+
35
+ it 'uses default page size instead of 30' do
36
+ subject.parse('')[:limit].should eq 5
37
+ end
38
+ end
39
+
40
+ context 'with :fields option' do
41
+ context 'as symbol' do
42
+ before { options[:field] = :limit }
43
+
44
+ it 'fields returns values for the key specified' do
45
+ subject.parse('per_page=10').should == {'limit' => 10}
46
+ end
47
+ end
48
+
49
+ context 'as Array of symbols' do
50
+ before { options[:fields] = [:limit, :offset] }
51
+
52
+ it 'fields returns values for the keys specified' do
53
+ subject.parse('per_page=10&page=2').should == {'limit' => 10, 'offset' => 10}
54
+ end
55
+ end
56
+
57
+ context 'as string' do
58
+ before { options[:field] = 'limit' }
59
+
60
+ it 'fields returns values for the key specified' do
61
+ subject.parse('per_page=10').should == {'limit' => 10}
62
+ end
63
+ end
64
+
65
+ context 'as Array of strings' do
66
+ before { options[:fields] = ['limit', 'offset'] }
67
+
68
+ it 'fields returns values for the keys specified' do
69
+ subject.parse('per_page=10&page=2').should == {'limit' => 10, 'offset' => 10}
70
+ end
71
+ end
72
+ end
73
+ end
74
+ end
@@ -0,0 +1,94 @@
1
+ require 'spec_helper'
2
+
3
+ describe Muster::Strategies::SortExpression do
4
+ let(:options) { {} }
5
+ subject { Muster::Strategies::SortExpression.new(options) }
6
+
7
+ describe '#parse' do
8
+
9
+ context 'by default' do
10
+ it 'returns empty hash for empty query string' do
11
+ subject.parse('').should == {}
12
+ end
13
+
14
+ it 'returns hash of all key/value pairs' do
15
+ subject.parse('sort=id&order=name').should == { 'sort' => 'id asc', 'order' => 'name asc' }
16
+ end
17
+
18
+ it 'hash supports indifferent key access' do
19
+ hash = subject.parse('sort=name')
20
+ hash[:sort].should eq 'name asc'
21
+ hash['sort'].should eq 'name asc'
22
+ end
23
+
24
+ it 'combines multiple expressions into an array' do
25
+ subject.parse('sort=id&sort=name').should == { 'sort' => ['id asc', 'name asc'] }
26
+ end
27
+
28
+ it 'supports comma separated expressions with directions' do
29
+ subject.parse('sort=id:asc,name:desc').should == { 'sort' => ['id asc', 'name desc'] }
30
+ end
31
+
32
+ it 'supports comma separated expressions without directions' do
33
+ subject.parse('sort=id,name').should == { 'sort' => ['id asc', 'name asc'] }
34
+ end
35
+
36
+ it 'discards non unique values' do
37
+ subject.parse('sort=id&sort=name&sort=id').should == { 'sort' => ['id asc', 'name asc'] }
38
+ end
39
+ end
40
+
41
+ context 'with direction' do
42
+ it 'supports asc' do
43
+ subject.parse('sort=id:asc').should == { 'sort' => 'id asc' }
44
+ end
45
+
46
+ it 'supports desc' do
47
+ subject.parse('sort=id:desc').should == { 'sort' => 'id desc' }
48
+ end
49
+
50
+ it 'supports ascending' do
51
+ subject.parse('sort=id:ascending').should == { 'sort' => 'id asc' }
52
+ end
53
+
54
+ it 'supports desc' do
55
+ subject.parse('sort=id:descending').should == { 'sort' => 'id desc' }
56
+ end
57
+ end
58
+
59
+ context 'with :fields option' do
60
+ context 'as symbol' do
61
+ before { options[:field] = :sort }
62
+
63
+ it 'fields returns expressions for the key specified' do
64
+ subject.parse('sort=id&order=name').should == { 'sort' => 'id asc' }
65
+ end
66
+ end
67
+
68
+ context 'as Array of symbols' do
69
+ before { options[:fields] = [:sort, :order] }
70
+
71
+ it 'fields returns expressions for the keys specified' do
72
+ subject.parse('sort=id&order=name&direction=place').should == { 'sort' => 'id asc', 'order' => 'name asc' }
73
+ end
74
+ end
75
+
76
+ context 'as string' do
77
+ before { options[:field] = 'sort' }
78
+
79
+ it 'fields returns expressions for the key specified' do
80
+ subject.parse('sort=id&order=name').should == { 'sort' => 'id asc' }
81
+ end
82
+ end
83
+
84
+ context 'as Array of strings' do
85
+ before { options[:fields] = ['sort', 'order'] }
86
+
87
+ it 'fields returns expressions for the keys specified' do
88
+ subject.parse('sort=id&order=name&direction=place').should == { 'sort' => 'id asc', 'order' => 'name asc' }
89
+ end
90
+ end
91
+ end
92
+
93
+ end
94
+ end
@@ -0,0 +1,8 @@
1
+ require 'rack/mock'
2
+ require 'muster'
3
+
4
+ RSpec.configure do |config|
5
+ config.treat_symbols_as_metadata_keys_with_true_values = true
6
+ config.run_all_when_everything_filtered = true
7
+ config.filter_run :focus
8
+ end
metadata ADDED
@@ -0,0 +1,134 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: muster
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Christopher H. Laco
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2012-06-25 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: activesupport
16
+ requirement: &70300796875420 !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ~>
20
+ - !ruby/object:Gem::Version
21
+ version: '3.0'
22
+ type: :runtime
23
+ prerelease: false
24
+ version_requirements: *70300796875420
25
+ - !ruby/object:Gem::Dependency
26
+ name: rack
27
+ requirement: &70300796873700 !ruby/object:Gem::Requirement
28
+ none: false
29
+ requirements:
30
+ - - ~>
31
+ - !ruby/object:Gem::Version
32
+ version: '1.4'
33
+ type: :runtime
34
+ prerelease: false
35
+ version_requirements: *70300796873700
36
+ - !ruby/object:Gem::Dependency
37
+ name: rspec
38
+ requirement: &70300796873220 !ruby/object:Gem::Requirement
39
+ none: false
40
+ requirements:
41
+ - - ~>
42
+ - !ruby/object:Gem::Version
43
+ version: 2.10.0
44
+ type: :development
45
+ prerelease: false
46
+ version_requirements: *70300796873220
47
+ - !ruby/object:Gem::Dependency
48
+ name: redcarpet
49
+ requirement: &70300796872700 !ruby/object:Gem::Requirement
50
+ none: false
51
+ requirements:
52
+ - - ~>
53
+ - !ruby/object:Gem::Version
54
+ version: '2.1'
55
+ type: :development
56
+ prerelease: false
57
+ version_requirements: *70300796872700
58
+ - !ruby/object:Gem::Dependency
59
+ name: yard
60
+ requirement: &70300796872220 !ruby/object:Gem::Requirement
61
+ none: false
62
+ requirements:
63
+ - - ~>
64
+ - !ruby/object:Gem::Version
65
+ version: 0.8.2
66
+ type: :development
67
+ prerelease: false
68
+ version_requirements: *70300796872220
69
+ description: Muster is a gem that turns query string options in varying formats into
70
+ data structures suitable for use in AR scopes and queryies.
71
+ email:
72
+ - claco@chrislaco.com
73
+ executables: []
74
+ extensions: []
75
+ extra_rdoc_files: []
76
+ files:
77
+ - .gitignore
78
+ - .rspec
79
+ - .yardopts
80
+ - Gemfile
81
+ - LICENSE
82
+ - README.md
83
+ - Rakefile
84
+ - lib/muster.rb
85
+ - lib/muster/rack.rb
86
+ - lib/muster/strategies.rb
87
+ - lib/muster/strategies/active_record.rb
88
+ - lib/muster/strategies/filter_expression.rb
89
+ - lib/muster/strategies/hash.rb
90
+ - lib/muster/strategies/pagination.rb
91
+ - lib/muster/strategies/rack.rb
92
+ - lib/muster/strategies/sort_expression.rb
93
+ - lib/muster/version.rb
94
+ - muster.gemspec
95
+ - spec/muster/rack_spec.rb
96
+ - spec/muster/strategies/active_record_spec.rb
97
+ - spec/muster/strategies/filter_expression_spec.rb
98
+ - spec/muster/strategies/hash_spec.rb
99
+ - spec/muster/strategies/pagination_spec.rb
100
+ - spec/muster/strategies/sort_expression_spec.rb
101
+ - spec/spec_helper.rb
102
+ homepage: https://github.com/claco/muster
103
+ licenses: []
104
+ post_install_message:
105
+ rdoc_options: []
106
+ require_paths:
107
+ - lib
108
+ required_ruby_version: !ruby/object:Gem::Requirement
109
+ none: false
110
+ requirements:
111
+ - - ! '>='
112
+ - !ruby/object:Gem::Version
113
+ version: '0'
114
+ required_rubygems_version: !ruby/object:Gem::Requirement
115
+ none: false
116
+ requirements:
117
+ - - ! '>='
118
+ - !ruby/object:Gem::Version
119
+ version: '0'
120
+ requirements: []
121
+ rubyforge_project:
122
+ rubygems_version: 1.8.16
123
+ signing_key:
124
+ specification_version: 3
125
+ summary: Muster various query string options into AR query compatable options.
126
+ test_files:
127
+ - spec/muster/rack_spec.rb
128
+ - spec/muster/strategies/active_record_spec.rb
129
+ - spec/muster/strategies/filter_expression_spec.rb
130
+ - spec/muster/strategies/hash_spec.rb
131
+ - spec/muster/strategies/pagination_spec.rb
132
+ - spec/muster/strategies/sort_expression_spec.rb
133
+ - spec/spec_helper.rb
134
+ has_rdoc: