sorted 2.0.3 → 2.1.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 47e5b8db73e27b5130e62753c00ec308e6c6886d
4
- data.tar.gz: 4c8abeb0e9399f5d2558d202597199ed8d236bea
3
+ metadata.gz: b9b0ab137af7f8964eb8b6d8bee93e782fae7dce
4
+ data.tar.gz: 373d2c35b43cdddecb7d0eb1e0b60b6cd2ebcbb0
5
5
  SHA512:
6
- metadata.gz: a1974de003bae9e48872f9652f209c5c374c0432d29635f1e169ef52ff3a0e626adff2bd2a8fa23ae583fe49cb98534e834ba82f36b1c285c456179f614ecb93
7
- data.tar.gz: f9d8cba70836197f131ce03c3c36c35318284842d8a40aeb2ae3b4815d411c8e142949900257541b986be0c47f6ff97a06d3c0d5de7709aff3630ad15464f394
6
+ metadata.gz: 53e9a1614a66a52f42ec5b219c25927978c410ae43ce4eb12cd0facb1be64c2e64cb2dba457909043f4f12320a04e3313336e60d1be7be5d57e817caf5656c4d
7
+ data.tar.gz: 57eaad9eb987b624cebe8f320a786e541450d4f24424a31f41153f233d0e12f55f38c8d8eb73edb045117dc7faccb2f4192f64077857cc1b8eb62f2589377c8d
data/.gitignore CHANGED
@@ -20,5 +20,6 @@ pkg
20
20
  .rvmrc
21
21
  Gemfile.lock
22
22
  .bundle
