json_select 0.1.2 → 0.1.3

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,7 +1,7 @@
1
1
  rvm:
2
- - 1.8.7
2
+ # - 1.8.7
3
3
  - 1.9.1
4
4
  - 1.9.2
5
5
  - jruby
6
- - rbx
7
- - ree
6
+ # - rbx
7
+ # - ree
data/README.md CHANGED
@@ -1,4 +1,4 @@
1
- # JSONSelect
1
+ # JSONSelect [![Build Status](http://travis-ci.org/fd/json_select.png)](http://travis-ci.org/fd/json_select)
2
2
 
3
3
  **CSS-like selectors for JSON.**
4
4
 
@@ -48,7 +48,9 @@ json = { # This would normally be loaded with something like yajl-ruby
48
48
  "weight" => 172
49
49
  }
50
50
 
51
- JSONSelect('string:first-child').match(json) # => ["Lloyd", "Bulgarian", "English", "Spanish", "window", "beer"]
51
+ JSONSelect('string:first-child').test(json) # => true
52
+ JSONSelect('string:first-child').match(json) # => "window"
53
+ JSONSelect('string:first-child').matches(json) # => ["window", "beer"]
52
54
  ```
53
55
 
54
56
  ## Note on Patches/Pull Requests
@@ -5,6 +5,12 @@ class JSONSelect
5
5
  require 'json_select/version'
6
6
  require 'json_select/selector_parser'
7
7
  require 'json_select/selector'
8
+
9
+ require 'json_select/helpers/size'
10
+ require 'json_select/helpers/key'
11
+ require 'json_select/helpers/type'
12
+ require 'json_select/helpers/depth'
13
+ require 'json_select/helpers/position'
8
14
 
9
15
  module Ast
10
16
  require 'json_select/ast/combination_selector'
@@ -0,0 +1,7 @@
1
+ module JSONSelect::DepthHelpers
2
+
3
+ def is_root(object, test, key, idx, size, depth)
4
+ depth == 0
5
+ end
6
+
7
+ end
@@ -0,0 +1,7 @@
1
+ module JSONSelect::KeyHelpers
2
+
3
+ def has_class(object, test, key, idx, size, depth)
4
+ test[:n] == key.to_s
5
+ end
6
+
7
+ end
@@ -0,0 +1,24 @@
1
+ module JSONSelect::PositionHelpers
2
+
3
+ def nth_child(object, test, key, idx, size, depth)
4
+ return false unless idx and size
5
+
6
+ idx += 1
7
+
8
+ a = test[:a]
9
+ b = test[:b]
10
+
11
+ if a == 0
12
+ (b == idx)
13
+ else
14
+ (((idx - b) % a) == 0) and ((idx * a + b) >= 0)
15
+ end
16
+ end
17
+
18
+ def nth_last_child(object, test, key, idx, size, depth)
19
+ return false unless idx and size
20
+
21
+ nth_child(object, test, key, (size - idx) - 1, size, depth)
22
+ end
23
+
24
+ end
@@ -0,0 +1,24 @@
1
+ module JSONSelect::SizeHelpers
2
+
3
+ def only_child(object, test, key, idx, size, depth)
4
+ return false unless size
5
+
6
+ size == 1
7
+ end
8
+
9
+ def empty(object, test, key, idx, size, depth)
10
+ return false unless size
11
+
12
+ case object
13
+ when Array then return object.empty?
14
+ else
15
+ if object.respond_to?(:json_select_each)
16
+ object.json_select_each { return false }
17
+ return true
18
+ end
19
+ end
20
+
21
+ return false
22
+ end
23
+
24
+ end
@@ -0,0 +1,31 @@
1
+ module JSONSelect::TypeHelpers
2
+
3
+ def instance_of_type(object, test, key, idx, size, depth)
4
+ test[:n] == type_of(object)
5
+ end
6
+
7
+ private
8
+
9
+ def type_of(object)
10
+ if object.respond_to?(:json_select_each)
11
+ return 'array'
12
+ end
13
+
14
+ if object.respond_to?(:json_select_each_pair)
15
+ return 'object'
16
+ end
17
+
18
+ case object
19
+ when Hash then 'object'
20
+ when Array then 'array'
21
+ when String then 'string'
22
+ when Symbol then 'string'
23
+ when Numeric then 'number'
24
+ when TrueClass then 'boolean'
25
+ when FalseClass then 'boolean'
26
+ when NilClass then 'null'
27
+ else raise "Invalid object of class #{object.class} for JSONSelect: #{object.inspect}"
28
+ end
29
+ end
30
+
31
+ end
@@ -42,6 +42,19 @@ class JSONSelect
42
42
  raise ArgumentError, "Expected a string for ast"
43
43
 
44
44
  end
45
+
46
+ @helpers = Module.new
47
+ @helpers.send(:extend,
48
+ JSONSelect::KeyHelpers,
49
+ JSONSelect::TypeHelpers,
50
+ JSONSelect::SizeHelpers,
51
+ JSONSelect::DepthHelpers,
52
+ JSONSelect::PositionHelpers)
53
+
54
+ @helper_methods = {}
55
+ (@helpers.public_methods - Module.public_methods).map do |name|
56
+ @helper_methods[name.to_sym] = @helpers.method(name)
57
+ end
45
58
  end
46
59
 
47
60
  # Returns the first matching child in `object`
@@ -79,32 +92,6 @@ class JSONSelect
79
92
 
80
93
  private
81
94
 
82
- # function forEach(sel, obj, fun, id, num, tot) {
83
- # var a = (sel[0] === ',') ? sel.slice(1) : [sel];
84
- # var a0 = [];
85
- # var call = false;
86
- # for (var i = 0; i < a.length; i++) {
87
- # var x = mn(obj, a[i], id, num, tot);
88
- # if (x[0]) call = true;
89
- # for (var j = 0; j < x[1].length; j++) a0.push(x[1][j]);
90
- # }
91
- # if (a0.length && typeof obj === 'object') {
92
- # if (a0.length >= 1) a0.unshift(",");
93
- # if (isArray(obj)) {
94
- # for (var i = 0; i < obj.length; i++) forEach(a0, obj[i], fun, undefined, i, obj.length);
95
- # } else {
96
- # // it's a shame to do this for :last-child and other
97
- # // properties which count from the end when we don't
98
- # // even know if they're present. Also, the stream
99
- # // parser is going to be pissed.
100
- # var l = 0;
101
- # for (var k in obj) if (obj.hasOwnProperty(k)) l++;
102
- # var i = 0;
103
- # for (var k in obj) if (obj.hasOwnProperty(k)) forEach(a0, obj[k], fun, k, i++, l);
104
- # }
105
- # }
106
- # if (call && fun) fun(obj);
107
- # };
108
95
  def _each(selector, object, id, number, total, depth, &block)
109
96
  a0 = (selector[0] == ',' ? selector[1..-1] : [selector])
110
97
  a1 = []
@@ -131,27 +118,33 @@ private
131
118
 
132
119
  when Hash
133
120
  a1.unshift(',')
134
- size = object.size
135
121
 
136
- object.each_with_index do |(key, child), idx|
137
- _each(a1, child, key, idx, size, depth + 1, &block)
122
+ object.each do |key, child|
123
+ _each(a1, child, key, nil, nil, depth + 1, &block)
138
124
  end
139
125
 
140
126
  else
141
127
  if object.respond_to?(:json_select_each)
142
128
  children = []
143
- object.json_select_each do |key, value|
144
- children << [key, value]
129
+ object.json_select_each do |value|
130
+ children << value
145
131
  end
146
132
 
147
133
  a1.unshift(',')
148
134
  size = children.size
149
135
 
150
- children.each_with_index do |(key, child), idx|
151
- _each(a1, child, key, idx, size, depth + 1, &block)
136
+ children.each_with_index do |child, idx|
137
+ _each(a1, child, nil, idx, size, depth + 1, &block)
138
+ end
139
+
140
+ elsif object.respond_to?(:json_select_each_pair)
141
+ a1.unshift(',')
142
+
143
+ object.json_select_each_pair do |key, child|
144
+ _each(a1, child, key, nil, nil, depth + 1, &block)
152
145
  end
146
+
153
147
  end
154
-
155
148
  end
156
149
  end
157
150
 
@@ -160,34 +153,6 @@ private
160
153
  end
161
154
  end
162
155
 
163
-
164
- # function mn(node, sel, id, num, tot) {
165
- # var sels = [];
166
- # var cs = (sel[0] === '>') ? sel[1] : sel[0];
167
- # var m = true;
168
- # if (cs.type) m = m && (cs.type === mytypeof(node));
169
- # if (cs.id) m = m && (cs.id === id);
170
- # if (m && cs.pf) {
171
- # if (cs.pf === ":nth-last-child") num = tot - num;
172
- # else num++;
173
- # if (cs.a === 0) {
174
- # m = cs.b === num;
175
- # } else {
176
- # m = (!((num - cs.b) % cs.a) && ((num*cs.a + cs.b) >= 0));
177
- # }
178
- # }
179
- #
180
- # // should we repeat this selector for descendants?
181
- # if (sel[0] !== '>' && sel[0].pc !== ":root") sels.push(sel);
182
- #
183
- # if (m) {
184
- # // is there a fragment that we should pass down?
185
- # if (sel[0] === '>') { if (sel.length > 2) { m = false; sels.push(sel.slice(2)); } }
186
- # else if (sel.length > 1) { m = false; sels.push(sel.slice(1)); }
187
- # }
188
- #
189
- # return [m, sels];
190
- # }
191
156
  def _match(object, selector, id, number, total, depth)
192
157
  selectors = []
193
158
  current_selector = (selector[0] == :> ? selector[1] : selector[0])
@@ -200,7 +165,7 @@ private
200
165
  end
201
166
 
202
167
  if match
203
- match = !!send(test[:f], object, test, id, number, total, depth)
168
+ match = !!@helper_methods[test[:f].to_sym].call(object, test, id, number, total, depth)
204
169
  end
205
170
  end
206
171
 
@@ -235,70 +200,4 @@ private
235
200
  return [match, selectors]
236
201
  end
237
202
 
238
- def type_of(object)
239
- if object.respond_to?(:json_select_each)
240
- return 'object'
241
- end
242
-
243
- case object
244
- when Hash then 'object'
245
- when Array then 'array'
246
- when String then 'string'
247
- when Symbol then 'string'
248
- when Numeric then 'number'
249
- when TrueClass then 'boolean'
250
- when FalseClass then 'boolean'
251
- when NilClass then 'null'
252
- else raise "Invalid object of class #{object.class} for JSONSelect: #{object.inspect}"
253
- end
254
- end
255
-
256
- def only_child(object, test, key, idx, size, depth)
257
- size == 1
258
- end
259
-
260
- def empty(object, test, key, idx, size, depth)
261
- case object
262
- when Array then return object.empty?
263
- when Hash then return object.empty?
264
- else
265
- if object.respond_to?(:json_select_each)
266
- object.json_select_each { return false }
267
- return true
268
- end
269
- end
270
- return false
271
- end
272
-
273
- def is_root(object, test, key, idx, size, depth)
274
- depth == 0
275
- end
276
-
277
- def instance_of_type(object, test, key, idx, size, depth)
278
- test[:n] == type_of(object)
279
- end
280
-
281
- def has_class(object, test, key, idx, size, depth)
282
- test[:n] == key.to_s
283
- end
284
-
285
- def nth_child(object, test, key, idx, size, depth)
286
- return false unless idx
287
-
288
- idx += 1
289
-
290
- a = test[:a]
291
- b = test[:b]
292
-
293
- if a == 0
294
- (b == idx)
295
- else
296
- (((idx - b) % a) == 0) and ((idx * a + b) >= 0)
297
- end
298
- end
299
-
300
- def nth_last_child(object, test, key, idx, size, depth)
301
- nth_child(object, test, key, (size - idx) - 1, size, depth)
302
- end
303
-
304
203
  end
@@ -1,3 +1,3 @@
1
1
  class JSONSelect
2
- VERSION = "0.1.2"
2
+ VERSION = "0.1.3"
3
3
  end
@@ -1,6 +1,2 @@
1
- "Lloyd"
2
- "Bulgarian"
3
- "English"
4
- "Spanish"
5
1
  "window"
6
2
  "beer"
@@ -1,6 +1,2 @@
1
- "Hilaiel"
2
- "advanced"
3
- "native"
4
- "beginner"
5
1
  "aisle"
6
2
  "wine"
@@ -1,12 +1,3 @@
1
- "Lloyd"
2
- "Hilaiel"
3
- "yellow"
4
- "Bulgarian"
5
- "advanced"
6
- "English"
7
- "native"
8
- "Spanish"
9
- "beginner"
10
1
  "window"
11
2
  "aisle"
12
3
  "beer"
@@ -1,7 +1,3 @@
1
- "Lloyd"
2
- "Bulgarian"
3
- "English"
4
- "Spanish"
5
1
  "window"
6
2
  "beer"
7
3
  "wine"
@@ -1,6 +1,2 @@
1
- "Hilaiel"
2
- "advanced"
3
- "native"
4
- "beginner"
5
1
  "aisle"
6
2
  "wine"
@@ -83,4 +83,4 @@
83
83
  "wine"
84
84
  ],
85
85
  "weight": 172
86
- }
86
+ }
@@ -12,9 +12,9 @@ describe "JSONSelect", "Ruby extensions" do
12
12
  should == :hello
13
13
  end
14
14
 
15
- it "treats Objects which respond to #json_select_each as Objects" do
15
+ it "treats Objects which respond to #json_select_each_pair as Objects" do
16
16
  class Person < Struct.new(:name, :age)
17
- def json_select_each
17
+ def json_select_each_pair
18
18
  yield(:name, self.name)
19
19
  yield(:age, self.age)
20
20
  end
@@ -25,4 +25,20 @@ describe "JSONSelect", "Ruby extensions" do
25
25
  should == 'Simon Menke'
26
26
  end
27
27
 
28
+ it "treats Objects which respond to #json_select_each as Arrays" do
29
+ class List
30
+ def initialize(items)
31
+ @items = items
32
+ end
33
+
34
+ def json_select_each
35
+ @items.each { |i| yield(i) }
36
+ end
37
+ end
38
+
39
+ JSONSelect('array.person string:first-child').
40
+ match(:person => List.new(%w( foo bar baz ))).
41
+ should == 'foo'
42
+ end
43
+
28
44
  end
metadata CHANGED
@@ -1,34 +1,39 @@
1
- --- !ruby/object:Gem::Specification
1
+ --- !ruby/object:Gem::Specification
2
2
  name: json_select
3
- version: !ruby/object:Gem::Version
4
- version: 0.1.2
3
+ version: !ruby/object:Gem::Version
5
4
  prerelease:
5
+ version: 0.1.3
6
6
  platform: ruby
7
- authors:
7
+ authors:
8
8
  - Simon Menke
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2011-05-26 00:00:00.000000000Z
13
- dependencies:
14
- - !ruby/object:Gem::Dependency
12
+
13
+ date: 2011-05-27 00:00:00 +02:00
14
+ default_executable:
15
+ dependencies:
16
+ - !ruby/object:Gem::Dependency
15
17
  name: treetop
16
- requirement: &70235358530860 !ruby/object:Gem::Requirement
18
+ prerelease: false
19
+ requirement: &id001 !ruby/object:Gem::Requirement
17
20
  none: false
18
- requirements:
19
- - - ! '>='
20
- - !ruby/object:Gem::Version
21
- version: '0'
21
+ requirements:
22
+ - - ">="
23
+ - !ruby/object:Gem::Version
24
+ version: "0"
22
25
  type: :runtime
23
- prerelease: false
24
- version_requirements: *70235358530860
26
+ version_requirements: *id001
25
27
  description: JSONSelect implementation for Ruby
26
- email:
28
+ email:
27
29
  - simon.menke@gmail.com
28
30
  executables: []
31
+
29
32
  extensions: []
33
+
30
34
  extra_rdoc_files: []
31
- files:
35
+
36
+ files:
32
37
  - .gitignore
33
38
  - .travis.yml
34
39
  - Gemfile
@@ -48,6 +53,11 @@ files:
48
53
  - lib/json_select/ast/simple_selector.rb
49
54
  - lib/json_select/ast/type_selector.rb
50
55
  - lib/json_select/ast/universal_selector.rb
56
+ - lib/json_select/helpers/depth.rb
57
+ - lib/json_select/helpers/key.rb
58
+ - lib/json_select/helpers/position.rb
59
+ - lib/json_select/helpers/size.rb
60
+ - lib/json_select/helpers/type.rb
51
61
  - lib/json_select/selector.rb
52
62
  - lib/json_select/selector_parser.rb
53
63
  - lib/json_select/selector_parser.tt
@@ -110,31 +120,35 @@ files:
110
120
  - spec/fixtures/basic_universal.selector
111
121
  - spec/ruby_extensions_spec.rb
112
122
  - spec/spec_helper.rb
123
+ has_rdoc: true
113
124
  homepage: http://github.com/fd/json_select
114
125
  licenses: []
126
+
115
127
  post_install_message:
116
128
  rdoc_options: []
117
- require_paths:
129
+
130
+ require_paths:
118
131
  - lib
119
- required_ruby_version: !ruby/object:Gem::Requirement
132
+ required_ruby_version: !ruby/object:Gem::Requirement
120
133
  none: false
121
- requirements:
122
- - - ! '>='
123
- - !ruby/object:Gem::Version
124
- version: '0'
125
- required_rubygems_version: !ruby/object:Gem::Requirement
134
+ requirements:
135
+ - - ">="
136
+ - !ruby/object:Gem::Version
137
+ version: "0"
138
+ required_rubygems_version: !ruby/object:Gem::Requirement
126
139
  none: false
127
- requirements:
128
- - - ! '>='
129
- - !ruby/object:Gem::Version
130
- version: '0'
140
+ requirements:
141
+ - - ">="
142
+ - !ruby/object:Gem::Version
143
+ version: "0"
131
144
  requirements: []
145
+
132
146
  rubyforge_project: json_select
133
- rubygems_version: 1.7.2
147
+ rubygems_version: 1.6.2
134
148
  signing_key:
135
149
  specification_version: 3
136
150
  summary: JSONSelect implementation for Ruby
137
- test_files:
151
+ test_files:
138
152
  - spec/conformance_spec.rb
139
153
  - spec/fixtures/README.md
140
154
  - spec/fixtures/alltests.txt