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 ADDED
@@ -0,0 +1,23 @@
1
+ == 0.0.1 2009-03-06
2
+
3
+ First gem!
4
+
5
+ == 0.0.2 2009-03-17
6
+
7
+ Nokogiri and Libxml support.
8
+
9
+ Select the parser to use by setting Mapricot.parser as follows:
10
+
11
+ Mapricot.parser = :nokogiri
12
+ Mapricot.parser = :libxml
13
+ Mapricot.parser = :hpricot
14
+
15
+ Hpricot will be used by default
16
+
17
+ == 0.0.3 2009-03-22
18
+
19
+ Can parse from url with Nokogiri
20
+
21
+ == 0.0.4 2009-05-27
22
+
23
+ Ditched rspec, now fully tested with test unit
data/License.txt ADDED
@@ -0,0 +1,19 @@
1
+ Copyright (c) 2009 Louis Zell <lzell11@gmail.com>
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining a copy
4
+ of this software and associated documentation files (the "Software"), to deal
5
+ in the Software without restriction, including without limitation the rights
6
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7
+ copies of the Software, and to permit persons to whom the Software is
8
+ furnished to do so, subject to the following conditions:
9
+
10
+ The above copyright notice and this permission notice shall be included in
11
+ all copies or substantial portions of the Software.
12
+
13
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19
+ THE SOFTWARE.
data/README.rdoc ADDED
@@ -0,0 +1,119 @@
1
+ == Mapricot
2
+
3
+ XML to object mapper with an interface similar to ActiveRecord associations.
4
+
5
+
6
+ == Install
7
+
8
+ sudo gem install mapricot
9
+
10
+
11
+ == Example Usage
12
+
13
+ ==== Super Simple
14
+ require 'mapricot'
15
+
16
+ simple_xml = %(
17
+ <user>
18
+ <id>1</name>
19
+ <name>Bob</name>
20
+ <pet>cat</pet>
21
+ <pet>dog</pet>
22
+ </user>
23
+ )
24
+
25
+ class User < Mapricot::Base
26
+ has_one :id, :integer
27
+ has_one :name, :string
28
+ has_many :pets, :string
29
+ end
30
+
31
+ user = User.new(:xml => simple_xml)
32
+ puts user.id # => 1
33
+ puts user.id.class # => Fixnum
34
+ puts user.name # => Bob
35
+ puts user.pets.class # => Array
36
+ puts user.pets.join(", ") # => cat, dog
37
+
38
+
39
+ ==== A little more realistic
40
+ require 'mapricot'
41
+
42
+ xml = %(
43
+ <user>
44
+ <id>2</name>
45
+ <name>Sally</name>
46
+ <location code="ny123">
47
+ <city>New York</city>
48
+ <state>NY</state>
49
+ </location>
50
+ <hobby>
51
+ <description>Skiing</description>
52
+ <number_of_years>2</number_of_years>
53
+ </hobby>
54
+ <hobby>
55
+ <description>Hiking</description>
56
+ <number_of_years>3</number_of_years>
57
+ </hobby>
58
+ </user>
59
+ )
60
+
61
+
62
+ class User < Mapricot::Base
63
+ has_one :id, :integer
64
+ has_one :name # Tag type will default to :string
65
+ has_many :pets
66
+ has_one :location, :xml
67
+ has_many :hobbies, :xml
68
+ end
69
+
70
+ class Location < Mapricot::Base
71
+ has_attribute :code
72
+ has_one :city
73
+ has_one :state
74
+ end
75
+
76
+ class Hobby < Mapricot::Base
77
+ has_one :description, :string
78
+ has_one :number_of_years, :integer
79
+ end
80
+
81
+ user = User.new(:xml => xml)
82
+ puts user.name # => Sally
83
+ puts user.pets.inspect # => []
84
+ puts user.location.class # => Location
85
+ puts user.location.city # => New York
86
+ puts user.location.state # => NY
87
+ puts user.location.code # => ny123
88
+ puts user.hobbies.class # => Array
89
+ puts user.hobbies.first.class # => Hobby
90
+
91
+ user.hobbies.each do |hobby|
92
+ puts "#{hobby.description} for #{hobby.number_of_years} years"
93
+ end
94
+ # => Skiing for 2 years
95
+ # => Hiking for 3 years
96
+
97
+ == Usage, TODO: fix this garbage
98
+
99
+ Your classes should inherit from Mapricot::Base, which provides the class methods
100
+ * has_one(name, type, opts = {})
101
+ * has_many(name, type, opts = {})
102
+ * has_attribute(name)
103
+
104
+ When you instantiate a Mapricot::Base object, you can pass it a string of xml:
105
+ class MapMe < Mapricot::Base
106
+ end
107
+
108
+ MapMe.new :xml => "<some_stuff>...</some_stuff>"
109
+
110
+ Or a url:
111
+
112
+ MapMe.new :url => "http://some_url"
113
+
114
+ == Credits
115
+
116
+ Named after why the luck stiff's Hpricot, which made this possible.
117
+
118
+
119
+ Copyright (c) 2009 Lou Zell, released under the MIT license
@@ -0,0 +1,127 @@
1
+ require File.expand_path(File.dirname(__FILE__) + "/../lib/mapricot")
2
+ require 'benchmark'
3
+
4
+ last_fm_example = %(<?xml version="1.0" encoding="utf-8"?>
5
+ <events>
6
+ <event>
7
+ <id>895664</id>
8
+ <title>Lydia</title>
9
+ <artists>
10
+ <artist>Lydia</artist>
11
+ <artist>Black Gold</artist>
12
+
13
+ <headliner>Lydia</headliner>
14
+ </artists>
15
+ <venue>
16
+ <name>Mercury Lounge</name>
17
+ <location>
18
+ <city>New York</city>
19
+ <country>United States</country>
20
+
21
+ <street>217 East Houston Street</street>
22
+ <postalcode>10002</postalcode>
23
+ <timezone>EST</timezone>
24
+
25
+ </location>
26
+ <url>http://www.last.fm/venue/8899833</url>
27
+ </venue>
28
+ <startDate>Thu, 05 Mar 2009</startDate>
29
+ <startTime>18:30</startTime>
30
+ <description><![CDATA[<div class="bbcode">On Sale Fri 1/16 at Noon<br />
31
+ 21+<br />
32
+ $10<br />
33
+ Doors 6:30pm/ Show 7:30pm</div>]]></description>
34
+ <image size="small">http://userserve-ak.last.fm/serve/34/9158303.jpg</image>
35
+
36
+ <image size="medium">http://userserve-ak.last.fm/serve/64/9158303.jpg</image>
37
+ <image size="large">http://userserve-ak.last.fm/serve/126/9158303.jpg</image>
38
+ <attendance>7</attendance>
39
+ <reviews>0</reviews>
40
+ <tag>lastfm:event=895664</tag>
41
+ <url>http://www.last.fm/event/895664</url>
42
+
43
+ </event>
44
+ <event>
45
+ <id>924763</id>
46
+ <title>Stars Like Fleas</title>
47
+ <artists>
48
+ <artist>Stars Like Fleas</artist>
49
+
50
+ <artist>Frances</artist>
51
+ <artist>twi the humble feather</artist>
52
+ <artist>La Strada</artist>
53
+ <headliner>Stars Like Fleas</headliner>
54
+ </artists>
55
+ <venue>
56
+ <name>Music Hall of Williamsburg</name>
57
+
58
+ <location>
59
+ <city>Brooklyn, NY</city>
60
+ <country>United States</country>
61
+ <street>66 North 6th Street</street>
62
+ <postalcode>11211</postalcode>
63
+ <timezone>EST</timezone>
64
+ </location>
65
+ <url>http://www.last.fm/venue/8851989</url>
66
+ </venue>
67
+ <startDate>Thu, 05 Mar 2009</startDate>
68
+
69
+ <startTime>19:00</startTime>
70
+ <description><![CDATA[<div class="bbcode">Doors 7 p.m. / Show 8 p.m.<br />
71
+ $10 advance / $12 day of show<br />
72
+ 18+<br />
73
+ <br />
74
+ On sale Wed. 2/4 at noon</div>]]></description>
75
+ <image size="small">http://userserve-ak.last.fm/serve/34/3598785.jpg</image>
76
+ <image size="medium">http://userserve-ak.last.fm/serve/64/3598785.jpg</image>
77
+ <image size="large">http://userserve-ak.last.fm/serve/126/3598785.jpg</image>
78
+ <attendance>1</attendance>
79
+
80
+ <reviews>0</reviews>
81
+ <tag>lastfm:event=924763</tag>
82
+ <url>http://www.last.fm/event/924763</url>
83
+ </event>
84
+ </events>
85
+
86
+ )
87
+
88
+
89
+ class Response < Mapricot::Base
90
+ has_many :events, :xml
91
+ end
92
+
93
+ class Event < Mapricot::Base
94
+ has_one :id, :integer
95
+ has_one :title, :string
96
+ has_one :artist_group, :xml, :tag_name => "artists"
97
+ has_one :venue, :xml
98
+ end
99
+
100
+ class ArtistGroup < Mapricot::Base
101
+ has_many :artists, :string
102
+ has_one :headliner, :string
103
+ end
104
+
105
+ class Venue < Mapricot::Base
106
+ has_one :name, :string
107
+ end
108
+
109
+ lfm = Response.new(:xml => last_fm_example)
110
+
111
+
112
+ n = 200
113
+ Benchmark.bm do |x|
114
+ x.report("hpricot") {
115
+ Mapricot.parser = :hpricot;
116
+ n.times { lfm = Response.new(:xml => last_fm_example) }
117
+ }
118
+ x.report("libxml") {
119
+ Mapricot.parser = :libxml;
120
+ n.times { lfm = Response.new(:xml => last_fm_example) }
121
+ }
122
+ x.report("nokogiri") {
123
+ Mapricot.parser = :nokogiri;
124
+ n.times { lfm = Response.new(:xml => last_fm_example) }
125
+ }
126
+
127
+ end
@@ -0,0 +1,86 @@
1
+ require 'rubygems'
2
+ require File.expand_path(File.dirname(__FILE__) + "/../lib/mapricot")
3
+
4
+ # Using a Facebook example
5
+ # This xml is taken straight from here: http://wiki.developers.facebook.com/index.php/Users.getInfo
6
+ # Note, libxml does not like this for some reason:
7
+ # <users_getInfo_response xmlns="http://api.facebook.com/1.0/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://api.facebook.com/1.0/ http://api.facebook.com/1.0/facebook.xsd" list="true">
8
+ # So 'xmlns="http://api.facebook.com/1.0/"' has been stripped from tag
9
+ # Because of this, for real requests we will have to use hpricot or nokogiri
10
+ FACEBOOK_XML = %(<?xml version="1.0" encoding="UTF-8"?>
11
+ <users_getInfo_response xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://api.facebook.com/1.0/ http://api.facebook.com/1.0/facebook.xsd" list="true">
12
+ <user>
13
+ <uid>8055</uid>
14
+ <about_me>This field perpetuates the glorification of the ego. Also, it has a character limit.</about_me>
15
+ <activities>Here: facebook, etc. There: Glee Club, a capella, teaching.</activities>
16
+ <affiliations list="true">
17
+ <affiliation>
18
+ <nid>50453093</nid>
19
+ <name>Facebook Developers</name>
20
+ <type>work</type>
21
+ <status/>
22
+ <year/>
23
+ </affiliation>
24
+ </affiliations>
25
+ <birthday>November 3</birthday>
26
+ <books>The Brothers K, GEB, Ken Wilber, Zen and the Art, Fitzgerald, The Emporer's New Mind, The Wonderful Story of Henry Sugar</books>
27
+ <current_location>
28
+ <city>Palo Alto</city>
29
+ <state>CA</state>
30
+ <country>United States</country>
31
+ <zip>94303</zip>
32
+ </current_location>
33
+ </user>
34
+ </users_getInfo_response>
35
+ )
36
+
37
+
38
+ class UsersGetInfoResponse < Mapricot::Base
39
+ has_many :users, :xml
40
+ end
41
+
42
+ class User < Mapricot::Base
43
+ has_one :uid, :integer
44
+ has_one :about_me, :string
45
+ has_one :activities, :string
46
+ has_one :affiliation_list, :xml, :tag_name => "affiliations" # this is cumbersome, do something about this
47
+ has_one :birthday, :string
48
+ has_one :current_location, :xml
49
+ end
50
+
51
+ class AffiliationList < Mapricot::Base
52
+ has_many :affiliations, :xml
53
+ end
54
+
55
+ class Affiliation < Mapricot::Base
56
+ has_one :nid, :integer
57
+ has_one :name, :string
58
+ has_one :type, :string
59
+ has_one :status, :string
60
+ has_one :year, :integer
61
+ end
62
+
63
+ class CurrentLocation < Mapricot::Base
64
+ has_one :city, :string
65
+ has_one :state, :string
66
+ has_one :country, :string
67
+ has_one :zip, :integer
68
+ end
69
+
70
+
71
+ response = UsersGetInfoResponse.new(:xml => FACEBOOK_XML)
72
+ puts response.users.class # => Array
73
+ puts response.users.size # => 1
74
+
75
+ user = response.users.first
76
+
77
+ puts user.uid # => 8055
78
+ puts user.activities # => "Here: facebook, etc. There: Glee Club, a capella, teaching."
79
+ puts user.current_location.city # => "Palo Alto"
80
+ puts user.current_location.state # => "CA"
81
+ puts user.current_location.country # => "United States"
82
+ puts user.current_location.zip # => 94303
83
+
84
+ # need to remove redundancy here:
85
+ puts user.affiliation_list.affiliations.first.name # => "Facebook Developers"
86
+ puts user.affiliation_list.affiliations.first.nid # => 50453093
@@ -0,0 +1,42 @@
1
+ # Get events in nyc with:
2
+ # http://ws.audioscrobbler.com/2.0/?method=geo.getevents&city=new+york&api_key=YOUR_API_KEY_HERE
3
+
4
+ # The point of this is to demonstrate mapping xml from a real api response.
5
+ # The only difference is you instantiate with:
6
+ # Response.new(:url => "http://someurl")
7
+ # instead of:
8
+ # Response.new(:xml => "some string of xml")
9
+
10
+ # If you do not have an API key, see examples/lastfm_api_no_request.rb
11
+ require 'rubygems'
12
+ require File.expand_path(File.dirname(__FILE__) + "/../lib/mapricot")
13
+
14
+ class Response < Mapricot::Base
15
+ has_many :events, :xml
16
+ end
17
+
18
+ class Event < Mapricot::Base
19
+ has_one :title
20
+ has_one :venue, :xml
21
+ end
22
+
23
+ class Venue < Mapricot::Base
24
+ has_one :name
25
+ has_one :location, :xml
26
+ end
27
+
28
+ class Location < Mapricot::Base
29
+ has_one :city
30
+ has_one :country
31
+ has_one :street
32
+ has_one :postalcode, :integer
33
+ end
34
+
35
+ response = Response.new(:url => "http://ws.audioscrobbler.com/2.0/?method=geo.getevents&city=new+york&api_key=#{YOUR_API_KEY_HERE}")
36
+
37
+ response.events.each do |event|
38
+ puts "-------------"
39
+ puts event.title
40
+ puts event.venue.name
41
+ puts event.venue.location.city
42
+ end
@@ -0,0 +1,127 @@
1
+ require 'rubygems'
2
+ require File.expand_path(File.dirname(__FILE__) + "/../lib/mapricot")
3
+
4
+
5
+ last_fm_example = %(
6
+ <?xml version="1.0" encoding="utf-8"?>
7
+ <lfm status="ok">
8
+ <events location="New York, United States" page="1" totalpages="92" xmlns:geo="http://www.w3.org/2003/01/geo/wgs84_pos#" total="917">
9
+ <event>
10
+ <id>895664</id>
11
+ <title>Lydia</title>
12
+ <artists>
13
+ <artist>Lydia</artist>
14
+ <artist>Black Gold</artist>
15
+
16
+ <headliner>Lydia</headliner>
17
+ </artists>
18
+ <venue>
19
+ <name>Mercury Lounge</name>
20
+ <location>
21
+ <city>New York</city>
22
+ <country>United States</country>
23
+
24
+ <street>217 East Houston Street</street>
25
+ <postalcode>10002</postalcode>
26
+ <geo:point>
27
+ <geo:lat>40.722024</geo:lat>
28
+ <geo:long>-73.98682</geo:long>
29
+ </geo:point>
30
+ <timezone>EST</timezone>
31
+
32
+ </location>
33
+ <url>http://www.last.fm/venue/8899833</url>
34
+ </venue>
35
+ <startDate>Thu, 05 Mar 2009</startDate>
36
+ <startTime>18:30</startTime>
37
+ <description><![CDATA[<div class="bbcode">On Sale Fri 1/16 at Noon<br />
38
+ 21+<br />
39
+ $10<br />
40
+ Doors 6:30pm/ Show 7:30pm</div>]]></description>
41
+ <image size="small">http://userserve-ak.last.fm/serve/34/9158303.jpg</image>
42
+
43
+ <image size="medium">http://userserve-ak.last.fm/serve/64/9158303.jpg</image>
44
+ <image size="large">http://userserve-ak.last.fm/serve/126/9158303.jpg</image>
45
+ <attendance>7</attendance>
46
+ <reviews>0</reviews>
47
+ <tag>lastfm:event=895664</tag>
48
+ <url>http://www.last.fm/event/895664</url>
49
+
50
+ </event>
51
+ <event>
52
+ <id>924763</id>
53
+ <title>Stars Like Fleas</title>
54
+ <artists>
55
+ <artist>Stars Like Fleas</artist>
56
+
57
+ <artist>Frances</artist>
58
+ <artist>twi the humble feather</artist>
59
+ <artist>La Strada</artist>
60
+ <headliner>Stars Like Fleas</headliner>
61
+ </artists>
62
+ <venue>
63
+ <name>Music Hall of Williamsburg</name>
64
+
65
+ <location>
66
+ <city>Brooklyn, NY</city>
67
+ <country>United States</country>
68
+ <street>66 North 6th Street</street>
69
+ <postalcode>11211</postalcode>
70
+ <geo:point>
71
+ <geo:lat>40.719308</geo:lat>
72
+
73
+ <geo:long>-73.961607</geo:long>
74
+ </geo:point>
75
+ <timezone>EST</timezone>
76
+ </location>
77
+ <url>http://www.last.fm/venue/8851989</url>
78
+ </venue>
79
+ <startDate>Thu, 05 Mar 2009</startDate>
80
+
81
+ <startTime>19:00</startTime>
82
+ <description><![CDATA[<div class="bbcode">Doors 7 p.m. / Show 8 p.m.<br />
83
+ $10 advance / $12 day of show<br />
84
+ 18+<br />
85
+ <br />
86
+ On sale Wed. 2/4 at noon</div>]]></description>
87
+ <image size="small">http://userserve-ak.last.fm/serve/34/3598785.jpg</image>
88
+ <image size="medium">http://userserve-ak.last.fm/serve/64/3598785.jpg</image>
89
+ <image size="large">http://userserve-ak.last.fm/serve/126/3598785.jpg</image>
90
+ <attendance>1</attendance>
91
+
92
+ <reviews>0</reviews>
93
+ <tag>lastfm:event=924763</tag>
94
+ <url>http://www.last.fm/event/924763</url>
95
+ </event>
96
+ </events></lfm>
97
+
98
+ )
99
+
100
+
101
+ class Response < Mapricot::Base
102
+ has_many :events, :xml
103
+ end
104
+
105
+ class Event < Mapricot::Base
106
+ has_one :id, :integer
107
+ has_one :title, :string
108
+ has_one :artist_group, :xml, :tag_name => "artists"
109
+ has_one :venue, :xml
110
+ end
111
+
112
+ class ArtistGroup < Mapricot::Base
113
+ has_many :artists, :string
114
+ has_one :headliner, :string
115
+ end
116
+
117
+ class Venue < Mapricot::Base
118
+ has_one :name, :string
119
+ end
120
+
121
+ lfm = Response.new(:xml => last_fm_example)
122
+ lfm.events.each do |event|
123
+ puts "-------------------------------"
124
+ puts event.title
125
+ puts event.artist_group.artists.inspect
126
+ puts event.venue.name
127
+ end
@@ -0,0 +1,82 @@
1
+ require File.expand_path(File.dirname(__FILE__) + "/../lib/mapricot")
2
+
3
+ # super simple
4
+ simple_xml = %(
5
+ <user>
6
+ <id>1</name>
7
+ <name>Bob</name>
8
+ <pet>cat</pet>
9
+ <pet>dog</pet>
10
+ </user>
11
+ )
12
+
13
+ class User < Mapricot::Base
14
+ has_one :id, :integer
15
+ has_one :name, :string
16
+ has_many :pets, :string
17
+ end
18
+
19
+ user = User.new(:xml => simple_xml)
20
+ puts user.id # => 1
21
+ puts user.id.class # => Fixnum
22
+ puts user.name # => Bob
23
+ puts user.pets.class # => Array
24
+ puts user.pets.join(", ") # => cat, dog
25
+
26
+ puts "-------------------"
27
+
28
+ # A little more realistic
29
+ xml = %(
30
+ <user>
31
+ <id>2</name>
32
+ <name>Sally</name>
33
+ <location code="ny123">
34
+ <city>New York</city>
35
+ <state>NY</state>
36
+ </location>
37
+ <hobby>
38
+ <description>Skiing</description>
39
+ <number_of_years>2</number_of_years>
40
+ </hobby>
41
+ <hobby>
42
+ <description>Hiking</description>
43
+ <number_of_years>3</number_of_years>
44
+ </hobby>
45
+ </user>
46
+ )
47
+
48
+
49
+ class User < Mapricot::Base
50
+ has_one :id, :integer
51
+ has_one :name # Tag type will default to :string
52
+ has_many :pets
53
+ has_one :location, :xml
54
+ has_many :hobbies, :xml
55
+ end
56
+
57
+ class Location < Mapricot::Base
58
+ has_attribute :code
59
+ has_one :city
60
+ has_one :state
61
+ end
62
+
63
+ class Hobby < Mapricot::Base
64
+ has_one :description, :string
65
+ has_one :number_of_years, :integer
66
+ end
67
+
68
+ user = User.new(:xml => xml)
69
+ puts user.name # => Sally
70
+ puts user.pets.inspect # => []
71
+ puts user.location.class # => Location
72
+ puts user.location.city # => New York
73
+ puts user.location.state # => NY
74
+ puts user.location.code # => ny123
75
+ puts user.hobbies.class # => Array
76
+ puts user.hobbies.first.class # => Hobby
77
+
78
+ user.hobbies.each do |hobby|
79
+ puts "#{hobby.description} for #{hobby.number_of_years} years"
80
+ end
81
+ # => Skiing for 2 years
82
+ # => Hiking for 3 years
@@ -0,0 +1,26 @@
1
+ require File.expand_path(File.dirname(__FILE__) + "/../lib/mapricot")
2
+
3
+
4
+ xml = %(
5
+ <response>
6
+ <user id="32" name="Bob"></user>
7
+ <user id="33" name="Sally"></user>
8
+ </response>
9
+ )
10
+
11
+
12
+ class Response < Mapricot::Base
13
+ has_many :users, :xml
14
+ end
15
+
16
+ class User < Mapricot::Base
17
+ has_attribute :id
18
+ has_attribute :name
19
+ end
20
+
21
+ response = Response.new(:xml => xml)
22
+
23
+ response.users.each do |user|
24
+ puts user.name
25
+ puts user.id
26
+ end