mapricot 0.0.4

Sign up to get free protection for your applications and to get access to all the features.
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