traverse 0.0.3 → 0.1.0
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.
- data/README.md +177 -4
- data/Rakefile +3 -1
- data/lib/traverse.rb +107 -7
- data/lib/traverse/version.rb +1 -1
- data/spec/json.rb +43 -0
- data/spec/{spec.rb → xml.rb} +48 -45
- data/traverse.gemspec +7 -3
- metadata +55 -8
data/README.md
CHANGED
@@ -1,12 +1,20 @@
|
|
1
1
|
# Traverse
|
2
2
|
|
3
|
-
|
3
|
+
```bash
|
4
|
+
gem install traverse
|
5
|
+
```
|
6
|
+
|
7
|
+
## Introduction
|
8
|
+
|
9
|
+
Traverse is a simple tool that makes it easy to traverse XML and JSON.
|
4
10
|
|
5
|
-
Let's say you're messing around with Twitter's
|
11
|
+
Let's say you're messing around with Twitter's XML
|
6
12
|
[public timeline](http://api.twitter.com/statuses/public_timeline.xml).
|
7
13
|
Traverse let's you do things like this:
|
8
14
|
|
9
15
|
```ruby
|
16
|
+
require 'open-uri'
|
17
|
+
|
10
18
|
timeline = Traverse::Document.new(open "http://api.twitter.com/statuses/public_timeline.xml")
|
11
19
|
|
12
20
|
timeline.statuses.each do |status|
|
@@ -14,6 +22,18 @@ timeline.statuses.each do |status|
|
|
14
22
|
end
|
15
23
|
```
|
16
24
|
|
25
|
+
Or, let's say you're foolin' with Spotify's JSON [Search
|
26
|
+
API](http://ws.spotify.com/search/1/track.json?q=like+a+virgin).
|
27
|
+
|
28
|
+
```ruby
|
29
|
+
search = Traverse::Document.new(open "http://ws.spotify.com/search/1/track.json?q=like+a+virgin")
|
30
|
+
|
31
|
+
search.tracks.each do |track|
|
32
|
+
puts "Track: #{track.name}"
|
33
|
+
puts "Album: #{track.album.name}"
|
34
|
+
end
|
35
|
+
```
|
36
|
+
|
17
37
|
For a slightly more complicated example, take a look at a
|
18
38
|
[boxscore](http://gd2.mlb.com/components/game/mlb/year_2011/month_03/day_31/gid_2011_03_31_detmlb_nyamlb_1/boxscore.xml)
|
19
39
|
pulled from Major League Baseball's public API.
|
@@ -22,8 +42,6 @@ pulled from Major League Baseball's public API.
|
|
22
42
|
url = "http://gd2.mlb.com/components/game/mlb/year_2011/month_03/day_31/gid_2011_03_31_detmlb_nyamlb_1/boxscore.xml"
|
23
43
|
boxscore = Traverse::Document.new(open url)
|
24
44
|
|
25
|
-
# let's start traversing!
|
26
|
-
|
27
45
|
boxscore.game_id # => '2011/03/31/detmlb-nyamlb-1'
|
28
46
|
|
29
47
|
boxscore.battings[0].batters[1].name_display_first_last # => 'Derek Jeter'
|
@@ -36,3 +54,158 @@ boxscore.pitchings.find do |pitching|
|
|
36
54
|
pitching.team_flag == 'away'
|
37
55
|
end.out # => '24'
|
38
56
|
```
|
57
|
+
|
58
|
+
## Traverse's XML API
|
59
|
+
|
60
|
+
When in doubt, check the spec file.
|
61
|
+
|
62
|
+
### Children
|
63
|
+
|
64
|
+
Let's say you're working with the following node of XML:
|
65
|
+
|
66
|
+
```xml
|
67
|
+
<foo>
|
68
|
+
<bar ...>
|
69
|
+
...
|
70
|
+
</bar>
|
71
|
+
</foo>
|
72
|
+
```
|
73
|
+
|
74
|
+
Assuming you've wrapped the XML in a `Traverse::Document` named `foo`, you can
|
75
|
+
traverse to the `bar` node with a simple method call:
|
76
|
+
|
77
|
+
```ruby
|
78
|
+
foo.bar # => returns a representation of the bar node
|
79
|
+
```
|
80
|
+
|
81
|
+
If there are in fact many `bar`s inside `foo`, Traverse will transparently
|
82
|
+
collect them in an array. You can access that array by pluralizing the name of
|
83
|
+
the individual nodes:
|
84
|
+
|
85
|
+
```ruby
|
86
|
+
foo.bars # => an array containing all of the bars
|
87
|
+
foo.bars.first # => grab the first bar
|
88
|
+
```
|
89
|
+
|
90
|
+
Traverse will also do its best to transparently collect singularly-named nodes
|
91
|
+
inside of pluralized parents. Example:
|
92
|
+
|
93
|
+
```xml
|
94
|
+
<foo>
|
95
|
+
<bars>
|
96
|
+
<bar ...>
|
97
|
+
...
|
98
|
+
</bar>
|
99
|
+
...
|
100
|
+
<bar ...>
|
101
|
+
...
|
102
|
+
</bar>
|
103
|
+
</bars>
|
104
|
+
</foo>
|
105
|
+
```
|
106
|
+
```ruby
|
107
|
+
foo.bars # => an array of all of the bars
|
108
|
+
foo.bars.first # => the first bar
|
109
|
+
```
|
110
|
+
|
111
|
+
This won't work if the pluralized parent node has attributes or if its children
|
112
|
+
aren't all singularized versions of itself! Twitter's timeline is an example;
|
113
|
+
the parent node's name is `statuses`, and its children are all named
|
114
|
+
`status`, but the `statuses` node has an attribute.
|
115
|
+
|
116
|
+
### Attributes
|
117
|
+
|
118
|
+
If your XML node has an attribute named `foo`, you can access that attribute
|
119
|
+
with a simple method call:
|
120
|
+
|
121
|
+
```ruby
|
122
|
+
my_node.foo # => return the attribute's value
|
123
|
+
```
|
124
|
+
|
125
|
+
Notice that there might be a conflict if your node has both an attribute named
|
126
|
+
`foo` _and_ a child `foo`. Traverse puts children first, so the attribute `foo`
|
127
|
+
will get clobbered.
|
128
|
+
|
129
|
+
To get around this, Traverse provides a backdoor for when you really want the
|
130
|
+
attribute:
|
131
|
+
|
132
|
+
```ruby
|
133
|
+
my_node.foo # => grabs the child named foo
|
134
|
+
my_node['foo'] # => grabs the attribute named foo
|
135
|
+
```
|
136
|
+
|
137
|
+
### Text
|
138
|
+
|
139
|
+
If you traverse to a node that has no attributes and contains only text, you
|
140
|
+
can grab that text with a simple method call. Let's suppose you have the
|
141
|
+
following XML:
|
142
|
+
|
143
|
+
```xml
|
144
|
+
<foo>
|
145
|
+
<bar>
|
146
|
+
This bar rocks!
|
147
|
+
</bar>
|
148
|
+
</foo>
|
149
|
+
```
|
150
|
+
|
151
|
+
You can grab the text like this:
|
152
|
+
|
153
|
+
```ruby
|
154
|
+
foo.bar # => "This bar rocks!"
|
155
|
+
```
|
156
|
+
|
157
|
+
What if `bar` does have attributes? Then you'll need to use the `text` method:
|
158
|
+
|
159
|
+
```xml
|
160
|
+
<foo>
|
161
|
+
<bar baz="quux">
|
162
|
+
This bar rocks!
|
163
|
+
</bar>
|
164
|
+
</foo>
|
165
|
+
```
|
166
|
+
```ruby
|
167
|
+
foo.bar # => grabs a representation of the node, not the text!
|
168
|
+
foo.bar.text # => "This bar rocks!"
|
169
|
+
```
|
170
|
+
|
171
|
+
I know what you're thinking: what the hell do I do if my node has text inside
|
172
|
+
it but I want to grab its attribute named `text`???
|
173
|
+
|
174
|
+
```ruby
|
175
|
+
foo.bar['text'] # => grab bar's attribute named 'text'
|
176
|
+
foo.bar.text # => grab bar's text contents
|
177
|
+
```
|
178
|
+
|
179
|
+
## Traverse's JSON API
|
180
|
+
|
181
|
+
Again, when in doubt, check the spec file.
|
182
|
+
|
183
|
+
Traverse doesn't really do anything magical with JSON data; under the hood, it
|
184
|
+
uses `YAJL` to parse JSON into a `Hash`, and hashes are alredy pretty
|
185
|
+
traversable in Ruby. But, to maintain consistency with the XML API, you can
|
186
|
+
happily traverse JSON using method calls instead of querying a hash.
|
187
|
+
|
188
|
+
## Helper methods
|
189
|
+
Traverse provides a few helper methods to help with traversal.
|
190
|
+
|
191
|
+
If you're traversing some JSON, the ```_keys_``` method will be available. It
|
192
|
+
returns an array containing the names of the JSON object's keys.
|
193
|
+
|
194
|
+
```ruby
|
195
|
+
search._keys_.count
|
196
|
+
# => 2
|
197
|
+
|
198
|
+
search.first._keys_
|
199
|
+
# => ["user","favorited","source","id","text","created_at"]
|
200
|
+
```
|
201
|
+
|
202
|
+
If you're looking at XML, the ```_children_``` and ```_attributes_``` methods
|
203
|
+
will be available. The ```_children_``` method gives you an array of
|
204
|
+
traversable child nodes, and ```_attributes_``` gives you a hash of
|
205
|
+
attribute-name/attribute-value pairs.
|
206
|
+
|
207
|
+
## Contributors!
|
208
|
+
|
209
|
+
Traverse wouldn't be possible without help from friends. Thanks!
|
210
|
+
|
211
|
+
- [muffs](https://github.com/muffs)
|
data/Rakefile
CHANGED
data/lib/traverse.rb
CHANGED
@@ -1,10 +1,53 @@
|
|
1
1
|
require "traverse/version"
|
2
2
|
require 'nokogiri'
|
3
|
-
require '
|
3
|
+
require 'yajl'
|
4
4
|
require 'active_support/inflector'
|
5
5
|
|
6
6
|
module Traverse
|
7
7
|
class Document
|
8
|
+
def initialize document
|
9
|
+
if xml? document
|
10
|
+
@proxy = XML.new document
|
11
|
+
elsif json? document
|
12
|
+
@proxy = JSON.new document
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
private
|
17
|
+
def method_missing m, *args, &block
|
18
|
+
@proxy.send m, *args, &block
|
19
|
+
end
|
20
|
+
|
21
|
+
def xml? document
|
22
|
+
begin
|
23
|
+
Nokogiri::XML(document) do |config|
|
24
|
+
config.options = Nokogiri::XML::ParseOptions::STRICT
|
25
|
+
end
|
26
|
+
true
|
27
|
+
rescue Nokogiri::XML::SyntaxError
|
28
|
+
false
|
29
|
+
ensure
|
30
|
+
document.rewind if document.respond_to? :read
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
def json? document
|
35
|
+
begin
|
36
|
+
Yajl::Parser.new.parse(document)
|
37
|
+
true
|
38
|
+
rescue Yajl::ParseError
|
39
|
+
false
|
40
|
+
ensure
|
41
|
+
document.rewind if document.respond_to? :read
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
def to_s
|
46
|
+
"<Traverse::Document...>"
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
class XML
|
8
51
|
def initialize document
|
9
52
|
setup_underlying_document document
|
10
53
|
|
@@ -23,7 +66,7 @@ module Traverse
|
|
23
66
|
end
|
24
67
|
else
|
25
68
|
define_singleton_method name do
|
26
|
-
|
69
|
+
XML.new child
|
27
70
|
end
|
28
71
|
end
|
29
72
|
else
|
@@ -32,7 +75,7 @@ module Traverse
|
|
32
75
|
if text_only_node? child
|
33
76
|
child.content.strip
|
34
77
|
else
|
35
|
-
|
78
|
+
XML.new child
|
36
79
|
end
|
37
80
|
end
|
38
81
|
end
|
@@ -43,7 +86,7 @@ module Traverse
|
|
43
86
|
define_singleton_method pluralized_child.name do
|
44
87
|
pluralized_child.children.reject do |baby|
|
45
88
|
baby.class == Nokogiri::XML::Text
|
46
|
-
end.map { |child|
|
89
|
+
end.map { |child| XML.new child }
|
47
90
|
end
|
48
91
|
end
|
49
92
|
|
@@ -53,15 +96,15 @@ module Traverse
|
|
53
96
|
@document.get_attribute attr
|
54
97
|
end
|
55
98
|
|
56
|
-
def
|
99
|
+
def _attributes_
|
57
100
|
name_value_pairs = @document.attributes.map do |name, attribute|
|
58
101
|
[name, attribute.value]
|
59
102
|
end
|
60
103
|
Hash[ name_value_pairs ]
|
61
104
|
end
|
62
105
|
|
63
|
-
def
|
64
|
-
real_children.map { |child|
|
106
|
+
def _children_
|
107
|
+
real_children.map { |child| XML.new child }
|
65
108
|
end
|
66
109
|
|
67
110
|
private
|
@@ -145,4 +188,61 @@ module Traverse
|
|
145
188
|
"<Traversable... >"
|
146
189
|
end
|
147
190
|
end
|
191
|
+
|
192
|
+
class JSON
|
193
|
+
|
194
|
+
def initialize json
|
195
|
+
|
196
|
+
setup_underlying_json json
|
197
|
+
|
198
|
+
if @json.is_a? Array
|
199
|
+
@proxy = @json.map do |item|
|
200
|
+
JSON.new item
|
201
|
+
end
|
202
|
+
elsif @json.is_a? Hash
|
203
|
+
@json.each_pair do |k,v|
|
204
|
+
define_singleton_method k do
|
205
|
+
if v.is_a? Hash
|
206
|
+
JSON.new(v)
|
207
|
+
elsif v.is_a? Array
|
208
|
+
v.map { |i| JSON.new(i) }
|
209
|
+
else
|
210
|
+
v
|
211
|
+
end
|
212
|
+
end
|
213
|
+
define_singleton_method "_keys_" do
|
214
|
+
@json.keys
|
215
|
+
end
|
216
|
+
end
|
217
|
+
elsif @json.is_a? Array
|
218
|
+
@json.map! { |i| JSON.new i }
|
219
|
+
end
|
220
|
+
end
|
221
|
+
|
222
|
+
private
|
223
|
+
def method_missing m, *args, &block
|
224
|
+
if @proxy
|
225
|
+
@proxy.send m, *args, &block
|
226
|
+
else
|
227
|
+
super
|
228
|
+
end
|
229
|
+
end
|
230
|
+
|
231
|
+
def setup_underlying_json document
|
232
|
+
if document.is_a? String
|
233
|
+
@json = Yajl::Parser.new.parse document
|
234
|
+
elsif document.respond_to? :read # Tempfile / StringIO
|
235
|
+
begin
|
236
|
+
parser = Yajl::Parser.new
|
237
|
+
@json = parser.parse(document)
|
238
|
+
rescue
|
239
|
+
nil
|
240
|
+
ensure
|
241
|
+
document.rewind
|
242
|
+
end
|
243
|
+
elsif document.is_a? Hash
|
244
|
+
@json = document
|
245
|
+
end
|
246
|
+
end
|
247
|
+
end
|
148
248
|
end
|
data/lib/traverse/version.rb
CHANGED
data/spec/json.rb
ADDED
@@ -0,0 +1,43 @@
|
|
1
|
+
require 'traverse'
|
2
|
+
|
3
|
+
gem 'minitest'
|
4
|
+
require 'minitest/autorun'
|
5
|
+
require 'minitest/pride'
|
6
|
+
|
7
|
+
json = %{
|
8
|
+
{
|
9
|
+
"menu": {
|
10
|
+
"id": "file",
|
11
|
+
"value": "File",
|
12
|
+
"popup": {
|
13
|
+
"menuitem": [
|
14
|
+
{"value": "New", "onclick": "CreateNewDoc()"},
|
15
|
+
{"value": "Open", "onclick": "OpenDoc()"},
|
16
|
+
{"value": "Close", "onclick": "CloseDoc()"}
|
17
|
+
]
|
18
|
+
}
|
19
|
+
}
|
20
|
+
}
|
21
|
+
}
|
22
|
+
|
23
|
+
describe Traverse::Document do
|
24
|
+
before do
|
25
|
+
@doc = Traverse::Document.new json
|
26
|
+
end
|
27
|
+
|
28
|
+
describe "Grabbing simple attributes" do
|
29
|
+
it "helps you access attributes" do
|
30
|
+
@doc.menu.id.must_equal "file"
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
describe "Grabbing attributes that are arrays" do
|
35
|
+
it "knows how to handle json arrays" do
|
36
|
+
@doc.menu.popup.menuitem.count.must_equal 3
|
37
|
+
end
|
38
|
+
|
39
|
+
it "traversifies the elements of json arrays" do
|
40
|
+
@doc.menu.popup.menuitem.last.value.must_equal "Close"
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
data/spec/{spec.rb → xml.rb}
RENAMED
@@ -1,4 +1,3 @@
|
|
1
|
-
$:.push '../'
|
2
1
|
require 'traverse'
|
3
2
|
|
4
3
|
gem 'minitest'
|
@@ -38,7 +37,7 @@ xml = %{
|
|
38
37
|
expert. Not a genius, exactly, more like an idiot savant with X-ray
|
39
38
|
vision.
|
40
39
|
</quotation>
|
41
|
-
</
|
40
|
+
</quotations>
|
42
41
|
<review reviewer="Salman Rushdie">
|
43
42
|
What is interesting is to have before us, at the end of the Greed
|
44
43
|
Decade, that rarest of birds: a major political novel about what
|
@@ -59,66 +58,70 @@ describe Traverse::Document do
|
|
59
58
|
@book = Traverse::Document.new xml
|
60
59
|
end
|
61
60
|
|
62
|
-
|
63
|
-
|
64
|
-
|
61
|
+
describe "Grabbing attributes" do
|
62
|
+
it "helps you access attributes" do
|
63
|
+
@book.title.must_equal "Vineland"
|
64
|
+
end
|
65
65
|
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
@book.author.name.must_equal "Thomas Pynchon"
|
70
|
-
end
|
66
|
+
it "also lets you access attributes shadowed by children" do
|
67
|
+
@book.author.wont_equal "Thomas Pynchon"
|
68
|
+
@book.author.class.wont_equal String
|
71
69
|
|
72
|
-
|
70
|
+
@book['author'].must_equal "Thomas Pynchon"
|
71
|
+
end
|
72
|
+
end
|
73
73
|
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
74
|
+
describe "Traversing to children" do
|
75
|
+
it "helps you traverse to child nodes" do
|
76
|
+
@book.review.reviewer.must_equal "Salman Rushdie"
|
77
|
+
@book.epigraph.author.must_equal "Johnny Copeland"
|
78
78
|
end
|
79
79
|
|
80
|
-
it "
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
80
|
+
it "knows to collect children with the same name" do
|
81
|
+
@book.author.books.class.must_equal Array
|
82
|
+
@book.author.books.count.must_equal 8
|
83
|
+
assert @book.author.books.all? do |book|
|
84
|
+
book.is_a? String
|
85
85
|
end
|
86
86
|
end
|
87
87
|
|
88
|
+
it "knows to collect singularized children of a pluralized parent" do
|
89
|
+
@book.quotations.count.must_equal 2
|
90
|
+
@book.quotations.last.text.must_match(/more like an idiot savant/)
|
91
|
+
end
|
88
92
|
end
|
89
93
|
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
+
describe "Dealing with text nodes" do
|
95
|
+
it "handles annoying text nodes transparently" do
|
96
|
+
@book.epigraph.text.must_match(/Every dog has his day/)
|
97
|
+
@book.review.text.must_match(/that rarest of birds/)
|
98
|
+
end
|
94
99
|
|
95
|
-
|
96
|
-
|
97
|
-
|
100
|
+
it "nevertheless handles attributes named 'text'" do
|
101
|
+
@book.text['text'].must_match(/seriously/)
|
102
|
+
@book.text.text.must_match(/rilly/)
|
103
|
+
end
|
98
104
|
|
99
|
-
|
100
|
-
|
101
|
-
|
105
|
+
it "handles nodes with only text and no attributes" do
|
106
|
+
@book.pagecount.must_equal "385"
|
107
|
+
end
|
102
108
|
end
|
103
109
|
|
104
|
-
it "nevertheless handles attributes named 'text'" do
|
105
|
-
@book.text['text'].must_match(/seriously/)
|
106
|
-
@book.text.text.must_match(/rilly/)
|
107
|
-
end
|
108
110
|
|
109
|
-
|
110
|
-
|
111
|
-
|
111
|
+
describe "Support for enumerable" do
|
112
|
+
it "gives you access to the current node's attributes" do
|
113
|
+
@book._attributes_.any? do |name, value|
|
114
|
+
value == "Vineland"
|
115
|
+
end.must_equal true
|
116
|
+
end
|
112
117
|
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
118
|
+
it "gives you access to the current node's children as traversable documents" do
|
119
|
+
assert @book._children_.any? do |child|
|
120
|
+
child.attributes.any? do |name, value|
|
121
|
+
name == "reviewer" and value == "Salman Rushdie"
|
122
|
+
end
|
123
|
+
end
|
117
124
|
end
|
118
125
|
end
|
119
126
|
|
120
|
-
it "knows to collect children of a pluralized parent" do
|
121
|
-
@book.quotations.count.must_equal 2
|
122
|
-
@book.quotations.last.text.must_match(/more like an idiot savant/)
|
123
|
-
end
|
124
127
|
end
|
data/traverse.gemspec
CHANGED
@@ -5,11 +5,11 @@ require "traverse/version"
|
|
5
5
|
Gem::Specification.new do |s|
|
6
6
|
s.name = "traverse"
|
7
7
|
s.version = Traverse::VERSION
|
8
|
-
s.authors = ["happy4crazy"]
|
8
|
+
s.authors = ["happy4crazy", "muffs"]
|
9
9
|
s.email = ["alan.m.odonnell@gmail.com"]
|
10
10
|
s.homepage = "https://github.com/happy4crazy/traverse"
|
11
|
-
s.summary = %q{Easily traverse
|
12
|
-
s.description = %q{Easily traverse
|
11
|
+
s.summary = %q{Easily traverse XML and JSON.}
|
12
|
+
s.description = %q{Easily traverse XML and JSON.}
|
13
13
|
|
14
14
|
s.rubyforge_project = "traverse"
|
15
15
|
|
@@ -18,5 +18,9 @@ Gem::Specification.new do |s|
|
|
18
18
|
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
19
19
|
s.require_paths = ["lib"]
|
20
20
|
|
21
|
+
s.add_development_dependency 'minitest'
|
21
22
|
s.add_dependency 'nokogiri', '~> 1.5'
|
23
|
+
s.add_dependency 'active_support'
|
24
|
+
s.add_dependency 'i18n'
|
25
|
+
s.add_dependency 'yajl-ruby'
|
22
26
|
end
|
metadata
CHANGED
@@ -1,20 +1,32 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: traverse
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0
|
4
|
+
version: 0.1.0
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
8
8
|
- happy4crazy
|
9
|
+
- muffs
|
9
10
|
autorequire:
|
10
11
|
bindir: bin
|
11
12
|
cert_chain: []
|
12
|
-
date: 2011-08-
|
13
|
+
date: 2011-08-18 00:00:00.000000000 -04:00
|
13
14
|
default_executable:
|
14
15
|
dependencies:
|
16
|
+
- !ruby/object:Gem::Dependency
|
17
|
+
name: minitest
|
18
|
+
requirement: &2157763120 !ruby/object:Gem::Requirement
|
19
|
+
none: false
|
20
|
+
requirements:
|
21
|
+
- - ! '>='
|
22
|
+
- !ruby/object:Gem::Version
|
23
|
+
version: '0'
|
24
|
+
type: :development
|
25
|
+
prerelease: false
|
26
|
+
version_requirements: *2157763120
|
15
27
|
- !ruby/object:Gem::Dependency
|
16
28
|
name: nokogiri
|
17
|
-
requirement: &
|
29
|
+
requirement: &2157762620 !ruby/object:Gem::Requirement
|
18
30
|
none: false
|
19
31
|
requirements:
|
20
32
|
- - ~>
|
@@ -22,8 +34,41 @@ dependencies:
|
|
22
34
|
version: '1.5'
|
23
35
|
type: :runtime
|
24
36
|
prerelease: false
|
25
|
-
version_requirements: *
|
26
|
-
|
37
|
+
version_requirements: *2157762620
|
38
|
+
- !ruby/object:Gem::Dependency
|
39
|
+
name: active_support
|
40
|
+
requirement: &2157762200 !ruby/object:Gem::Requirement
|
41
|
+
none: false
|
42
|
+
requirements:
|
43
|
+
- - ! '>='
|
44
|
+
- !ruby/object:Gem::Version
|
45
|
+
version: '0'
|
46
|
+
type: :runtime
|
47
|
+
prerelease: false
|
48
|
+
version_requirements: *2157762200
|
49
|
+
- !ruby/object:Gem::Dependency
|
50
|
+
name: i18n
|
51
|
+
requirement: &2152011700 !ruby/object:Gem::Requirement
|
52
|
+
none: false
|
53
|
+
requirements:
|
54
|
+
- - ! '>='
|
55
|
+
- !ruby/object:Gem::Version
|
56
|
+
version: '0'
|
57
|
+
type: :runtime
|
58
|
+
prerelease: false
|
59
|
+
version_requirements: *2152011700
|
60
|
+
- !ruby/object:Gem::Dependency
|
61
|
+
name: yajl-ruby
|
62
|
+
requirement: &2152011280 !ruby/object:Gem::Requirement
|
63
|
+
none: false
|
64
|
+
requirements:
|
65
|
+
- - ! '>='
|
66
|
+
- !ruby/object:Gem::Version
|
67
|
+
version: '0'
|
68
|
+
type: :runtime
|
69
|
+
prerelease: false
|
70
|
+
version_requirements: *2152011280
|
71
|
+
description: Easily traverse XML and JSON.
|
27
72
|
email:
|
28
73
|
- alan.m.odonnell@gmail.com
|
29
74
|
executables: []
|
@@ -36,7 +81,8 @@ files:
|
|
36
81
|
- Rakefile
|
37
82
|
- lib/traverse.rb
|
38
83
|
- lib/traverse/version.rb
|
39
|
-
- spec/
|
84
|
+
- spec/json.rb
|
85
|
+
- spec/xml.rb
|
40
86
|
- traverse.gemspec
|
41
87
|
has_rdoc: true
|
42
88
|
homepage: https://github.com/happy4crazy/traverse
|
@@ -62,6 +108,7 @@ rubyforge_project: traverse
|
|
62
108
|
rubygems_version: 1.6.2
|
63
109
|
signing_key:
|
64
110
|
specification_version: 3
|
65
|
-
summary: Easily traverse
|
111
|
+
summary: Easily traverse XML and JSON.
|
66
112
|
test_files:
|
67
|
-
- spec/
|
113
|
+
- spec/json.rb
|
114
|
+
- spec/xml.rb
|