crack 0.3.2 → 0.4.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/.gitignore +7 -0
- data/Gemfile +6 -0
- data/Gemfile.lock +22 -0
- data/README.md +44 -0
- data/crack.gemspec +15 -48
- data/lib/crack.rb +0 -1
- data/lib/crack/json.rb +15 -1
- data/lib/crack/version.rb +3 -0
- data/lib/crack/xml.rb +13 -5
- data/script/bootstrap +21 -0
- data/script/release +42 -0
- data/script/test +25 -0
- data/test/hash_test.rb +19 -21
- data/test/json_test.rb +20 -27
- data/test/parser_test.rb +13 -13
- data/test/string_test.rb +17 -17
- data/test/test_helper.rb +2 -11
- data/test/xml_test.rb +115 -93
- metadata +59 -50
- data/README.rdoc +0 -42
- data/Rakefile +0 -32
- data/test/crack_test.rb +0 -4
data/.gitignore
ADDED
data/Gemfile
ADDED
data/Gemfile.lock
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
PATH
|
2
|
+
remote: .
|
3
|
+
specs:
|
4
|
+
crack (0.3.2)
|
5
|
+
safe_yaml (~> 0.9.0)
|
6
|
+
|
7
|
+
GEM
|
8
|
+
remote: https://rubygems.org/
|
9
|
+
specs:
|
10
|
+
jnunemaker-matchy (0.4.0)
|
11
|
+
minitest (5.0.3)
|
12
|
+
rake (10.0.3)
|
13
|
+
safe_yaml (0.9.2)
|
14
|
+
|
15
|
+
PLATFORMS
|
16
|
+
ruby
|
17
|
+
|
18
|
+
DEPENDENCIES
|
19
|
+
crack!
|
20
|
+
jnunemaker-matchy
|
21
|
+
minitest
|
22
|
+
rake
|
data/README.md
ADDED
@@ -0,0 +1,44 @@
|
|
1
|
+
# crack
|
2
|
+
|
3
|
+
Really simple JSON and XML parsing, ripped from Merb and Rails. The XML parser is ripped from Merb and the JSON parser is ripped from Rails. I take no credit, just packaged them for all to enjoy and easily use.
|
4
|
+
|
5
|
+
## compatibility
|
6
|
+
|
7
|
+
* ruby 1.8.7
|
8
|
+
* ruby 1.9+ (3 failures related to time parsing, would love it if someone could figure them out)
|
9
|
+
|
10
|
+
## note on patches/pull requests
|
11
|
+
|
12
|
+
* Fork the project.
|
13
|
+
* Make your feature addition or bug fix.
|
14
|
+
* Add tests for it. This is important so I don't break it in a future version unintentionally.
|
15
|
+
* `script/test` - this will bootstrap and run the tests
|
16
|
+
* Commit, do not mess with rakefile, version, or history. (if you want to have your own version, that is fine but bump version in a commit by itself in another branch so I can ignore when I pull)
|
17
|
+
* Send me a pull request. Bonus points for topic branches.
|
18
|
+
|
19
|
+
## usage
|
20
|
+
|
21
|
+
```ruby
|
22
|
+
gem 'crack' # in Gemfile
|
23
|
+
require 'crack' # for xml and json
|
24
|
+
require 'crack/json' # for just json
|
25
|
+
require 'crack/xml' # for just xml
|
26
|
+
```
|
27
|
+
|
28
|
+
## examples
|
29
|
+
|
30
|
+
```ruby
|
31
|
+
Crack::XML.parse("<tag>This is the contents</tag>")
|
32
|
+
# => {'tag' => 'This is the contents'}
|
33
|
+
|
34
|
+
Crack::JSON.parse('{"tag":"This is the contents"}')
|
35
|
+
# => {'tag' => 'This is the contents'}
|
36
|
+
```
|
37
|
+
|
38
|
+
## Copyright
|
39
|
+
|
40
|
+
Copyright (c) 2009 John Nunemaker. See LICENSE for details.
|
41
|
+
|
42
|
+
## Docs
|
43
|
+
|
44
|
+
http://rdoc.info/projects/jnunemaker/crack
|
data/crack.gemspec
CHANGED
@@ -1,53 +1,20 @@
|
|
1
|
-
# Generated by jeweler
|
2
|
-
# DO NOT EDIT THIS FILE DIRECTLY
|
3
|
-
# Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec'
|
4
1
|
# -*- encoding: utf-8 -*-
|
2
|
+
require File.expand_path('../lib/crack/version', __FILE__)
|
5
3
|
|
6
|
-
Gem::Specification.new do |
|
7
|
-
|
8
|
-
|
4
|
+
Gem::Specification.new do |gem|
|
5
|
+
gem.authors = ["John Nunemaker"]
|
6
|
+
gem.email = ["nunemaker@gmail.com"]
|
7
|
+
gem.description = %q{Really simple JSON and XML parsing, ripped from Merb and Rails.}
|
8
|
+
gem.summary = %q{Really simple JSON and XML parsing, ripped from Merb and Rails.}
|
9
|
+
gem.homepage = "http://github.com/jnunemaker/crack"
|
9
10
|
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
]
|
18
|
-
s.files = [
|
19
|
-
"History",
|
20
|
-
"LICENSE",
|
21
|
-
"README.rdoc",
|
22
|
-
"Rakefile",
|
23
|
-
"crack.gemspec",
|
24
|
-
"lib/crack.rb",
|
25
|
-
"lib/crack/json.rb",
|
26
|
-
"lib/crack/util.rb",
|
27
|
-
"lib/crack/xml.rb",
|
28
|
-
"test/crack_test.rb",
|
29
|
-
"test/data/twittersearch-firefox.json",
|
30
|
-
"test/data/twittersearch-ie.json",
|
31
|
-
"test/hash_test.rb",
|
32
|
-
"test/json_test.rb",
|
33
|
-
"test/parser_test.rb",
|
34
|
-
"test/string_test.rb",
|
35
|
-
"test/test_helper.rb",
|
36
|
-
"test/xml_test.rb"
|
37
|
-
]
|
38
|
-
s.homepage = "http://github.com/jnunemaker/crack"
|
39
|
-
s.require_paths = ["lib"]
|
40
|
-
s.rubyforge_project = "crack"
|
41
|
-
s.rubygems_version = "1.8.10"
|
42
|
-
s.summary = "Really simple JSON and XML parsing, ripped from Merb and Rails."
|
11
|
+
gem.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
12
|
+
gem.files = `git ls-files`.split("\n")
|
13
|
+
gem.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
14
|
+
gem.name = "crack"
|
15
|
+
gem.require_paths = ["lib"]
|
16
|
+
gem.version = Crack::VERSION
|
17
|
+
gem.license = "MIT"
|
43
18
|
|
44
|
-
|
45
|
-
s.specification_version = 3
|
46
|
-
|
47
|
-
if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
|
48
|
-
else
|
49
|
-
end
|
50
|
-
else
|
51
|
-
end
|
19
|
+
gem.add_dependency "safe_yaml", "~> 0.9.0"
|
52
20
|
end
|
53
|
-
|
data/lib/crack.rb
CHANGED
data/lib/crack/json.rb
CHANGED
@@ -8,9 +8,23 @@ require 'strscan'
|
|
8
8
|
|
9
9
|
module Crack
|
10
10
|
class JSON
|
11
|
+
def self.parser_exceptions
|
12
|
+
@parser_exceptions ||= begin
|
13
|
+
exceptions = [ArgumentError]
|
14
|
+
|
15
|
+
if const_defined?(:Psych)
|
16
|
+
if Psych.const_defined?(:SyntaxError)
|
17
|
+
exceptions << Psych::SyntaxError
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
exceptions
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
11
25
|
def self.parse(json)
|
12
26
|
YAML.load(unescape(convert_json_to_yaml(json)))
|
13
|
-
rescue
|
27
|
+
rescue *parser_exceptions
|
14
28
|
raise ParseError, "Invalid JSON string"
|
15
29
|
end
|
16
30
|
|
data/lib/crack/xml.rb
CHANGED
@@ -2,11 +2,19 @@ require 'rexml/parsers/streamparser'
|
|
2
2
|
require 'rexml/parsers/baseparser'
|
3
3
|
require 'rexml/light/node'
|
4
4
|
require 'rexml/text'
|
5
|
+
require "rexml/document"
|
5
6
|
require 'date'
|
6
7
|
require 'time'
|
7
8
|
require 'yaml'
|
8
9
|
require 'bigdecimal'
|
9
10
|
|
11
|
+
# The Reason behind redefining the String Class for this specific plugin is to
|
12
|
+
# avoid the dynamic insertion of stuff on it (see version previous to this commit).
|
13
|
+
# Doing that disables the possibility of efectuating a dump on the structure. This way it goes.
|
14
|
+
class REXMLUtiliyNodeString < String
|
15
|
+
attr_accessor :attributes
|
16
|
+
end
|
17
|
+
|
10
18
|
# This is a slighly modified version of the XMLUtilityNode from
|
11
19
|
# http://merb.devjavu.com/projects/merb/ticket/95 (has.sox@gmail.com)
|
12
20
|
# It's mainly just adding vowels, as I ht cd wth n vwls :)
|
@@ -68,7 +76,8 @@ class REXMLUtilityNode #:nodoc:
|
|
68
76
|
end
|
69
77
|
|
70
78
|
def to_hash
|
71
|
-
|
79
|
+
# ACG: Added a check here to prevent an exception a type == "file" tag has nodes within it
|
80
|
+
if @type == "file" and (@children.first.nil? or @children.first.is_a?(String))
|
72
81
|
f = StringIO.new((@children.first || '').unpack('m').first)
|
73
82
|
class << f
|
74
83
|
attr_accessor :original_filename, :content_type
|
@@ -81,9 +90,7 @@ class REXMLUtilityNode #:nodoc:
|
|
81
90
|
if @text
|
82
91
|
t = typecast_value( unnormalize_xml_entities( inner_html ) )
|
83
92
|
if t.is_a?(String)
|
84
|
-
|
85
|
-
attr_accessor :attributes
|
86
|
-
end
|
93
|
+
t = REXMLUtiliyNodeString.new(t)
|
87
94
|
t.attributes = attributes
|
88
95
|
end
|
89
96
|
return { name => t }
|
@@ -187,7 +194,7 @@ class REXMLUtilityNode #:nodoc:
|
|
187
194
|
end
|
188
195
|
|
189
196
|
module Crack
|
190
|
-
|
197
|
+
class REXMLParser
|
191
198
|
def self.parse(xml)
|
192
199
|
stack = []
|
193
200
|
parser = REXML::Parsers::BaseParser.new(xml)
|
@@ -210,6 +217,7 @@ module Crack
|
|
210
217
|
stack.last.add_node(event[1]) unless event[1].strip.length == 0 || stack.empty?
|
211
218
|
end
|
212
219
|
end
|
220
|
+
|
213
221
|
stack.length > 0 ? stack.pop.to_hash : {}
|
214
222
|
end
|
215
223
|
end
|
data/script/bootstrap
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
#!/bin/sh
|
2
|
+
#/ Usage: bootstrap [bundle options]
|
3
|
+
#/
|
4
|
+
#/ Bundle install the dependencies.
|
5
|
+
#/
|
6
|
+
#/ Examples:
|
7
|
+
#/
|
8
|
+
#/ bootstrap
|
9
|
+
#/ bootstrap --local
|
10
|
+
#/
|
11
|
+
|
12
|
+
set -e
|
13
|
+
cd $(dirname "$0")/..
|
14
|
+
|
15
|
+
[ "$1" = "--help" -o "$1" = "-h" -o "$1" = "help" ] && {
|
16
|
+
grep '^#/' <"$0"| cut -c4-
|
17
|
+
exit 0
|
18
|
+
}
|
19
|
+
|
20
|
+
rm -rf .bundle/{binstubs,config}
|
21
|
+
bundle install --binstubs .bundle/binstubs --path .bundle --quiet "$@"
|
data/script/release
ADDED
@@ -0,0 +1,42 @@
|
|
1
|
+
#!/bin/sh
|
2
|
+
#/ Usage: release
|
3
|
+
#/
|
4
|
+
#/ Tag the version in the repo and push the gem.
|
5
|
+
#/
|
6
|
+
|
7
|
+
set -e
|
8
|
+
cd $(dirname "$0")/..
|
9
|
+
|
10
|
+
[ "$1" = "--help" -o "$1" = "-h" -o "$1" = "help" ] && {
|
11
|
+
grep '^#/' <"$0"| cut -c4-
|
12
|
+
exit 0
|
13
|
+
}
|
14
|
+
|
15
|
+
gem_name=crack
|
16
|
+
|
17
|
+
# Build a new gem archive.
|
18
|
+
rm -rf $gem_name-*.gem
|
19
|
+
gem build -q $gem_name.gemspec
|
20
|
+
|
21
|
+
# Make sure we're on the master branch.
|
22
|
+
(git branch | grep -q '* master') || {
|
23
|
+
echo "Only release from the master branch."
|
24
|
+
exit 1
|
25
|
+
}
|
26
|
+
|
27
|
+
# Figure out what version we're releasing.
|
28
|
+
tag=v`ls $gem_name-*.gem | sed "s/^$gem_name-\(.*\)\.gem$/\1/"`
|
29
|
+
|
30
|
+
echo "Releasing $tag"
|
31
|
+
|
32
|
+
# Make sure we haven't released this version before.
|
33
|
+
git fetch -t origin
|
34
|
+
|
35
|
+
(git tag -l | grep -q "$tag") && {
|
36
|
+
echo "Whoops, there's already a '${tag}' tag."
|
37
|
+
exit 1
|
38
|
+
}
|
39
|
+
|
40
|
+
# Tag it and bag it.
|
41
|
+
gem push $gem_name-*.gem && git tag "$tag" &&
|
42
|
+
git push origin master && git push origin "$tag"
|
data/script/test
ADDED
@@ -0,0 +1,25 @@
|
|
1
|
+
#!/bin/sh
|
2
|
+
#/ Usage: test [individual test file]
|
3
|
+
#/
|
4
|
+
#/ Bootstrap and run all tests or an individual test.
|
5
|
+
#/
|
6
|
+
#/ Examples:
|
7
|
+
#/
|
8
|
+
#/ # run all tests
|
9
|
+
#/ test
|
10
|
+
#/
|
11
|
+
#/ # run individual test
|
12
|
+
#/ test test/controller_instrumentation_test.rb
|
13
|
+
#/
|
14
|
+
|
15
|
+
set -e
|
16
|
+
cd $(dirname "$0")/..
|
17
|
+
|
18
|
+
[ "$1" = "--help" -o "$1" = "-h" -o "$1" = "help" ] && {
|
19
|
+
grep '^#/' <"$0"| cut -c4-
|
20
|
+
exit 0
|
21
|
+
}
|
22
|
+
|
23
|
+
script/bootstrap && ruby -I lib -I test -r rubygems \
|
24
|
+
-e 'require "bundler/setup"' \
|
25
|
+
-e '(ARGV.empty? ? Dir["test/**/*_test.rb"] : ARGV).each { |f| load f }' -- "$@"
|
data/test/hash_test.rb
CHANGED
@@ -1,28 +1,26 @@
|
|
1
1
|
require 'test_helper'
|
2
2
|
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
end
|
3
|
+
describe "Crack::Util.to_xml_attributes" do
|
4
|
+
before do
|
5
|
+
@hash = { :one => "ONE", "two" => "TWO", :three => "it \"should\" work" }
|
6
|
+
end
|
8
7
|
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
8
|
+
it "turn the hash into xml attributes" do
|
9
|
+
attrs = Crack::Util.to_xml_attributes(@hash)
|
10
|
+
attrs.must_match /one="ONE"/m
|
11
|
+
attrs.must_match /two="TWO"/m
|
12
|
+
attrs.must_match /three="it "should" work"/m
|
13
|
+
end
|
15
14
|
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
15
|
+
it "preserve _ in hash keys" do
|
16
|
+
attrs = Crack::Util.to_xml_attributes({
|
17
|
+
:some_long_attribute => "with short value",
|
18
|
+
:crash => :burn,
|
19
|
+
:merb => "uses extlib"
|
20
|
+
})
|
22
21
|
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
end
|
22
|
+
attrs.must_match /some_long_attribute="with short value"/
|
23
|
+
attrs.must_match /merb="uses extlib"/
|
24
|
+
attrs.must_match /crash="burn"/
|
27
25
|
end
|
28
26
|
end
|
data/test/json_test.rb
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
# coding: utf-8
|
2
2
|
require 'test_helper'
|
3
3
|
|
4
|
-
|
4
|
+
describe "JSON Parsing" do
|
5
5
|
TESTS = {
|
6
6
|
%q({"data": "G\u00fcnter"}) => {"data" => "Günter"},
|
7
7
|
%q({"html": "\u003Cdiv\\u003E"}) => {"html" => "<div>"},
|
@@ -11,14 +11,14 @@ class JsonTest < Test::Unit::TestCase
|
|
11
11
|
%q({"returnTo":{"\/categories":1}}) => {"returnTo" => {"/categories" => 1}},
|
12
12
|
%({"returnTo":[1,"a"]}) => {"returnTo" => [1, "a"]},
|
13
13
|
%({"returnTo":[1,"\\"a\\",", "b"]}) => {"returnTo" => [1, "\"a\",", "b"]},
|
14
|
-
%({a: "'", "b": "5,000"})
|
15
|
-
%({a: "a's, b's and c's", "b": "5,000"})
|
16
|
-
%({a: "2007-01-01"})
|
17
|
-
%({a: "2007-01-01 01:12:34 Z"})
|
14
|
+
%({"a": "'", "b": "5,000"}) => {"a" => "'", "b" => "5,000"},
|
15
|
+
%({"a": "a's, b's and c's", "b": "5,000"}) => {"a" => "a's, b's and c's", "b" => "5,000"},
|
16
|
+
%({"a": "2007-01-01"}) => {'a' => Date.new(2007, 1, 1)},
|
17
|
+
%({"a": "2007-01-01 01:12:34 Z"}) => {'a' => Time.utc(2007, 1, 1, 1, 12, 34)},
|
18
18
|
# Handle ISO 8601 date/time format http://en.wikipedia.org/wiki/ISO_8601
|
19
|
-
%({a: "2007-01-01T01:12:34Z"})
|
19
|
+
%({"a": "2007-01-01T01:12:34Z"}) => {'a' => Time.utc(2007, 1, 1, 1, 12, 34)},
|
20
20
|
# no time zone
|
21
|
-
%({a: "2007-01-01 01:12:34"})
|
21
|
+
%({"a": "2007-01-01 01:12:34"}) => {'a' => "2007-01-01 01:12:34"},
|
22
22
|
%({"bio": "1985-01-29: birthdate"}) => {'bio' => '1985-01-29: birthdate'},
|
23
23
|
%({"regex": /foo.*/}) => {'regex' => /foo.*/},
|
24
24
|
%({"regex": /foo.*/i}) => {'regex' => /foo.*/i},
|
@@ -42,41 +42,34 @@ class JsonTest < Test::Unit::TestCase
|
|
42
42
|
%q({"foo":"bar\x00"}) => {"foo" => "bar\x00"},
|
43
43
|
%q({"foo":"bar\x00baz"}) => {"foo" => "bar\x00baz"}
|
44
44
|
}
|
45
|
-
|
45
|
+
|
46
46
|
TESTS.each do |json, expected|
|
47
|
-
|
48
|
-
|
49
|
-
Crack::JSON.parse(json).should == expected
|
50
|
-
}.should_not raise_error
|
47
|
+
it "decode json (#{json})" do
|
48
|
+
Crack::JSON.parse(json).must_equal expected
|
51
49
|
end
|
52
50
|
end
|
53
51
|
|
54
|
-
|
55
|
-
|
52
|
+
it "raise error for failed decoding" do
|
53
|
+
assert_raises(Crack::ParseError) {
|
56
54
|
Crack::JSON.parse(%({: 1}))
|
57
|
-
}
|
55
|
+
}
|
58
56
|
end
|
59
|
-
|
60
|
-
|
57
|
+
|
58
|
+
it "be able to parse a JSON response from a Twitter search about 'firefox'" do
|
61
59
|
data = ''
|
62
60
|
File.open(File.dirname(__FILE__) + "/data/twittersearch-firefox.json", "r") { |f|
|
63
61
|
data = f.read
|
64
62
|
}
|
65
|
-
|
66
|
-
|
67
|
-
Crack::JSON.parse(data)
|
68
|
-
}.should_not raise_error(Crack::ParseError)
|
63
|
+
|
64
|
+
Crack::JSON.parse(data)
|
69
65
|
end
|
70
66
|
|
71
|
-
|
67
|
+
it "be able to parse a JSON response from a Twitter search about 'internet explorer'" do
|
72
68
|
data = ''
|
73
69
|
File.open(File.dirname(__FILE__) + "/data/twittersearch-ie.json", "r") { |f|
|
74
70
|
data = f.read
|
75
71
|
}
|
76
|
-
|
77
|
-
lambda {
|
78
|
-
Crack::JSON.parse(data)
|
79
|
-
}.should_not raise_error(Crack::ParseError)
|
80
|
-
end
|
81
72
|
|
73
|
+
Crack::JSON.parse(data)
|
74
|
+
end
|
82
75
|
end
|
data/test/parser_test.rb
CHANGED
@@ -1,26 +1,26 @@
|
|
1
1
|
require 'test_helper'
|
2
2
|
|
3
|
-
|
4
|
-
|
5
|
-
Crack::XML.parser.
|
3
|
+
describe Crack::XML do
|
4
|
+
it "default to REXMLParser" do
|
5
|
+
Crack::XML.parser.must_equal Crack::REXMLParser
|
6
6
|
end
|
7
7
|
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
8
|
+
describe "with a custom Parser" do
|
9
|
+
class CustomParser
|
10
|
+
def self.parse(xml)
|
11
|
+
xml
|
12
|
+
end
|
13
|
+
end
|
14
14
|
|
15
|
-
|
15
|
+
before do
|
16
16
|
Crack::XML.parser = CustomParser
|
17
17
|
end
|
18
18
|
|
19
|
-
|
20
|
-
|
19
|
+
it "use the custom Parser" do
|
20
|
+
Crack::XML.parse("<xml/>").must_equal "<xml/>"
|
21
21
|
end
|
22
22
|
|
23
|
-
|
23
|
+
after do
|
24
24
|
Crack::XML.parser = nil
|
25
25
|
end
|
26
26
|
end
|
data/test/string_test.rb
CHANGED
@@ -1,31 +1,31 @@
|
|
1
1
|
require 'test_helper'
|
2
2
|
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
Crack::Util.snake_case("Merb").
|
3
|
+
describe Crack::Util do
|
4
|
+
describe "snake_case" do
|
5
|
+
it "lowercases one word CamelCase" do
|
6
|
+
Crack::Util.snake_case("Merb").must_equal "merb"
|
7
7
|
end
|
8
8
|
|
9
|
-
|
10
|
-
Crack::Util.snake_case("MerbCore").
|
9
|
+
it "makes one underscore snake_case two word CamelCase" do
|
10
|
+
Crack::Util.snake_case("MerbCore").must_equal "merb_core"
|
11
11
|
end
|
12
12
|
|
13
|
-
|
14
|
-
Crack::Util.snake_case("SoYouWantContributeToMerbCore").
|
13
|
+
it "handles CamelCase with more than 2 words" do
|
14
|
+
Crack::Util.snake_case("SoYouWantContributeToMerbCore").must_equal "so_you_want_contribute_to_merb_core"
|
15
15
|
end
|
16
16
|
|
17
|
-
|
18
|
-
Crack::Util.snake_case("CNN").
|
19
|
-
Crack::Util.snake_case("CNNNews").
|
20
|
-
Crack::Util.snake_case("HeadlineCNNNews").
|
17
|
+
it "handles CamelCase with more than 2 capital letter in a row" do
|
18
|
+
Crack::Util.snake_case("CNN").must_equal "cnn"
|
19
|
+
Crack::Util.snake_case("CNNNews").must_equal "cnn_news"
|
20
|
+
Crack::Util.snake_case("HeadlineCNNNews").must_equal "headline_cnn_news"
|
21
21
|
end
|
22
22
|
|
23
|
-
|
24
|
-
Crack::Util.snake_case("merb").
|
23
|
+
it "does NOT change one word lowercase" do
|
24
|
+
Crack::Util.snake_case("merb").must_equal "merb"
|
25
25
|
end
|
26
26
|
|
27
|
-
|
28
|
-
Crack::Util.snake_case("merb_core").
|
27
|
+
it "leaves snake_case as is" do
|
28
|
+
Crack::Util.snake_case("merb_core").must_equal "merb_core"
|
29
29
|
end
|
30
30
|
end
|
31
|
-
end
|
31
|
+
end
|
data/test/test_helper.rb
CHANGED
@@ -1,12 +1,3 @@
|
|
1
|
-
require '
|
2
|
-
require '
|
3
|
-
require 'shoulda'
|
4
|
-
gem 'jnunemaker-matchy', '>= 0.4.0'
|
5
|
-
require 'matchy'
|
6
|
-
|
7
|
-
$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
|
8
|
-
$LOAD_PATH.unshift(File.dirname(__FILE__))
|
1
|
+
require 'pp'
|
2
|
+
require 'minitest/autorun'
|
9
3
|
require 'crack'
|
10
|
-
|
11
|
-
class Test::Unit::TestCase
|
12
|
-
end
|
data/test/xml_test.rb
CHANGED
@@ -1,12 +1,12 @@
|
|
1
1
|
require 'test_helper'
|
2
2
|
|
3
|
-
|
4
|
-
|
3
|
+
describe Crack::XML do
|
4
|
+
it "should transform a simple tag with content" do
|
5
5
|
xml = "<tag>This is the contents</tag>"
|
6
|
-
Crack::XML.parse(xml).
|
6
|
+
Crack::XML.parse(xml).must_equal({ 'tag' => 'This is the contents' })
|
7
7
|
end
|
8
8
|
|
9
|
-
|
9
|
+
it "should work with cdata tags" do
|
10
10
|
xml = <<-END
|
11
11
|
<tag>
|
12
12
|
<![CDATA[
|
@@ -14,16 +14,16 @@ class XmlTest < Test::Unit::TestCase
|
|
14
14
|
]]>
|
15
15
|
</tag>
|
16
16
|
END
|
17
|
-
Crack::XML.parse(xml)["tag"].strip.
|
17
|
+
Crack::XML.parse(xml)["tag"].strip.must_equal "text inside cdata"
|
18
18
|
end
|
19
19
|
|
20
|
-
|
20
|
+
it "should transform a simple tag with attributes" do
|
21
21
|
xml = "<tag attr1='1' attr2='2'></tag>"
|
22
22
|
hash = { 'tag' => { 'attr1' => '1', 'attr2' => '2' } }
|
23
|
-
Crack::XML.parse(xml).
|
23
|
+
Crack::XML.parse(xml).must_equal hash
|
24
24
|
end
|
25
25
|
|
26
|
-
|
26
|
+
it "should transform repeating siblings into an array" do
|
27
27
|
xml =<<-XML
|
28
28
|
<opt>
|
29
29
|
<user login="grep" fullname="Gary R Epstein" />
|
@@ -31,7 +31,7 @@ class XmlTest < Test::Unit::TestCase
|
|
31
31
|
</opt>
|
32
32
|
XML
|
33
33
|
|
34
|
-
Crack::XML.parse(xml)['opt']['user'].class.
|
34
|
+
Crack::XML.parse(xml)['opt']['user'].class.must_equal Array
|
35
35
|
|
36
36
|
hash = {
|
37
37
|
'opt' => {
|
@@ -45,17 +45,17 @@ class XmlTest < Test::Unit::TestCase
|
|
45
45
|
}
|
46
46
|
}
|
47
47
|
|
48
|
-
Crack::XML.parse(xml).
|
48
|
+
Crack::XML.parse(xml).must_equal hash
|
49
49
|
end
|
50
50
|
|
51
|
-
|
51
|
+
it "should not transform non-repeating siblings into an array" do
|
52
52
|
xml =<<-XML
|
53
53
|
<opt>
|
54
54
|
<user login="grep" fullname="Gary R Epstein" />
|
55
55
|
</opt>
|
56
56
|
XML
|
57
57
|
|
58
|
-
Crack::XML.parse(xml)['opt']['user'].class.
|
58
|
+
Crack::XML.parse(xml)['opt']['user'].class.must_equal Hash
|
59
59
|
|
60
60
|
hash = {
|
61
61
|
'opt' => {
|
@@ -66,11 +66,11 @@ class XmlTest < Test::Unit::TestCase
|
|
66
66
|
}
|
67
67
|
}
|
68
68
|
|
69
|
-
Crack::XML.parse(xml).
|
69
|
+
Crack::XML.parse(xml).must_equal hash
|
70
70
|
end
|
71
71
|
|
72
|
-
|
73
|
-
|
72
|
+
describe "Parsing xml with text and attributes" do
|
73
|
+
before do
|
74
74
|
xml =<<-XML
|
75
75
|
<opt>
|
76
76
|
<user login="grep">Gary R Epstein</user>
|
@@ -80,60 +80,60 @@ class XmlTest < Test::Unit::TestCase
|
|
80
80
|
@data = Crack::XML.parse(xml)
|
81
81
|
end
|
82
82
|
|
83
|
-
|
84
|
-
@data.
|
83
|
+
it "correctly parse text nodes" do
|
84
|
+
@data.must_equal({
|
85
85
|
'opt' => {
|
86
86
|
'user' => [
|
87
87
|
'Gary R Epstein',
|
88
88
|
'Simon T Tyson'
|
89
89
|
]
|
90
90
|
}
|
91
|
-
}
|
91
|
+
})
|
92
92
|
end
|
93
93
|
|
94
|
-
|
95
|
-
@data['opt']['user'][0].attributes.
|
94
|
+
it "be parse attributes for text node if present" do
|
95
|
+
@data['opt']['user'][0].attributes.must_equal({'login' => 'grep'})
|
96
96
|
end
|
97
97
|
|
98
|
-
|
99
|
-
@data['opt']['user'][1].attributes.
|
98
|
+
it "default attributes to empty hash if not present" do
|
99
|
+
@data['opt']['user'][1].attributes.must_equal({})
|
100
100
|
end
|
101
101
|
|
102
|
-
|
103
|
-
@data['opt']['user'][0].respond_to?(:attributes).
|
104
|
-
@data['opt']['user'][0].respond_to?(:attributes=).
|
102
|
+
it "add 'attributes' accessor methods to parsed instances of String" do
|
103
|
+
@data['opt']['user'][0].respond_to?(:attributes).must_equal(true)
|
104
|
+
@data['opt']['user'][0].respond_to?(:attributes=).must_equal(true)
|
105
105
|
end
|
106
106
|
|
107
|
-
|
108
|
-
"some-string".respond_to?(:attributes).
|
109
|
-
"some-string".respond_to?(:attributes=).
|
107
|
+
it "not add 'attributes' accessor methods to all instances of String" do
|
108
|
+
"some-string".respond_to?(:attributes).must_equal(false)
|
109
|
+
"some-string".respond_to?(:attributes=).must_equal(false)
|
110
110
|
end
|
111
111
|
end
|
112
112
|
|
113
|
-
|
113
|
+
it "should typecast an integer" do
|
114
114
|
xml = "<tag type='integer'>10</tag>"
|
115
|
-
Crack::XML.parse(xml)['tag'].
|
115
|
+
Crack::XML.parse(xml)['tag'].must_equal 10
|
116
116
|
end
|
117
117
|
|
118
|
-
|
118
|
+
it "should typecast a true boolean" do
|
119
119
|
xml = "<tag type='boolean'>true</tag>"
|
120
|
-
Crack::XML.parse(xml)['tag'].
|
120
|
+
Crack::XML.parse(xml)['tag'].must_equal(true)
|
121
121
|
end
|
122
122
|
|
123
|
-
|
123
|
+
it "should typecast a false boolean" do
|
124
124
|
["false"].each do |w|
|
125
|
-
Crack::XML.parse("<tag type='boolean'>#{w}</tag>")['tag'].
|
125
|
+
Crack::XML.parse("<tag type='boolean'>#{w}</tag>")['tag'].must_equal(false)
|
126
126
|
end
|
127
127
|
end
|
128
128
|
|
129
|
-
|
129
|
+
it "should typecast a datetime" do
|
130
130
|
xml = "<tag type='datetime'>2007-12-31 10:32</tag>"
|
131
|
-
Crack::XML.parse(xml)['tag'].
|
131
|
+
Crack::XML.parse(xml)['tag'].must_equal Time.parse( '2007-12-31 10:32' ).utc
|
132
132
|
end
|
133
133
|
|
134
|
-
|
134
|
+
it "should typecast a date" do
|
135
135
|
xml = "<tag type='date'>2007-12-31</tag>"
|
136
|
-
Crack::XML.parse(xml)['tag'].
|
136
|
+
Crack::XML.parse(xml)['tag'].must_equal Date.parse('2007-12-31')
|
137
137
|
end
|
138
138
|
|
139
139
|
xml_entities = {
|
@@ -143,57 +143,57 @@ class XmlTest < Test::Unit::TestCase
|
|
143
143
|
"'" => "'",
|
144
144
|
"&" => "&"
|
145
145
|
}
|
146
|
-
|
146
|
+
it "should unescape html entities" do
|
147
147
|
xml_entities.each do |k,v|
|
148
148
|
xml = "<tag>Some content #{v}</tag>"
|
149
|
-
Crack::XML.parse(xml)['tag'].
|
149
|
+
Crack::XML.parse(xml)['tag'].must_match Regexp.new(k)
|
150
150
|
end
|
151
151
|
end
|
152
152
|
|
153
|
-
|
153
|
+
it "should unescape XML entities in attributes" do
|
154
154
|
xml_entities.each do |k,v|
|
155
155
|
xml = "<tag attr='Some content #{v}'></tag>"
|
156
|
-
Crack::XML.parse(xml)['tag']['attr'].
|
156
|
+
Crack::XML.parse(xml)['tag']['attr'].must_match Regexp.new(k)
|
157
157
|
end
|
158
158
|
end
|
159
159
|
|
160
|
-
|
160
|
+
it "should undasherize keys as tags" do
|
161
161
|
xml = "<tag-1>Stuff</tag-1>"
|
162
|
-
Crack::XML.parse(xml).keys.
|
162
|
+
Crack::XML.parse(xml).keys.must_include( 'tag_1' )
|
163
163
|
end
|
164
164
|
|
165
|
-
|
165
|
+
it "should undasherize keys as attributes" do
|
166
166
|
xml = "<tag1 attr-1='1'></tag1>"
|
167
|
-
Crack::XML.parse(xml)['tag1'].keys.
|
167
|
+
Crack::XML.parse(xml)['tag1'].keys.must_include( 'attr_1')
|
168
168
|
end
|
169
169
|
|
170
|
-
|
170
|
+
it "should undasherize keys as tags and attributes" do
|
171
171
|
xml = "<tag-1 attr-1='1'></tag-1>"
|
172
|
-
Crack::XML.parse(xml).keys.
|
173
|
-
Crack::XML.parse(xml)['tag_1'].keys.
|
172
|
+
Crack::XML.parse(xml).keys.must_include( 'tag_1' )
|
173
|
+
Crack::XML.parse(xml)['tag_1'].keys.must_include( 'attr_1')
|
174
174
|
end
|
175
175
|
|
176
|
-
|
176
|
+
it "should render nested content correctly" do
|
177
177
|
xml = "<root><tag1>Tag1 Content <em><strong>This is strong</strong></em></tag1></root>"
|
178
|
-
Crack::XML.parse(xml)['root']['tag1'].
|
178
|
+
Crack::XML.parse(xml)['root']['tag1'].must_equal "Tag1 Content <em><strong>This is strong</strong></em>"
|
179
179
|
end
|
180
180
|
|
181
|
-
|
181
|
+
it "should render nested content with splshould text nodes correctly" do
|
182
182
|
xml = "<root>Tag1 Content<em>Stuff</em> Hi There</root>"
|
183
|
-
Crack::XML.parse(xml)['root'].
|
183
|
+
Crack::XML.parse(xml)['root'].must_equal "Tag1 Content<em>Stuff</em> Hi There"
|
184
184
|
end
|
185
185
|
|
186
|
-
|
186
|
+
it "should ignore attributes when a child is a text node" do
|
187
187
|
xml = "<root attr1='1'>Stuff</root>"
|
188
|
-
Crack::XML.parse(xml).
|
188
|
+
Crack::XML.parse(xml).must_equal({ "root" => "Stuff" })
|
189
189
|
end
|
190
190
|
|
191
|
-
|
191
|
+
it "should ignore attributes when any child is a text node" do
|
192
192
|
xml = "<root attr1='1'>Stuff <em>in italics</em></root>"
|
193
|
-
Crack::XML.parse(xml).
|
193
|
+
Crack::XML.parse(xml).must_equal({ "root" => "Stuff <em>in italics</em>" })
|
194
194
|
end
|
195
195
|
|
196
|
-
|
196
|
+
it "should correctly transform multiple children" do
|
197
197
|
xml = <<-XML
|
198
198
|
<user gender='m'>
|
199
199
|
<age type='integer'>35</age>
|
@@ -215,10 +215,10 @@ class XmlTest < Test::Unit::TestCase
|
|
215
215
|
}
|
216
216
|
}
|
217
217
|
|
218
|
-
Crack::XML.parse(xml).
|
218
|
+
Crack::XML.parse(xml).must_equal hash
|
219
219
|
end
|
220
220
|
|
221
|
-
|
221
|
+
it "should properly handle nil values (ActiveSupport Compatible)" do
|
222
222
|
topic_xml = <<-EOT
|
223
223
|
<topic>
|
224
224
|
<title></title>
|
@@ -238,10 +238,10 @@ class XmlTest < Test::Unit::TestCase
|
|
238
238
|
'viewed_at' => nil,
|
239
239
|
'parent_id' => nil
|
240
240
|
}
|
241
|
-
Crack::XML.parse(topic_xml)["topic"].
|
241
|
+
Crack::XML.parse(topic_xml)["topic"].must_equal expected_topic_hash
|
242
242
|
end
|
243
243
|
|
244
|
-
|
244
|
+
it "should handle a single record from xml (ActiveSupport Compatible)" do
|
245
245
|
topic_xml = <<-EOT
|
246
246
|
<topic>
|
247
247
|
<title>The First Topic</title>
|
@@ -277,11 +277,11 @@ class XmlTest < Test::Unit::TestCase
|
|
277
277
|
}
|
278
278
|
|
279
279
|
Crack::XML.parse(topic_xml)["topic"].each do |k,v|
|
280
|
-
v.
|
280
|
+
v.must_equal expected_topic_hash[k]
|
281
281
|
end
|
282
282
|
end
|
283
283
|
|
284
|
-
|
284
|
+
it "should handle multiple records (ActiveSupport Compatible)" do
|
285
285
|
topics_xml = <<-EOT
|
286
286
|
<topics type="array">
|
287
287
|
<topic>
|
@@ -328,11 +328,11 @@ class XmlTest < Test::Unit::TestCase
|
|
328
328
|
}
|
329
329
|
# puts Crack::XML.parse(topics_xml)['topics'].first.inspect
|
330
330
|
Crack::XML.parse(topics_xml)["topics"].first.each do |k,v|
|
331
|
-
v.
|
331
|
+
v.must_equal expected_topic_hash[k]
|
332
332
|
end
|
333
333
|
end
|
334
334
|
|
335
|
-
|
335
|
+
it "should handle a single record from_xml with attributes other than type (ActiveSupport Compatible)" do
|
336
336
|
topic_xml = <<-EOT
|
337
337
|
<rsp stat="ok">
|
338
338
|
<photos page="1" pages="1" perpage="100" total="16">
|
@@ -352,21 +352,21 @@ class XmlTest < Test::Unit::TestCase
|
|
352
352
|
'isfamily' => "0",
|
353
353
|
}
|
354
354
|
Crack::XML.parse(topic_xml)["rsp"]["photos"]["photo"].each do |k,v|
|
355
|
-
v.
|
355
|
+
v.must_equal expected_topic_hash[k]
|
356
356
|
end
|
357
357
|
end
|
358
358
|
|
359
|
-
|
359
|
+
it "should handle an emtpy array (ActiveSupport Compatible)" do
|
360
360
|
blog_xml = <<-XML
|
361
361
|
<blog>
|
362
362
|
<posts type="array"></posts>
|
363
363
|
</blog>
|
364
364
|
XML
|
365
365
|
expected_blog_hash = {"blog" => {"posts" => []}}
|
366
|
-
Crack::XML.parse(blog_xml).
|
366
|
+
Crack::XML.parse(blog_xml).must_equal expected_blog_hash
|
367
367
|
end
|
368
368
|
|
369
|
-
|
369
|
+
it "should handle empty array with whitespace from xml (ActiveSupport Compatible)" do
|
370
370
|
blog_xml = <<-XML
|
371
371
|
<blog>
|
372
372
|
<posts type="array">
|
@@ -374,10 +374,10 @@ class XmlTest < Test::Unit::TestCase
|
|
374
374
|
</blog>
|
375
375
|
XML
|
376
376
|
expected_blog_hash = {"blog" => {"posts" => []}}
|
377
|
-
Crack::XML.parse(blog_xml).
|
377
|
+
Crack::XML.parse(blog_xml).must_equal expected_blog_hash
|
378
378
|
end
|
379
379
|
|
380
|
-
|
380
|
+
it "should handle array with one entry from_xml (ActiveSupport Compatible)" do
|
381
381
|
blog_xml = <<-XML
|
382
382
|
<blog>
|
383
383
|
<posts type="array">
|
@@ -386,10 +386,10 @@ class XmlTest < Test::Unit::TestCase
|
|
386
386
|
</blog>
|
387
387
|
XML
|
388
388
|
expected_blog_hash = {"blog" => {"posts" => ["a post"]}}
|
389
|
-
Crack::XML.parse(blog_xml).
|
389
|
+
Crack::XML.parse(blog_xml).must_equal expected_blog_hash
|
390
390
|
end
|
391
391
|
|
392
|
-
|
392
|
+
it "should handle array with multiple entries from xml (ActiveSupport Compatible)" do
|
393
393
|
blog_xml = <<-XML
|
394
394
|
<blog>
|
395
395
|
<posts type="array">
|
@@ -399,10 +399,10 @@ class XmlTest < Test::Unit::TestCase
|
|
399
399
|
</blog>
|
400
400
|
XML
|
401
401
|
expected_blog_hash = {"blog" => {"posts" => ["a post", "another post"]}}
|
402
|
-
Crack::XML.parse(blog_xml).
|
402
|
+
Crack::XML.parse(blog_xml).must_equal expected_blog_hash
|
403
403
|
end
|
404
404
|
|
405
|
-
|
405
|
+
it "should handle file types (ActiveSupport Compatible)" do
|
406
406
|
blog_xml = <<-XML
|
407
407
|
<blog>
|
408
408
|
<logo type="file" name="logo.png" content_type="image/png">
|
@@ -410,15 +410,15 @@ class XmlTest < Test::Unit::TestCase
|
|
410
410
|
</blog>
|
411
411
|
XML
|
412
412
|
hash = Crack::XML.parse(blog_xml)
|
413
|
-
hash.keys.
|
414
|
-
hash['blog'].keys.
|
413
|
+
hash.keys.must_include('blog')
|
414
|
+
hash['blog'].keys.must_include('logo')
|
415
415
|
|
416
416
|
file = hash['blog']['logo']
|
417
|
-
file.original_filename.
|
418
|
-
file.content_type.
|
417
|
+
file.original_filename.must_equal 'logo.png'
|
418
|
+
file.content_type.must_equal 'image/png'
|
419
419
|
end
|
420
420
|
|
421
|
-
|
421
|
+
it "should handle file from xml with defaults (ActiveSupport Compatible)" do
|
422
422
|
blog_xml = <<-XML
|
423
423
|
<blog>
|
424
424
|
<logo type="file">
|
@@ -426,11 +426,11 @@ class XmlTest < Test::Unit::TestCase
|
|
426
426
|
</blog>
|
427
427
|
XML
|
428
428
|
file = Crack::XML.parse(blog_xml)['blog']['logo']
|
429
|
-
file.original_filename.
|
430
|
-
file.content_type.
|
429
|
+
file.original_filename.must_equal 'untitled'
|
430
|
+
file.content_type.must_equal 'application/octet-stream'
|
431
431
|
end
|
432
432
|
|
433
|
-
|
433
|
+
it "should handle xsd like types from xml (ActiveSupport Compatible)" do
|
434
434
|
bacon_xml = <<-EOT
|
435
435
|
<bacon>
|
436
436
|
<weight type="double">0.5</weight>
|
@@ -451,10 +451,10 @@ class XmlTest < Test::Unit::TestCase
|
|
451
451
|
'illustration' => "babe.png"
|
452
452
|
}
|
453
453
|
|
454
|
-
Crack::XML.parse(bacon_xml)["bacon"].
|
454
|
+
Crack::XML.parse(bacon_xml)["bacon"].must_equal expected_bacon_hash
|
455
455
|
end
|
456
456
|
|
457
|
-
|
457
|
+
it "should let type trickle through when unknown (ActiveSupport Compatible)" do
|
458
458
|
product_xml = <<-EOT
|
459
459
|
<product>
|
460
460
|
<weight type="double">0.5</weight>
|
@@ -468,25 +468,47 @@ class XmlTest < Test::Unit::TestCase
|
|
468
468
|
'image' => {'type' => 'ProductImage', 'filename' => 'image.gif' },
|
469
469
|
}
|
470
470
|
|
471
|
-
Crack::XML.parse(product_xml)["product"].
|
471
|
+
Crack::XML.parse(product_xml)["product"].must_equal expected_product_hash
|
472
472
|
end
|
473
473
|
|
474
|
-
|
474
|
+
it "should handle unescaping from xml (ActiveResource Compatible)" do
|
475
475
|
xml_string = '<person><bare-string>First & Last Name</bare-string><pre-escaped-string>First &amp; Last Name</pre-escaped-string></person>'
|
476
476
|
expected_hash = {
|
477
477
|
'bare_string' => 'First & Last Name',
|
478
478
|
'pre_escaped_string' => 'First & Last Name'
|
479
479
|
}
|
480
480
|
|
481
|
-
Crack::XML.parse(xml_string)['person'].
|
481
|
+
Crack::XML.parse(xml_string)['person'].must_equal expected_hash
|
482
482
|
end
|
483
483
|
|
484
|
-
|
485
|
-
Crack::XML.parse('').
|
484
|
+
it "handle an empty xml string" do
|
485
|
+
Crack::XML.parse('').must_equal({})
|
486
486
|
end
|
487
487
|
|
488
488
|
# As returned in the response body by the unfuddle XML API when creating objects
|
489
|
-
|
490
|
-
Crack::XML.parse(' ').
|
489
|
+
it "handle an xml string containing a single space" do
|
490
|
+
Crack::XML.parse(' ').must_equal({})
|
491
|
+
end
|
492
|
+
|
493
|
+
it "can dump parsed xml" do
|
494
|
+
xml = <<-XML
|
495
|
+
<blog>
|
496
|
+
<posts language="english">I like big butts and I cannot Lie</posts>
|
497
|
+
</blog>
|
498
|
+
XML
|
499
|
+
|
500
|
+
Marshal.dump(Crack::XML.parse(xml))
|
501
|
+
end
|
502
|
+
|
503
|
+
it "properly handles a node with type == file that has children" do
|
504
|
+
# Example is an excerpt from a problematic kvm domain config file
|
505
|
+
example_xml = <<-EOT
|
506
|
+
<disk type='file' device='cdrom'>
|
507
|
+
<driver name='qemu' type='raw' cache='none' io='native'/>
|
508
|
+
<source file='/tmp/cdrom.iso'/>
|
509
|
+
</disk>
|
510
|
+
EOT
|
511
|
+
|
512
|
+
Crack::XML.parse(example_xml).must_equal({"disk"=>{"driver"=>{"name"=>"qemu", "type"=>"raw", "cache"=>"none", "io"=>"native"}, "source"=>{"file"=>"/tmp/cdrom.iso"}, "type"=>"file", "device"=>"cdrom"}})
|
491
513
|
end
|
492
514
|
end
|
metadata
CHANGED
@@ -1,44 +1,54 @@
|
|
1
|
-
--- !ruby/object:Gem::Specification
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
2
|
name: crack
|
3
|
-
version: !ruby/object:Gem::Version
|
4
|
-
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.4.0
|
5
5
|
prerelease:
|
6
|
-
segments:
|
7
|
-
- 0
|
8
|
-
- 3
|
9
|
-
- 2
|
10
|
-
version: 0.3.2
|
11
6
|
platform: ruby
|
12
|
-
authors:
|
7
|
+
authors:
|
13
8
|
- John Nunemaker
|
14
|
-
- Wynn Netherland
|
15
9
|
autorequire:
|
16
10
|
bindir: bin
|
17
11
|
cert_chain: []
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
12
|
+
date: 2013-06-05 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: safe_yaml
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
18
|
+
requirements:
|
19
|
+
- - ~>
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: 0.9.0
|
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.9.0
|
30
|
+
description: Really simple JSON and XML parsing, ripped from Merb and Rails.
|
31
|
+
email:
|
32
|
+
- nunemaker@gmail.com
|
24
33
|
executables: []
|
25
|
-
|
26
34
|
extensions: []
|
27
|
-
|
28
|
-
|
29
|
-
-
|
30
|
-
-
|
31
|
-
|
35
|
+
extra_rdoc_files: []
|
36
|
+
files:
|
37
|
+
- .gitignore
|
38
|
+
- Gemfile
|
39
|
+
- Gemfile.lock
|
32
40
|
- History
|
33
41
|
- LICENSE
|
34
|
-
- README.
|
35
|
-
- Rakefile
|
42
|
+
- README.md
|
36
43
|
- crack.gemspec
|
37
44
|
- lib/crack.rb
|
38
45
|
- lib/crack/json.rb
|
39
46
|
- lib/crack/util.rb
|
47
|
+
- lib/crack/version.rb
|
40
48
|
- lib/crack/xml.rb
|
41
|
-
-
|
49
|
+
- script/bootstrap
|
50
|
+
- script/release
|
51
|
+
- script/test
|
42
52
|
- test/data/twittersearch-firefox.json
|
43
53
|
- test/data/twittersearch-ie.json
|
44
54
|
- test/hash_test.rb
|
@@ -48,37 +58,36 @@ files:
|
|
48
58
|
- test/test_helper.rb
|
49
59
|
- test/xml_test.rb
|
50
60
|
homepage: http://github.com/jnunemaker/crack
|
51
|
-
licenses:
|
52
|
-
|
61
|
+
licenses:
|
62
|
+
- MIT
|
53
63
|
post_install_message:
|
54
64
|
rdoc_options: []
|
55
|
-
|
56
|
-
require_paths:
|
65
|
+
require_paths:
|
57
66
|
- lib
|
58
|
-
required_ruby_version: !ruby/object:Gem::Requirement
|
67
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
59
68
|
none: false
|
60
|
-
requirements:
|
61
|
-
- -
|
62
|
-
- !ruby/object:Gem::Version
|
63
|
-
|
64
|
-
|
65
|
-
- 0
|
66
|
-
version: "0"
|
67
|
-
required_rubygems_version: !ruby/object:Gem::Requirement
|
69
|
+
requirements:
|
70
|
+
- - ! '>='
|
71
|
+
- !ruby/object:Gem::Version
|
72
|
+
version: '0'
|
73
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
68
74
|
none: false
|
69
|
-
requirements:
|
70
|
-
- -
|
71
|
-
- !ruby/object:Gem::Version
|
72
|
-
|
73
|
-
segments:
|
74
|
-
- 0
|
75
|
-
version: "0"
|
75
|
+
requirements:
|
76
|
+
- - ! '>='
|
77
|
+
- !ruby/object:Gem::Version
|
78
|
+
version: '0'
|
76
79
|
requirements: []
|
77
|
-
|
78
|
-
|
79
|
-
rubygems_version: 1.8.10
|
80
|
+
rubyforge_project:
|
81
|
+
rubygems_version: 1.8.23
|
80
82
|
signing_key:
|
81
83
|
specification_version: 3
|
82
84
|
summary: Really simple JSON and XML parsing, ripped from Merb and Rails.
|
83
|
-
test_files:
|
84
|
-
|
85
|
+
test_files:
|
86
|
+
- test/data/twittersearch-firefox.json
|
87
|
+
- test/data/twittersearch-ie.json
|
88
|
+
- test/hash_test.rb
|
89
|
+
- test/json_test.rb
|
90
|
+
- test/parser_test.rb
|
91
|
+
- test/string_test.rb
|
92
|
+
- test/test_helper.rb
|
93
|
+
- test/xml_test.rb
|
data/README.rdoc
DELETED
@@ -1,42 +0,0 @@
|
|
1
|
-
= crack
|
2
|
-
|
3
|
-
Really simple JSON and XML parsing, ripped from Merb and Rails. The XML parser is ripped from Merb and the JSON parser is ripped from Rails. I take no credit, just packaged them for all to enjoy and easily use.
|
4
|
-
|
5
|
-
== note on releases
|
6
|
-
|
7
|
-
Releases are tagged on github and also released as gems on github and rubyforge. Master is pushed to whenever I add a patch or a new feature. To build from master, you can clone the code, generate the updated gemspec, build the gem and install.
|
8
|
-
|
9
|
-
* rake gemspec
|
10
|
-
* gem build crack.gemspec
|
11
|
-
* gem install the gem that was built
|
12
|
-
|
13
|
-
== note on patches/pull requests
|
14
|
-
|
15
|
-
* Fork the project.
|
16
|
-
* Make your feature addition or bug fix.
|
17
|
-
* Add tests for it. This is important so I don't break it in a future version unintentionally.
|
18
|
-
* Commit, do not mess with rakefile, version, or history. (if you want to have your own version, that is fine but bump version in a commit by itself in another branch so I can ignore when I pull)
|
19
|
-
* Send me a pull request. Bonus points for topic branches.
|
20
|
-
|
21
|
-
== usage
|
22
|
-
|
23
|
-
gem 'crack'
|
24
|
-
require 'crack' # for xml and json
|
25
|
-
require 'crack/json' # for just json
|
26
|
-
require 'crack/xml' # for just xml
|
27
|
-
|
28
|
-
== examples
|
29
|
-
|
30
|
-
Crack::XML.parse("<tag>This is the contents</tag>")
|
31
|
-
# => {'tag' => 'This is the contents'}
|
32
|
-
|
33
|
-
Crack::JSON.parse('{"tag":"This is the contents"}')
|
34
|
-
# => {'tag' => 'This is the contents'}
|
35
|
-
|
36
|
-
== Copyright
|
37
|
-
|
38
|
-
Copyright (c) 2009 John Nunemaker. See LICENSE for details.
|
39
|
-
|
40
|
-
== Docs
|
41
|
-
|
42
|
-
http://rdoc.info/projects/jnunemaker/crack
|
data/Rakefile
DELETED
@@ -1,32 +0,0 @@
|
|
1
|
-
$:.unshift("lib")
|
2
|
-
require 'rubygems'
|
3
|
-
require 'rake'
|
4
|
-
|
5
|
-
$:.unshift(File.expand_path('lib', File.dirname(__FILE__)))
|
6
|
-
require 'crack'
|
7
|
-
|
8
|
-
begin
|
9
|
-
require 'jeweler'
|
10
|
-
Jeweler::Tasks.new do |gem|
|
11
|
-
gem.name = "crack"
|
12
|
-
gem.summary = %Q{Really simple JSON and XML parsing, ripped from Merb and Rails.}
|
13
|
-
gem.email = "nunemaker@gmail.com"
|
14
|
-
gem.homepage = "http://github.com/jnunemaker/crack"
|
15
|
-
gem.authors = ["John Nunemaker", "Wynn Netherland"]
|
16
|
-
gem.rubyforge_project = 'crack'
|
17
|
-
gem.version = Crack::VERSION
|
18
|
-
# gem is a Gem::Specification... see http://www.rubygems.org/read/chapter/20 for additional settings
|
19
|
-
end
|
20
|
-
Jeweler::GemcutterTasks.new
|
21
|
-
rescue LoadError
|
22
|
-
puts "Jeweler not available. Install it with: sudo gem install jeweler"
|
23
|
-
end
|
24
|
-
|
25
|
-
require 'rake/testtask'
|
26
|
-
Rake::TestTask.new(:test) do |test|
|
27
|
-
test.libs << 'lib' << 'test'
|
28
|
-
test.pattern = 'test/**/*_test.rb'
|
29
|
-
test.verbose = false
|
30
|
-
end
|
31
|
-
|
32
|
-
task :default => :test
|
data/test/crack_test.rb
DELETED