mapricot 0.0.4
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/History.txt +23 -0
- data/License.txt +19 -0
- data/README.rdoc +119 -0
- data/benchmark/benchmarks.rb +127 -0
- data/examples/facebook_api.rb +86 -0
- data/examples/lastfm_api.rb +42 -0
- data/examples/lastfm_api_no_request.rb +127 -0
- data/examples/readme_examples.rb +82 -0
- data/examples/xml_with_attributes.rb +26 -0
- data/lib/mapricot/abstract_doc.rb +119 -0
- data/lib/mapricot/associations.rb +100 -0
- data/lib/mapricot/attribute.rb +22 -0
- data/lib/mapricot/base.rb +81 -0
- data/lib/mapricot.rb +12 -0
- data/mapricot.gemspec +40 -0
- data/test/has_attribute/test_has_attribute.rb +42 -0
- data/test/has_many/test_has_many_ids.rb +55 -0
- data/test/has_many/test_has_many_nested.rb +81 -0
- data/test/has_one/test_has_one_id.rb +25 -0
- data/test/has_one/test_has_one_nested.rb +31 -0
- data/test/suite.rb +20 -0
- data/test/test_abstract_doc.rb +41 -0
- data/test/test_mapricot.rb +89 -0
- data/test/test_mapricot_readme.rb +105 -0
- metadata +123 -0
@@ -0,0 +1,119 @@
|
|
1
|
+
require 'open-uri'
|
2
|
+
require 'hpricot'
|
3
|
+
require 'libxml'
|
4
|
+
require 'nokogiri'
|
5
|
+
|
6
|
+
|
7
|
+
module Mapricot
|
8
|
+
@parser = :hpricot
|
9
|
+
class << self; attr_accessor :parser; end
|
10
|
+
|
11
|
+
# AbstractDoc should be able to find tags, get inner tag content. Find all tags (return an array)
|
12
|
+
# I think I will also need AbstractNode
|
13
|
+
|
14
|
+
class AbstractDoc
|
15
|
+
|
16
|
+
def self.from_url(url)
|
17
|
+
adoc = new
|
18
|
+
adoc.url = url
|
19
|
+
adoc
|
20
|
+
end
|
21
|
+
|
22
|
+
def self.from_string(string)
|
23
|
+
adoc = new
|
24
|
+
adoc.string = string
|
25
|
+
adoc
|
26
|
+
end
|
27
|
+
|
28
|
+
def url=(url)
|
29
|
+
if Mapricot.parser == :libxml
|
30
|
+
@udoc = LibXML::XML::Parser.file(url).parse
|
31
|
+
elsif Mapricot.parser == :hpricot
|
32
|
+
@udoc = Hpricot::XML(open(url))
|
33
|
+
elsif Mapricot.parser == :nokogiri
|
34
|
+
@udoc = Nokogiri::HTML(open(url))
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
def string=(string)
|
39
|
+
if Mapricot.parser == :libxml
|
40
|
+
@udoc = LibXML::XML::Parser.string(string).parse
|
41
|
+
elsif Mapricot.parser == :hpricot
|
42
|
+
@udoc = Hpricot::XML(string)
|
43
|
+
elsif Mapricot.parser == :nokogiri
|
44
|
+
@udoc = Nokogiri::XML(string)
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
|
49
|
+
def find(tagname)
|
50
|
+
if Mapricot.parser == :libxml
|
51
|
+
AbstractNodeList.new(@udoc.find("//#{tagname}")) # hmm...
|
52
|
+
elsif Mapricot.parser == :hpricot
|
53
|
+
# AbstractNodeList.new(@udoc/tagname)
|
54
|
+
AbstractNodeList.new(@udoc/"//#{tagname}")
|
55
|
+
elsif Mapricot.parser == :nokogiri
|
56
|
+
AbstractNodeList.new(@udoc.search(tagname))
|
57
|
+
# AbstractNodeList.new(@udoc.xpath("//#{tagname}"))
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
end
|
62
|
+
|
63
|
+
|
64
|
+
|
65
|
+
class AbstractNodeList
|
66
|
+
include Enumerable
|
67
|
+
|
68
|
+
def initialize(node_list)
|
69
|
+
@unode_list = node_list
|
70
|
+
end
|
71
|
+
|
72
|
+
def each(&block)
|
73
|
+
@unode_list.each {|unode| yield(AbstractNode.new(unode))}
|
74
|
+
end
|
75
|
+
|
76
|
+
def [](i)
|
77
|
+
AbstractNode.new(@unode_list[i])
|
78
|
+
end
|
79
|
+
|
80
|
+
def first
|
81
|
+
AbstractNode.new(@unode_list.first)
|
82
|
+
end
|
83
|
+
|
84
|
+
def empty?
|
85
|
+
@unode_list.empty?
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
|
90
|
+
class AbstractNode
|
91
|
+
attr_reader :unode
|
92
|
+
|
93
|
+
def initialize(unode)
|
94
|
+
@unode = unode # unresolved node
|
95
|
+
end
|
96
|
+
|
97
|
+
def to_s
|
98
|
+
@unode.to_s
|
99
|
+
end
|
100
|
+
|
101
|
+
def attributes
|
102
|
+
if Mapricot.parser != :nokogiri
|
103
|
+
@unode.attributes
|
104
|
+
else
|
105
|
+
atts = {}
|
106
|
+
@unode.attributes.each {|k,v| atts[k] = v.value}
|
107
|
+
atts
|
108
|
+
end
|
109
|
+
end
|
110
|
+
|
111
|
+
def contents
|
112
|
+
if Mapricot.parser == :libxml || Mapricot.parser == :nokogiri
|
113
|
+
@unode.content
|
114
|
+
else
|
115
|
+
@unode.inner_html
|
116
|
+
end
|
117
|
+
end
|
118
|
+
end
|
119
|
+
end
|
@@ -0,0 +1,100 @@
|
|
1
|
+
module Mapricot
|
2
|
+
# Abstract class; used to subclass HasOneAssociation and HasManyAssociation
|
3
|
+
class Association
|
4
|
+
VALID_TYPES = [:integer, :time, :xml, :string]
|
5
|
+
|
6
|
+
attr_accessor :name, :type, :value
|
7
|
+
attr_accessor :namespace
|
8
|
+
|
9
|
+
def initialize(name, type, opts = {})
|
10
|
+
raise "Don't instantiate me" if abstract_class?
|
11
|
+
@name, @type, @opts = name, type, opts
|
12
|
+
@namespace = nil
|
13
|
+
end
|
14
|
+
|
15
|
+
def tag_name
|
16
|
+
@opts[:tag_name] || singular_name
|
17
|
+
end
|
18
|
+
|
19
|
+
private
|
20
|
+
def typecast
|
21
|
+
raise "association type is invalid" unless VALID_TYPES.include?(@type)
|
22
|
+
if [:integer, :time].include?(@type)
|
23
|
+
@value = self.send("typecast_#{@type}")
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
def typecast_integer
|
28
|
+
@value.is_a?(Array) ? @value.collect {|v| v.to_i} : @value.to_i
|
29
|
+
end
|
30
|
+
|
31
|
+
# oh, forgot about this, need to add to readme
|
32
|
+
def typecast_time
|
33
|
+
if @value.is_a?(Array)
|
34
|
+
@value.collect {|v| Time.parse(v) }
|
35
|
+
else
|
36
|
+
Time.parse(@value)
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
def abstract_class?
|
41
|
+
self.class == Association
|
42
|
+
end
|
43
|
+
|
44
|
+
def singular_name
|
45
|
+
@name.to_s
|
46
|
+
end
|
47
|
+
|
48
|
+
def class_from_name
|
49
|
+
# ok, first we have to find how the class that inherited from Mapricot::Base is namespaced
|
50
|
+
# the class will an @associations class instance var, that will hold an instance of
|
51
|
+
if @namespace
|
52
|
+
"#{@namespace}::#{singular_name.classify}".constantize
|
53
|
+
else
|
54
|
+
singular_name.classify.constantize
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
def set_value_from_node_list(node_list)
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
|
63
|
+
class HasOneAssociation < Association
|
64
|
+
|
65
|
+
# pass a node list, depending on the type of association
|
66
|
+
def set_value_from_node_list(node_list)
|
67
|
+
if node_list.empty?
|
68
|
+
@value = nil
|
69
|
+
else
|
70
|
+
if @type == :xml
|
71
|
+
@value = class_from_name.new(:xml => node_list.first.to_s)
|
72
|
+
else
|
73
|
+
@value = node_list.first.contents
|
74
|
+
typecast
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
|
81
|
+
class HasManyAssociation < Association
|
82
|
+
|
83
|
+
def singular_name
|
84
|
+
"#{@name}".singularize
|
85
|
+
end
|
86
|
+
|
87
|
+
def set_value_from_node_list(node_list)
|
88
|
+
@value = []
|
89
|
+
node_list.each do |node|
|
90
|
+
if @type == :xml
|
91
|
+
@value << class_from_name.new(:xml => node.to_s)
|
92
|
+
else
|
93
|
+
@value << node.contents
|
94
|
+
end
|
95
|
+
end
|
96
|
+
typecast
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
module Mapricot
|
2
|
+
class Attribute
|
3
|
+
attr_accessor :name, :type, :value
|
4
|
+
|
5
|
+
def initialize(name, type)
|
6
|
+
@name = name
|
7
|
+
@type = type
|
8
|
+
end
|
9
|
+
|
10
|
+
def set_value_from_node(node)
|
11
|
+
@value = node.attributes[name.to_s]
|
12
|
+
typecast
|
13
|
+
end
|
14
|
+
|
15
|
+
private
|
16
|
+
def typecast
|
17
|
+
if !@value.nil? && !@value.empty? && @type == :integer
|
18
|
+
@value = @value.to_i
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,81 @@
|
|
1
|
+
module Mapricot
|
2
|
+
# Inherit from base, e.g. class Animal < Mapricot::Base
|
3
|
+
# Use either a string of xml or a url to initialize
|
4
|
+
class Base
|
5
|
+
|
6
|
+
class << self
|
7
|
+
# @associations is used to initialize instance variables
|
8
|
+
# creates a new HasOneAssociation and appends it to the @association_list
|
9
|
+
def has_one(name, type = :string, opts = {})
|
10
|
+
association = HasOneAssociation.new(name, type, opts)
|
11
|
+
if self.name.match(/::/)
|
12
|
+
association.namespace = self.name.match(/(.*)::[^:]+$/)[1]
|
13
|
+
end
|
14
|
+
association_list << association
|
15
|
+
class_eval "attr_reader :#{name}", __FILE__, __LINE__
|
16
|
+
end
|
17
|
+
|
18
|
+
# creates a new HasManyAssociation and appends it to the @association_list
|
19
|
+
def has_many(name, type = :string, opts = {})
|
20
|
+
association = HasManyAssociation.new(name, type, opts)
|
21
|
+
if self.name.match(/::/)
|
22
|
+
association.namespace = self.name.match(/(.*)::[^:]+$/)[1]
|
23
|
+
end
|
24
|
+
association_list << association
|
25
|
+
class_eval "attr_reader :#{name}", __FILE__, __LINE__
|
26
|
+
end
|
27
|
+
|
28
|
+
def has_attribute(name, type = :string)
|
29
|
+
attribute_list << Attribute.new(name, type)
|
30
|
+
class_eval "attr_reader :#{name}", __FILE__, __LINE__
|
31
|
+
end
|
32
|
+
|
33
|
+
def association_list
|
34
|
+
@association_list ||= []
|
35
|
+
end
|
36
|
+
|
37
|
+
def attribute_list
|
38
|
+
@attribute_list ||= []
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
# class SomeClass < Mapricot::Base; end;
|
43
|
+
# SomeClass.new :url => "http://some_url"
|
44
|
+
# SomeClass.new :xml => %(<hi></hi>)
|
45
|
+
# the class instance variable @association_list is duplicated in every instance of Feed, as the instance variable @associations.
|
46
|
+
# i.e. Feed.association_list is the template for feed.associations
|
47
|
+
def initialize(opts)
|
48
|
+
@doc = AbstractDoc.from_url(opts[:url]) if opts[:url]
|
49
|
+
@doc = AbstractDoc.from_string(opts[:xml]) if opts[:xml]
|
50
|
+
dup_associations_and_attributes
|
51
|
+
map_associations
|
52
|
+
map_attributes
|
53
|
+
end
|
54
|
+
|
55
|
+
def dup_associations_and_attributes
|
56
|
+
@associations = self.class.association_list.collect {|x| x.dup} # do not do this: self.class.association_list.dup
|
57
|
+
@attributes = self.class.attribute_list.collect {|x| x.dup}
|
58
|
+
end
|
59
|
+
|
60
|
+
def map_associations
|
61
|
+
@associations.each do |association|
|
62
|
+
node_list = @doc.find(association.tag_name)
|
63
|
+
association.set_value_from_node_list(node_list)
|
64
|
+
instance_variable_set("@#{association.name}", association.value)
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
def map_attributes
|
69
|
+
@attributes.each do |attribute|
|
70
|
+
node = @doc.find(tag_name).first
|
71
|
+
attribute.set_value_from_node(node)
|
72
|
+
instance_variable_set("@#{attribute.name}", attribute.value)
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
# associations and base classes both have tag_name method
|
77
|
+
def tag_name
|
78
|
+
self.class.name.downcase.match(/[^:]+$/)[0]
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
data/lib/mapricot.rb
ADDED
@@ -0,0 +1,12 @@
|
|
1
|
+
require 'active_support/inflector'
|
2
|
+
|
3
|
+
module Mapricot
|
4
|
+
VERSION = "0.0.4"
|
5
|
+
end
|
6
|
+
|
7
|
+
path = File.expand_path(File.join(File.dirname(__FILE__), 'mapricot'))
|
8
|
+
|
9
|
+
require File.join(path, 'base')
|
10
|
+
require File.join(path, 'abstract_doc')
|
11
|
+
require File.join(path, 'associations')
|
12
|
+
require File.join(path, 'attribute')
|
data/mapricot.gemspec
ADDED
@@ -0,0 +1,40 @@
|
|
1
|
+
Gem::Specification.new do |s|
|
2
|
+
s.name = "mapricot"
|
3
|
+
s.version = "0.0.4"
|
4
|
+
s.summary = "XML to object mapper"
|
5
|
+
s.email = "lzell11@gmail.com"
|
6
|
+
s.homepage = "http://github.com/lzell/mapricot"
|
7
|
+
s.description = "XML to object mapper with an interface similar to ActiveRecord associations."
|
8
|
+
s.has_rdoc = true
|
9
|
+
s.authors = ["Lou Zell"]
|
10
|
+
s.files = ["README.rdoc",
|
11
|
+
"History.txt",
|
12
|
+
"License.txt",
|
13
|
+
"mapricot.gemspec",
|
14
|
+
"examples/facebook_api.rb",
|
15
|
+
"examples/lastfm_api.rb",
|
16
|
+
"examples/lastfm_api_no_request.rb",
|
17
|
+
"examples/readme_examples.rb",
|
18
|
+
"examples/xml_with_attributes.rb",
|
19
|
+
"test/suite.rb",
|
20
|
+
"test/test_abstract_doc.rb",
|
21
|
+
"test/test_mapricot.rb",
|
22
|
+
"test/test_mapricot_readme.rb",
|
23
|
+
"test/has_attribute/test_has_attribute.rb",
|
24
|
+
"test/has_many/test_has_many_ids.rb",
|
25
|
+
"test/has_many/test_has_many_nested.rb",
|
26
|
+
"test/has_one/test_has_one_id.rb",
|
27
|
+
"test/has_one/test_has_one_nested.rb",
|
28
|
+
"lib/mapricot.rb",
|
29
|
+
"lib/mapricot/abstract_doc.rb",
|
30
|
+
"lib/mapricot/associations.rb",
|
31
|
+
"lib/mapricot/attribute.rb",
|
32
|
+
"lib/mapricot/base.rb",
|
33
|
+
"benchmark/benchmarks.rb"]
|
34
|
+
s.require_paths = ["lib"]
|
35
|
+
s.rdoc_options = ["--main", "README.rdoc", "--title", "Mapricot"]
|
36
|
+
s.extra_rdoc_files = ["README.rdoc"]
|
37
|
+
s.add_dependency("hpricot")
|
38
|
+
s.add_dependency("nokogiri")
|
39
|
+
s.add_dependency("libxml-ruby")
|
40
|
+
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
require 'test/unit'
|
2
|
+
require File.expand_path(File.join(File.dirname(__FILE__), '..', '..', 'lib', 'mapricot'))
|
3
|
+
|
4
|
+
|
5
|
+
class Response < Mapricot::Base
|
6
|
+
has_one :location, :xml
|
7
|
+
end
|
8
|
+
|
9
|
+
class Location < Mapricot::Base
|
10
|
+
has_one :city
|
11
|
+
has_one :state
|
12
|
+
has_attribute :code
|
13
|
+
has_attribute :id, :integer
|
14
|
+
end
|
15
|
+
|
16
|
+
class TestResponse < Test::Unit::TestCase
|
17
|
+
|
18
|
+
def setup
|
19
|
+
@parsers = [:hpricot, :nokogiri, :libxml]
|
20
|
+
@xml = %(
|
21
|
+
<response>
|
22
|
+
<location code='nyc' id='100'>
|
23
|
+
<city>New York</city>
|
24
|
+
<state>NY</state>
|
25
|
+
</location>
|
26
|
+
</response>
|
27
|
+
)
|
28
|
+
end
|
29
|
+
|
30
|
+
def test_response
|
31
|
+
@parsers.each do |parser|
|
32
|
+
Mapricot.parser = parser
|
33
|
+
response = Response.new(:xml => @xml)
|
34
|
+
assert_equal "New York", response.location.city
|
35
|
+
assert_equal "NY", response.location.state
|
36
|
+
assert_equal "nyc", response.location.code
|
37
|
+
assert_equal 100, response.location.id
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
end
|
42
|
+
|
@@ -0,0 +1,55 @@
|
|
1
|
+
require 'test/unit'
|
2
|
+
require File.expand_path(File.join(File.dirname(__FILE__), '..', '..', 'lib', 'mapricot'))
|
3
|
+
|
4
|
+
|
5
|
+
class ResponseWithManyIds < Mapricot::Base
|
6
|
+
has_many :ids, :integer
|
7
|
+
end
|
8
|
+
|
9
|
+
|
10
|
+
class TestResponseWithManyIds < Test::Unit::TestCase
|
11
|
+
|
12
|
+
def setup
|
13
|
+
@parsers = [:hpricot, :nokogiri, :libxml]
|
14
|
+
@xml = %(
|
15
|
+
<response>
|
16
|
+
<id>10</id>
|
17
|
+
<id>20</id>
|
18
|
+
<id>30</id>
|
19
|
+
</response>
|
20
|
+
)
|
21
|
+
end
|
22
|
+
|
23
|
+
def test_response
|
24
|
+
@parsers.each do |parser|
|
25
|
+
Mapricot.parser = parser
|
26
|
+
response = ResponseWithManyIds.new(:xml => @xml)
|
27
|
+
assert_equal 10, response.ids[0]
|
28
|
+
assert_equal 20, response.ids[1]
|
29
|
+
assert_equal 30, response.ids[2]
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
# ---------------- stop reading here ---------------- #
|
34
|
+
|
35
|
+
|
36
|
+
|
37
|
+
|
38
|
+
|
39
|
+
|
40
|
+
|
41
|
+
def test_internals
|
42
|
+
response = ResponseWithManyIds.new(:xml => @xml)
|
43
|
+
template = response.class.association_list.first
|
44
|
+
assert_equal :ids, template.name
|
45
|
+
assert_equal :integer, template.type
|
46
|
+
assert_nil template.namespace
|
47
|
+
assert_nil template.value
|
48
|
+
|
49
|
+
ass = response.instance_variable_get(:@associations).first
|
50
|
+
assert_equal :ids, ass.name
|
51
|
+
assert_equal :integer, ass.type
|
52
|
+
assert_nil ass.namespace
|
53
|
+
assert_equal [10,20,30], ass.value
|
54
|
+
end
|
55
|
+
end
|
@@ -0,0 +1,81 @@
|
|
1
|
+
require 'test/unit'
|
2
|
+
require File.expand_path(File.join(File.dirname(__FILE__), '..', '..', 'lib', 'mapricot'))
|
3
|
+
|
4
|
+
class ResponseWithNesting < Mapricot::Base
|
5
|
+
has_many :users, :xml
|
6
|
+
end
|
7
|
+
|
8
|
+
class User < Mapricot::Base
|
9
|
+
has_one :id, :integer
|
10
|
+
has_one :name
|
11
|
+
end
|
12
|
+
|
13
|
+
class TestResponseWithNesting < Test::Unit::TestCase
|
14
|
+
|
15
|
+
def setup
|
16
|
+
@parsers = [:hpricot, :nokogiri, :libxml]
|
17
|
+
@xml = %(
|
18
|
+
<response>
|
19
|
+
<user>
|
20
|
+
<id>10</id>
|
21
|
+
<name>bob</name>
|
22
|
+
</user>
|
23
|
+
<user>
|
24
|
+
<id>20</id>
|
25
|
+
<name>sally</name>
|
26
|
+
</user>
|
27
|
+
</response>
|
28
|
+
)
|
29
|
+
end
|
30
|
+
|
31
|
+
|
32
|
+
def test_response
|
33
|
+
@parsers.each do |parser|
|
34
|
+
Mapricot.parser = parser
|
35
|
+
response = ResponseWithNesting.new(:xml => @xml)
|
36
|
+
assert_equal 10, response.users[0].id
|
37
|
+
assert_equal "bob", response.users[0].name
|
38
|
+
assert_equal 20, response.users[1].id
|
39
|
+
assert_equal "sally", response.users[1].name
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
# ---------------- stop reading here ---------------- #
|
44
|
+
|
45
|
+
|
46
|
+
|
47
|
+
|
48
|
+
|
49
|
+
|
50
|
+
def test_response_internals
|
51
|
+
response = ResponseWithNesting.new(:xml => @xml)
|
52
|
+
template = response.class.association_list.first
|
53
|
+
|
54
|
+
assert_equal :users, template.name
|
55
|
+
assert_equal :xml, template.type
|
56
|
+
assert_nil template.namespace
|
57
|
+
assert_nil template.value
|
58
|
+
|
59
|
+
ass = response.instance_variable_get(:@associations).first
|
60
|
+
assert_equal :users, ass.name
|
61
|
+
assert_equal :xml, ass.type
|
62
|
+
assert_nil ass.namespace
|
63
|
+
assert_not_nil ass.value
|
64
|
+
end
|
65
|
+
|
66
|
+
def test_response_users_internals
|
67
|
+
response = ResponseWithNesting.new(:xml => @xml)
|
68
|
+
template = response.users.first.class.association_list.first
|
69
|
+
assert_equal :id, template.name
|
70
|
+
assert_equal :integer, template.type
|
71
|
+
assert_nil template.namespace
|
72
|
+
assert_nil template.value
|
73
|
+
|
74
|
+
ass = response.users.first.instance_variable_get(:@associations).first
|
75
|
+
assert_equal :id, ass.name
|
76
|
+
assert_equal :integer, ass.type
|
77
|
+
assert_nil ass.namespace
|
78
|
+
assert_equal 10, ass.value
|
79
|
+
end
|
80
|
+
|
81
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
require 'test/unit'
|
2
|
+
require File.expand_path(File.join(File.dirname(__FILE__), '..', '..', 'lib', 'mapricot'))
|
3
|
+
|
4
|
+
class ResponseWithOneId < Mapricot::Base
|
5
|
+
has_one :id, :integer
|
6
|
+
end
|
7
|
+
|
8
|
+
|
9
|
+
class TestReponseWithOneId < Test::Unit::TestCase
|
10
|
+
|
11
|
+
def setup
|
12
|
+
@parsers = [:hpricot, :nokogiri, :libxml]
|
13
|
+
@xml = %(
|
14
|
+
<id>10</id>
|
15
|
+
)
|
16
|
+
end
|
17
|
+
|
18
|
+
def test_response
|
19
|
+
@parsers.each do |parser|
|
20
|
+
Mapricot.parser = parser
|
21
|
+
response = ResponseWithOneId.new(:xml => @xml)
|
22
|
+
assert_equal 10, response.id
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
require 'test/unit'
|
2
|
+
require File.expand_path(File.join(File.dirname(__FILE__), '..', '..', 'lib', 'mapricot'))
|
3
|
+
|
4
|
+
class ResponseWithNesting < Mapricot::Base
|
5
|
+
has_one :user, :xml
|
6
|
+
end
|
7
|
+
|
8
|
+
class User < Mapricot::Base
|
9
|
+
has_one :name
|
10
|
+
end
|
11
|
+
|
12
|
+
|
13
|
+
class TestReponseWithNesting < Test::Unit::TestCase
|
14
|
+
|
15
|
+
def setup
|
16
|
+
@parsers = [:hpricot, :nokogiri, :libxml]
|
17
|
+
@xml = %(
|
18
|
+
<user>
|
19
|
+
<name>bob</name>
|
20
|
+
</user>
|
21
|
+
)
|
22
|
+
end
|
23
|
+
|
24
|
+
def test_response
|
25
|
+
@parsers.each do |parser|
|
26
|
+
Mapricot.parser = parser
|
27
|
+
response = ResponseWithNesting.new(:xml => @xml)
|
28
|
+
assert_equal "bob", response.user.name
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
data/test/suite.rb
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
# Usage:
|
2
|
+
# ruby suite.rb
|
3
|
+
# OR
|
4
|
+
# ruby suite.rb rg
|
5
|
+
# ^^^ that one is for color, and requires the redgreen gem
|
6
|
+
|
7
|
+
path = File.expand_path(File.dirname(__FILE__))
|
8
|
+
|
9
|
+
test_glob = File.join(path, "**", "test_*.rb")
|
10
|
+
tests = Dir.glob(test_glob)
|
11
|
+
|
12
|
+
if ARGV[0] != 'rg'
|
13
|
+
tests.each {|test| system("ruby #{test}")}
|
14
|
+
else
|
15
|
+
tests.each {|test| system("rg #{test}")}
|
16
|
+
end
|
17
|
+
|
18
|
+
# spec_glob = File.join(path, "**", "*_spec.rb")
|
19
|
+
# specs = Dir.glob(spec_glob)
|
20
|
+
# specs.each {|spec| system("spec --format progress --color #{spec}")}
|
@@ -0,0 +1,41 @@
|
|
1
|
+
require 'test/unit'
|
2
|
+
require File.expand_path(File.join(File.dirname(__FILE__), '..', 'lib', 'mapricot'))
|
3
|
+
|
4
|
+
|
5
|
+
class TestAbstractDoc < Test::Unit::TestCase
|
6
|
+
|
7
|
+
def test_initialize_from_string_or_url
|
8
|
+
assert_respond_to Mapricot::AbstractDoc, :from_string
|
9
|
+
assert_respond_to Mapricot::AbstractDoc, :from_url
|
10
|
+
end
|
11
|
+
|
12
|
+
def test_getting_node_contents
|
13
|
+
[:libxml, :nokogiri, :hpricot].each do |parser|
|
14
|
+
Mapricot.parser = parser
|
15
|
+
@doc = Mapricot::AbstractDoc.from_string('<user>bob</user>')
|
16
|
+
@node = @doc.find(:user).first
|
17
|
+
assert_equal "bob", @node.contents
|
18
|
+
assert_equal "<user>bob</user>", @node.to_s
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
def test_node_list
|
23
|
+
[:libxml, :nokogiri, :hpricot].each do |parser|
|
24
|
+
Mapricot.parser = parser
|
25
|
+
@doc = Mapricot::AbstractDoc.from_string('<response><user>sally</user><user>bob</user></response>')
|
26
|
+
@node_list = @doc.find(:user)
|
27
|
+
assert_instance_of Mapricot::AbstractNodeList, @node_list
|
28
|
+
assert_respond_to @node_list, :each
|
29
|
+
assert_respond_to @node_list, :first
|
30
|
+
assert_respond_to @node_list, :[]
|
31
|
+
|
32
|
+
@node_list.each do |node|
|
33
|
+
assert_instance_of Mapricot::AbstractNode, node
|
34
|
+
end
|
35
|
+
|
36
|
+
assert_equal "sally", @node_list[0].contents
|
37
|
+
assert_equal "bob", @node_list[1].contents
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
end
|