23
+ doc/*
23
24
 
24
25
  ## PROJECT::SPECIFIC
@@ -1,7 +1,4 @@
1
1
  inherit_from: .rubocop_todo.yml
2
2
 
3
- Style/Blocks:
4
- Enabled: false
5
-
6
3
  Style/WordArray:
7
4
  MinSize: 2
@@ -1,5 +1,5 @@
1
1
  # This configuration was generated by `rubocop --auto-gen-config`
2
- # on 2015-03-01 13:05:10 +1100 using RuboCop version 0.28.0.
2
+ # on 2015-09-23 09:55:31 +1000 using RuboCop version 0.28.0.
3
3
  # The point is for the user to remove these configuration records
4
4
  # one by one as the offenses are removed from the code base.
5
5
  # Note that changes in the inspected code, or installation of new
@@ -12,9 +12,9 @@ Metrics/AbcSize:
12
12
  # Offense count: 1
13
13
  # Configuration parameters: CountComments.
14
14
  Metrics/ClassLength:
15
- Max: 103
15
+ Max: 130
16
16
 
17
- # Offense count: 12
17
+ # Offense count: 18
18
18
  # Configuration parameters: AllowURI, URISchemes.
19
19
  Metrics/LineLength:
20
20
  Max: 131
@@ -24,7 +24,7 @@ Metrics/LineLength:
24
24
  Metrics/MethodLength:
25
25
  Max: 13
26
26
 
27
- # Offense count: 8
27
+ # Offense count: 9
28
28
  Style/Documentation:
29
29
  Enabled: false
30
30
 
@@ -37,3 +37,7 @@ Style/For:
37
37
  # Configuration parameters: MaxLineLength.
38
38
  Style/IfUnlessModifier:
39
39
  Enabled: false
40
+
41
+ # Offense count: 3
42
+ Style/OpMethod:
43
+ Enabled: false
data/README.md CHANGED
@@ -10,6 +10,8 @@ attributes in weird and wonderful ways.
10
10
  The secret sauce is the `Sorted::Set` object, in this example we 'toggle' email:
11
11
 
12
12
  ```ruby
13
+ require 'sorted/set'
14
+
13
15
  a = Sorted::Set.new([['email', 'asc'], ['name', 'asc']])
14
16
  b = Sorted::Set.new([['email', 'asc'], ['phone', 'asc']])
15
17
 
@@ -26,6 +28,8 @@ when you sort by various columns, `Sorted::Set` pretty much just does that.
26
28
  Parsers return a `Sorted::Set` that can then be used by an encoder:
27
29
 
28
30
  ```ruby
31
+ require 'sorted/uri_query'
32
+
29
33
  set = Sorted::URIQuery.parse('name_asc!email_asc')
30
34
  Sorted::SQLQuery.encode(set) #=> 'name ASC email ASC'
31
35
  ```
@@ -1,274 +1,2 @@
1
1
  module Sorted
2
- class Set
3
- include Enumerable
4
- include Comparable
5
-
6
- def initialize(set = [])
7
- @set = set
8
- end
9
-
10
- def each(&block)
11
- @set.each(&block)
12
- end
13
-
14
- ##
15
- # Gets the keys from the array pairs
16
- #
17
- # set = [["email", "name"], ["desc", "desc"]]
18
- # set.transpose #=> [["email", "name"], ["desc", "desc"]]
19
- # set.transpose.first #=> ["email", "name"]
20
-
21
- def keys
22
- @set.transpose.first || []
23
- end
24
-
25
- ##
26
- # Returns a resulting set with specific keys flipped
27
- #
28
- # a = Sorted::Set.new([['email', 'asc'], ['name', 'asc']])
29
- # b = Sorted::Set.new([['email', 'asc'], ['phone', 'asc']])
30
- # s = a.direction_intersect(b)
31
- # s.to_a #=> [['email', 'desc'], ['phone', 'asc'], ['name', 'asc']]
32
-
33
- def direction_intersect(other)
34
- self.class.new.tap do |memo|
35
- unless other.keys.empty?
36
- a(memo, other)
37
- b(memo, other)
38
- end
39
- c(memo)
40
- d(memo, other)
41
- end
42
- end
43
-
44
- def -(other)
45
- self.class.new.tap do |memo|
46
- each do |a|
47
- b = other.assoc(a.first)
48
- next if b
49
- memo << a
50
- end
51
- end
52
- end
53
-
54
- def +(other)
55
- self.class.new(@set + other.to_a)
56
- end
57
-
58
- def <<(other)
59
- self.class.new(@set << other.to_a)
60
- end
61
-
62
- def select(&block)
63
- self.class.new(@set.select(&block))
64
- end
65
-
66
- def reject(&block)
67
- self.class.new(@set.reject(&block))
68
- end
69
-
70
- def <=>(other)
71
- @set <=> other.to_a
72
- end
73
-
74
- def uniq
75
- self.class.new(@set.uniq)
76
- end
77
-
78
- def assoc(o)
79
- @set.assoc(o)
80
- end
81
-
82
- def at(i)
83
- @set.at(i)
84
- end
85
-
86
- def to_a
87
- @set
88
- end
89
-
90
- def to_hash
91
- @set.inject({}) { |a, e| a.merge(Hash[e[0], e[1]]) }
92
- end
93
-
94
- private
95
-
96
- # If the order of keys match upto the size of the set then flip them
97
- def a(memo, other)
98
- if keys == other.keys.take(keys.size)
99
- keys.each do |order|
100
- if other.keys.include?(order)
101
- memo << [order, flip_direction(other.assoc(order).last)]
102
- end
103
- end
104
- else
105
- keys.each do |order|
106
- if other.keys.include?(order)
107
- memo << other.assoc(order)
108
- end
109
- end
110
- end
111
- end
112
-
113
- # Add items from other that are common and not already added
114
- def b(memo, other)
115
- other.keys.each do |sort|
116
- if keys.include?(sort) && !memo.keys.include?(sort)
117
- memo << other.assoc(sort)
118
- end
119
- end
120
- end
121
-
122
- # Add items not in memo
123
- def c(memo)
124
- each do |order|
125
- unless memo.keys.include?(order[0])
126
- memo << order
127
- end
128
- end
129
- end
130
-
131
- # Add items from other not in memo
132
- def d(memo, other)
133
- other.each do |sort|
134
- unless memo.keys.include?(sort[0])
135
- memo << sort
136
- end
137
- end
138
- end
139
-
140
- def flip_direction(direction)
141
- case direction
142
- when 'asc' then 'desc'
143
- when 'desc'then 'asc'
144
- end
145
- end
146
- end
147
-
148
- module Parse
149
- def split(raw, delim, &block)
150
- return Set.new if raw.nil?
151
- raw.to_s.split(delim).inject(Set.new, &block)
152
- end
153
-
154
- def parse_match(m)
155
- [(m[2].nil? ? m[1] : m[2]), (m[3].nil? ? 'asc' : m[3].downcase)]
156
- end
157
- end
158
-
159
- class URIQuery
160
- extend Parse
161
-
162
- REGEXP = /(([a-z0-9._]+)_([asc|desc]+)|[a-z0-9._]+)/i
163
-
164
- def self.parse(raw)
165
- split(raw, /!/) do |set, part|
166
- m = part.match(REGEXP)
167
- next unless m
168
- set << parse_match(m)
169
- end
170
- end
171
-
172
- def self.encode(set)
173
- set.map { |a| a.join('_') }.join('!')
174
- end
175
- end
176
-
177
- class SQLQuery
178
- extend Parse
179
-
180
- REGEXP = /(([a-z0-9._]+)\s([asc|desc]+)|[a-z0-9._]+)/i
181
-
182
- def self.parse(raw)
183
- split(raw, /,/) do |set, part|
184
- m = part.match(REGEXP)
185
- next unless m
186
- set << parse_match(m)
187
- end
188
- end
189
-
190
- def self.encode(set, quote_proc = ->(f) { f })
191
- set.map { |a| "#{column(a[0], quote_proc)} #{a[1].upcase}" }.join(', ')
192
- end
193
-
194
- def self.column(parts, quote_proc)
195
- parts.split('.').map { |frag| quote_proc.call(frag) }.join('.')
196
- end
197
- private_class_method :column
198
- end
199
-
200
- class JSONQuery
201
- extend Parse
202
-
203
- JSON_TO_SORTED = { 1 => 'asc', -1 => 'desc' }
204
- SORTED_TO_JSON = { 'asc' => 1, 'desc' => -1 }
205
-
206
- def self.parse(raw)
207
- Set.new(raw.map { |key, val| [key, JSON_TO_SORTED[val]] })
208
- end
209
-
210
- def self.encode(set)
211
- set.inject({}) { |a, e| a.merge(Hash[e[0], SORTED_TO_JSON[e[1]]]) }
212
- end
213
- end
214
-
215
- ##
216
- # Parses an Elasticsearch type set of order
217
- #
218
- # Parsing:
219
- #
220
- # params = [{ 'email' => {'order' => 'desc'}}]
221
- # set = Sorted::ElasticsearchQuery.parse(params)
222
- # set.to_a #=> [['email', 'desc']]
223
- #
224
- # Encoding:
225
- #
226
- # Sorted::ParamsQuery.encode(set) #=> [{ 'email' => {'order' => 'desc'}}]
227
- #
228
-
229
- class ElasticsearchQuery
230
- extend Parse
231
-
232
- def self.parse(raw)
233
- Set.new(raw.each_with_object([]) { |hash, a| a << [hash.first.first, hash.first.last['order']] })
234
- end
235
-
236
- def self.encode(set)
237
- set.to_a.each_with_object([]) { |f, a| a << { f.first => { 'order' => f.last } } }
238
- end
239
- end
240
-
241
- ##
242
- # Parses an array of decoded query params
243
- #
244
- # This parser/encoder uses an already decoded array of sort strings parsed by
245
- # a URI library.
246
- #
247
- # Parsing:
248
- #
249
- # params = ['phone_desc', 'name_asc']
250
- # set = Sorted::ParamsQuery.parse(params)
251
- # set.to_a #=> [['phone', 'desc'], ['name', asc']]
252
- #
253
- # Encoding:
254
- #
255
- # Sorted::ParamsQuery.encode(set) #=> ['phone_desc', 'name_asc']
256
-
257
- class ParamsQuery
258
- extend Parse
259
-
260
- REGEXP = /(([a-z0-9._]+)_([asc|desc]+)|[a-z0-9._]+)/i
261
-
262
- def self.parse(params)
263
- params.inject(Set.new) do |set, part|
264
- m = part.match(REGEXP)
265
- next unless m
266
- set << parse_match(m)
267
- end
268
- end
269
-
270
- def self.encode(set)
271
- set.map { |a| a.join('_') }
272
- end
273
- end
274
2
  end
@@ -0,0 +1,27 @@
1
+ require 'sorted/set'
2
+
3
+ module Sorted
4
+ ##
5
+ # Parses an Elasticsearch type set of order
6
+ #
7
+ # Parsing:
8
+ #
9
+ # params = [{ 'email' => {'order' => 'desc'}}]
10
+ # set = Sorted::ElasticsearchQuery.parse(params)
11
+ # set.to_a #=> [['email', 'desc']]
12
+ #
13
+ # Encoding:
14
+ #
15
+ # Sorted::ParamsQuery.encode(set) #=> [{ 'email' => {'order' => 'desc'}}]
16
+ #
17
+
18
+ class ElasticsearchQuery
19
+ def self.parse(raw)
20
+ Set.new(raw.each_with_object([]) { |hash, a| a << [hash.first.first, hash.first.last['order']] })
21
+ end
22
+
23
+ def self.encode(set)
24
+ set.to_a.each_with_object([]) { |f, a| a << { f.first => { 'order' => f.last } } }
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,16 @@
1
+ require 'sorted/set'
2
+
3
+ module Sorted
4
+ class JSONQuery
5
+ JSON_TO_SORTED = { 1 => 'asc', -1 => 'desc' }
6
+ SORTED_TO_JSON = { 'asc' => 1, 'desc' => -1 }
7
+
8
+ def self.parse(raw)
9
+ Set.new(raw.map { |key, val| [key, JSON_TO_SORTED[val]] })
10
+ end
11
+
12
+ def self.encode(set)
13
+ set.inject({}) { |a, e| a.merge(Hash[e[0], SORTED_TO_JSON[e[1]]]) }
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,38 @@
1
+ require 'sorted/set'
2
+ require 'sorted/parse'
3
+
4
+ module Sorted
5
+ ##
6
+ # Parses an array of decoded query params
7
+ #
8
+ # This parser/encoder uses an already decoded array of sort strings parsed by
9
+ # a URI library.
10
+ #
11
+ # Parsing:
12
+ #
13
+ # params = ['phone_desc', 'name_asc']
14
+ # set = Sorted::ParamsQuery.parse(params)
15
+ # set.to_a #=> [['phone', 'desc'], ['name', asc']]
16
+ #
17
+ # Encoding:
18
+ #
19
+ # Sorted::ParamsQuery.encode(set) #=> ['phone_desc', 'name_asc']
20
+
21
+ class ParamsQuery
22
+ extend Parse
23
+
24
+ REGEXP = /(([a-z0-9._]+)_([asc|desc]+)|[a-z0-9._]+)/i
25
+
26
+ def self.parse(params)
27
+ params.inject(Set.new) do |set, part|
28
+ m = part.match(REGEXP)
29
+ next unless m
30
+ set << parse_match(m)
31
+ end
32
+ end
33
+
34
+ def self.encode(set)
35
+ set.map { |a| a.join('_') }
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,14 @@
1
+ require 'sorted/set'
2
+
3
+ module Sorted
4
+ module Parse
5
+ def split(raw, delim, &block)
6
+ return Set.new if raw.nil?
7
+ raw.to_s.split(delim).inject(Set.new, &block)
8
+ end
9
+
10
+ def parse_match(m)
11
+ [(m[2].nil? ? m[1] : m[2]), (m[3].nil? ? 'asc' : m[3].downcase)]
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,238 @@
1
+ module Sorted
2
+ class Set
3
+ include Enumerable
4
+ include Comparable
5
+
6
+ def initialize(ary = [])
7
+ @ary = ary
8
+ end
9
+
10
+ ##
11
+ # Calls the given block once for each element in self, passing that element
12
+ # as a parameter.
13
+ #
14
+ # An Enumerator is returned if no block is given.
15
+
16
+ def each
17
+ return to_enum(:each) unless block_given?
18
+ @ary.each { |item| yield item }
19
+ end
20
+
21
+ ##
22
+ # Returns the keys form the array pairs.
23
+ #
24
+ # set = Sorted::Set.new([["email", "desc"], ["name", "desc"]])
25
+ # set.keys #=> ["email", "name"]
26
+
27
+ def keys
28
+ @ary.transpose.first || []
29
+ end
30
+
31
+ ##
32
+ # Returns a new array containing elements common to the two arrays,
33
+ # excluding any duplicates.
34
+ #
35
+ # Any matching keys at matching indexes with the same order will have the
36
+ # order reversed.
37
+ #
38
+ # a = Sorted::Set.new([['email', 'asc'], ['name', 'asc']])
39
+ # b = Sorted::Set.new([['email', 'asc'], ['phone', 'asc']])
40
+ # s = a.direction_intersect(b)
41
+ # s.to_a #=> [['email', 'desc'], ['phone', 'asc'], ['name', 'asc']]
42
+
43
+ def direction_intersect(other_set)
44
+ self.class.new.tap do |memo|
45
+ unless other_set.keys.empty?
46
+ a(memo, other_set)
47
+ b(memo, other_set)
48
+ end
49
+ c(memo)
50
+ d(memo, other_set)
51
+ end
52
+ end
53
+
54
+ ##
55
+ # Array Difference - Returns a new set that is a copy of the original set,
56
+ # removing any items that also appear in +other_set+. The order is preserved
57
+ # from the original set.
58
+ #
59
+ # set = Sorted::Set.new(['email', 'desc'])
60
+ # other_set = Sorted::Set.new(['phone', 'asc'])
61
+ # set - other_set #=> #<Sorted::Set:0x007fafde1ead80>
62
+
63
+ def -(other_set)
64
+ self.class.new.tap do |memo|
65
+ each do |a|
66
+ b = other_set.assoc(a.first)
67
+ next if b
68
+ memo << a
69
+ end
70
+ end
71
+ end
72
+
73
+ ##
74
+ # Concatenation - Returns a new set built by concatenating the two sets
75
+ # together to produce a third set.
76
+ #
77
+ # set = Sorted::Set.new(['email', 'desc'])
78
+ # other_set = Sorted::Set.new(['phone', 'asc'])
79
+ # set + other_set #=> #<Sorted::Set:0x007fafde1ead80>
80
+
81
+ def +(other_set)
82
+ self.class.new(@ary + other_set.to_a)
83
+ end
84
+
85
+ ##
86
+ # Append - Pushes the given order array on to the end of this set. This
87
+ # expression returns the set itself, so several appends may be chained
88
+ # together.
89
+ #
90
+ # set = Sorted::Set.new(['name', 'asc'])
91
+ # set << ['email', 'desc'] << ['phone', 'asc']
92
+ # set.to_a #=> [['name', 'asc'], ['email', 'desc'], ['phone', 'asc']]
93
+
94
+ def <<(ary)
95
+ @ary << ary
96
+ self
97
+ end
98
+
99
+ ##
100
+ # Returns a new set containing all elements of self for which the given
101
+ # block returns a true value.
102
+ #
103
+ # If no block is given, an Enumerator is returned instead.
104
+
105
+ def select
106
+ return to_enum(:select) unless block_given?
107
+ self.class.new(@ary.select { |item| yield item })
108
+ end
109
+
110
+ ##
111
+ # Returns a new set containing the items in self for which the given block
112
+ # is not true.
113
+ #
114
+ # If no block is given, an Enumerator is returned instead.
115
+
116
+ def reject
117
+ return to_enum(:reject) unless block_given?
118
+ self.class.new(@ary.reject { |item| yield item })
119
+ end
120
+
121
+ ##
122
+ # Comparison - Returns an integer (-1, 0, or +1) if this array is less than,
123
+ # equal to, or greater than +other_set+.
124
+
125
+ def <=>(other_set)
126
+ @ary <=> other_set.to_a
127
+ end
128
+
129
+ ##
130
+ # Returns a new set by removing duplicate values in self.
131
+ #
132
+ # If a block is given, it will use the return value of the block for comparison.
133
+
134
+ def uniq
135
+ return self.class.new(@ary.uniq) unless block_given?
136
+ self.class.new(@ary.uniq { |item| yield item })
137
+ end
138
+
139
+ ##
140
+ # Searches through an array whose elements are also arrays comparing +item+
141
+ # with the first element of each contained array using +item+.==.
142
+ #
143
+ # Returns the first contained array that matches (that is, the first
144
+ # associated array), or nil if no match is found.
145
+
146
+ def assoc(item)
147
+ @ary.assoc(item)
148
+ end
149
+
150
+ ##
151
+ # Returns key, order array pair at index +index+
152
+
153
+ def at(index)
154
+ @ary.at(index)
155
+ end
156
+
157
+ ##
158
+ # Returns the underlying array for the set object.
159
+ #
160
+ # set = Sorted::Set.new(['name', 'asc'])
161
+ # set.to_a #=> [['name', 'asc']]
162
+
163
+ def to_a
164
+ @ary
165
+ end
166
+
167
+ ##
168
+ # Returns the result of interpreting ary as an array of [key, value] pairs.
169
+ #
170
+ # set = Sorted::Set.new([['email', 'asc']])
171
+ # set.to_h #=> { 'email' => 'asc' }
172
+
173
+ def to_h
174
+ @ary.inject({}) { |a, e| a.merge(Hash[e[0], e[1]]) }
175
+ end
176
+
177
+ ##
178
+ # Returns the number of elements in self. May be zero.
179
+
180
+ def length
181
+ @ary.length
182
+ end
183
+ alias_method :size, :length
184
+
185
+ private
186
+
187
+ # If the order of keys match upto the size of the set then flip them
188
+ def a(memo, other)
189
+ if keys == other.keys.take(keys.size)
190
+ keys.each do |order|
191
+ if other.keys.include?(order)
192
+ memo << [order, flip_direction(other.assoc(order).last)]
193
+ end
194
+ end
195
+ else
196
+ keys.each do |order|
197
+ if other.keys.include?(order)
198
+ memo << other.assoc(order)
199
+ end
200
+ end
201
+ end
202
+ end
203
+
204
+ # Add items from other that are common and not already added
205
+ def b(memo, other)
206
+ other.keys.each do |sort|
207
+ if keys.include?(sort) && !memo.keys.include?(sort)
208
+ memo << other.assoc(sort)
209
+ end
210
+ end
211
+ end
212
+
213
+ # Add items not in memo
214
+ def c(memo)
215
+ each do |order|
216
+ unless memo.keys.include?(order[0])
217
+ memo << order
218
+ end
219
+ end
220
+ end
221
+
222
+ # Add items from other not in memo
223
+ def d(memo, other)
224
+ other.each do |sort|
225
+ unless memo.keys.include?(sort[0])
226
+ memo << sort
227
+ end
228
+ end
229
+ end
230
+
231
+ def flip_direction(direction)
232
+ case direction
233
+ when 'asc' then 'desc'
234
+ when 'desc' then 'asc'
235
+ end
236
+ end
237
+ end
238
+ end
@@ -0,0 +1,26 @@
1
+ require 'sorted/set'
2
+
3
+ module Sorted
4
+ class SQLQuery
5
+ extend Parse
6
+
7
+ REGEXP = /(([a-z0-9._]+)\s([asc|desc]+)|[a-z0-9._]+)/i
8
+
9
+ def self.parse(raw)
10
+ split(raw, /,/) do |set, part|
11
+ m = part.match(REGEXP)
12
+ next unless m
13
+ set << parse_match(m)
14
+ end
15
+ end
16
+
17
+ def self.encode(set, quote_proc = ->(f) { f })
18
+ set.map { |a| "#{column(a[0], quote_proc)} #{a[1].upcase}" }.join(', ')
19
+ end
20
+
21
+ def self.column(parts, quote_proc)
22
+ parts.split('.').map { |frag| quote_proc.call(frag) }.join('.')
23
+ end
24
+ private_class_method :column
25
+ end
26
+ end
@@ -0,0 +1,22 @@
1
+ require 'sorted/set'
2
+ require 'sorted/parse'
3
+
4
+ module Sorted
5
+ class URIQuery
6
+ extend Parse
7
+
8
+ REGEXP = /(([a-z0-9._]+)_([asc|desc]+)|[a-z0-9._]+)/i
9
+
10
+ def self.parse(raw)
11
+ split(raw, /!/) do |set, part|
12
+ m = part.match(REGEXP)
13
+ next unless m
14
+ set << parse_match(m)
15
+ end
16
+ end
17
+
18
+ def self.encode(set)
19
+ set.map { |a| a.join('_') }.join('!')
20
+ end
21
+ end
22
+ end
@@ -1,3 +1,3 @@
1
1
  module Sorted
2
- VERSION = '2.0.3'
2
+ VERSION = '2.1.1'
3
3
  end
@@ -21,6 +21,6 @@ Gem::Specification.new do |s|
21
21
  s.add_development_dependency 'rubocop', '>= 0.28'
22
22
 
23
23
  s.files = `git ls-files`.split("\n")
24
- s.executables = `git ls-files`.split("\n").map { |f| f =~ /^bin\/(.*)/ ? Regexp.last_match[1] : nil }.compact
24
+ s.executables = `git ls-files`.split("\n").map { |f| f =~ %r{/^bin\/(.*)/} ? Regexp.last_match[1] : nil }.compact
25
25
  s.require_path = 'lib'
26
26
  end
@@ -1,5 +1,7 @@
1
1
  require 'spec_helper'
2
2
 
3
+ require 'sorted/elasticsearch_query'
4
+
3
5
  describe Sorted::ElasticsearchQuery, 'decode' do
4
6
  it 'should decode elasticsearch order hash to into set' do
5
7
  json = [{ 'email' => { 'order' => 'desc' } }, { 'phone' => { 'order' => 'asc' } }, { 'name' => { 'order' => 'desc' } }]
@@ -1,5 +1,7 @@
1
1
  require 'spec_helper'
2
2
 
3
+ require 'sorted/json_query'
4
+
3
5
  describe Sorted::JSONQuery, 'decode' do
4
6
  it 'should return a nice array from the order sql' do
5
7
  json = { 'email' => 1, 'phone' => 1, 'name' => -1 }
@@ -1,5 +1,7 @@
1
1
  require 'spec_helper'
2
2
 
3
+ require 'sorted/params_query'
4
+
3
5
  describe Sorted::ParamsQuery, 'decode' do
4
6
  it 'should return a set from an array of params' do
5
7
  params = %w(email_asc phone_asc name_desc)
@@ -1,5 +1,7 @@
1
1
  require 'spec_helper'
2
2
 
3
+ require 'sorted/set'
4
+
3
5
  describe Sorted::Set do
4
6
  it 'should bring phone to first order importance but not toggle ascendance' do
5
7
  orders = Sorted::Set.new([['email', 'asc'], ['phone', 'asc']])
@@ -69,7 +71,7 @@ describe Sorted::Set do
69
71
  set = Sorted::Set.new([['email', 'asc']])
70
72
  result = { 'email' => 'asc' }
71
73
 
72
- expect(set.to_hash).to eq(result)
74
+ expect(set.to_h).to eq(result)
73
75
  end
74
76
 
75
77
  it 'should return set when selecting items' do
@@ -83,4 +85,18 @@ describe Sorted::Set do
83
85
 
84
86
  expect(set.reject { true }.class).to eq(Sorted::Set)
85
87
  end
88
+
89
+ it 'should append value to set' do
90
+ set = Sorted::Set.new([['email', 'asc']])
91
+ set << ['name', 'asc'] << ['phone', 'asc']
92
+
93
+ expect(set.length).to eq(3)
94
+ expect(set.size).to eq(3)
95
+ end
96
+
97
+ it 'should return a unique set' do
98
+ set = Sorted::Set.new([['email', 'asc'], ['email', 'asc']])
99
+
100
+ expect(set.uniq.to_a).to eq([['email', 'asc']])
101
+ end
86
102
  end
@@ -2,4 +2,3 @@ $LOAD_PATH.unshift(File.dirname(__FILE__))
2
2
  $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
3
3
 
4
4
  require 'rspec'
5
- require 'sorted'
@@ -1,5 +1,7 @@
1
1
  require 'spec_helper'
2
2
 
3
+ require 'sorted/sql_query'
4
+
3
5
  describe Sorted::SQLQuery, 'decode' do
4
6
  it 'should return a nice array from the order sql' do
5
7
  sql = 'email ASC, phone ASC, name DESC'
@@ -41,9 +43,7 @@ describe Sorted::SQLQuery, 'encode' do
41
43
  end
42
44
  end
43
45
 
44
- let(:quoter) {
45
- ->(frag) { FakeConnection.quote_column_name(frag) }
46
- }
46
+ let(:quoter) { ->(frag) { FakeConnection.quote_column_name(frag) } }
47
47
 
48
48
  it 'should properly escape sql column names' do
49
49
  set = Sorted::Set.new([['users.name', 'desc']])
@@ -1,5 +1,7 @@
1
1
  require 'spec_helper'
2
2
 
3
+ require 'sorted/uri_query'
4
+
3
5
  describe Sorted::URIQuery, 'decode' do
4
6
  it 'should allow numbers, underscores and full stops in sort params' do
5
7
  uri = 'assessmentsTable.name_desc!users_300.name_5_desc'
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: sorted
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.0.3
4
+ version: 2.1.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Rufus Post
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-09-17 00:00:00.000000000 Z
11
+ date: 2015-12-24 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rake
@@ -83,6 +83,13 @@ files:
83
83
  - README.md
84
84
  - Rakefile
85
85
  - lib/sorted.rb
86
+ - lib/sorted/elasticsearch_query.rb
87
+ - lib/sorted/json_query.rb
88
+ - lib/sorted/params_query.rb
89
+ - lib/sorted/parse.rb
90
+ - lib/sorted/set.rb
91
+ - lib/sorted/sql_query.rb
92
+ - lib/sorted/uri_query.rb
86
93
  - lib/sorted/version.rb
87
94
  - sorted.gemspec
88
95
  - spec/elasticsearch_query_spec.rb