smg 0.2.0 → 0.2.1
Sign up to get free protection for your applications and to get access to all the features.
- data/README.rdoc +2 -1
- data/examples/crazy.rb +37 -0
- data/examples/weather.rb +2 -1
- data/lib/smg/document.rb +34 -41
- data/lib/smg/mapping.rb +0 -6
- data/lib/smg/version.rb +1 -1
- data/spec/collect_spec.rb +38 -20
- data/spec/extract_spec.rb +19 -0
- metadata +4 -3
data/README.rdoc
CHANGED
data/examples/crazy.rb
ADDED
@@ -0,0 +1,37 @@
|
|
1
|
+
require File.expand_path(File.join(File.dirname(__FILE__), 'helper'))
|
2
|
+
|
3
|
+
class A
|
4
|
+
include SMG::Resource
|
5
|
+
extract "a" , :as => :href , :at => :href
|
6
|
+
extract "a" , :as => :content
|
7
|
+
end
|
8
|
+
|
9
|
+
class P
|
10
|
+
include SMG::Resource
|
11
|
+
extract "p" , :as => :raw
|
12
|
+
collect "p/a" , :as => :links , :class => A
|
13
|
+
end
|
14
|
+
|
15
|
+
class Requirements
|
16
|
+
include SMG::Resource
|
17
|
+
root "div"
|
18
|
+
extract "p" , :as => :raw
|
19
|
+
extract "p" , :as => :p , :class => P
|
20
|
+
collect "p/a" , :as => :links , :class => A
|
21
|
+
end
|
22
|
+
|
23
|
+
data = <<-HTML
|
24
|
+
<div><p>Requirements: <a href="http://github.com/tenderlove/nokogiri">nokogiri</a> and <a href="http://github.com/sporkmonger/addressable">addressable</a>.</p></div>
|
25
|
+
HTML
|
26
|
+
|
27
|
+
parsed = Requirements.parse(data)
|
28
|
+
|
29
|
+
puts parsed.raw #=> "Requirements: nokogiri and addressable."
|
30
|
+
puts parsed.links.map { |a| a.href } #=> ["http://github.com/tenderlove/nokogiri", "http://github.com/sporkmonger/addressable"]
|
31
|
+
puts parsed.links.map { |a| a.content } #=> ["nokogiri", "addressable"]
|
32
|
+
|
33
|
+
puts parsed.p.raw #=> "Requirements: nokogiri and addressable."
|
34
|
+
puts parsed.p.links.map { |a| a.href } #=> ["http://github.com/tenderlove/nokogiri", "http://github.com/sporkmonger/addressable"]
|
35
|
+
puts parsed.p.links.map { |a| a.content } #=> ["nokogiri", "addressable"]
|
36
|
+
|
37
|
+
# EOF
|
data/examples/weather.rb
CHANGED
@@ -132,9 +132,10 @@ class YWeather
|
|
132
132
|
|
133
133
|
root 'rss/channel/item'
|
134
134
|
|
135
|
+
extract "title"
|
136
|
+
extract "description"
|
135
137
|
extract "geo:lat" , :as => :latitude
|
136
138
|
extract "geo:long" , :as => :longitude
|
137
|
-
extract "title" , :as => :title
|
138
139
|
extract "yweather:condition" , :as => :current , :class => Condition
|
139
140
|
collect "yweather:forecast" , :as => :forecasts , :class => Forecast
|
140
141
|
|
data/lib/smg/document.rb
CHANGED
@@ -8,11 +8,10 @@ module SMG #:nodoc:
|
|
8
8
|
@mapping = object.class.mapping
|
9
9
|
@stack = []
|
10
10
|
@docs = []
|
11
|
+
@elements = []
|
11
12
|
@thing = thing
|
12
13
|
@context = context
|
13
|
-
@
|
14
|
-
|
15
|
-
@mapping.refresh!
|
14
|
+
@parsed = []
|
16
15
|
end
|
17
16
|
|
18
17
|
def start_element(name, attrs)
|
@@ -20,55 +19,49 @@ module SMG #:nodoc:
|
|
20
19
|
@stack << name
|
21
20
|
ahash = nil
|
22
21
|
|
23
|
-
if
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
thing.with?(ahash ||= Hash[*attrs])
|
29
|
-
|
30
|
-
@docs << doc = Document.new(thing.data_class.new,@context,thing)
|
31
|
-
doc.start_element(name, attrs)
|
22
|
+
if thing = @mapping.nested[@stack] and
|
23
|
+
!@parsed.include?(thing.object_id) &&
|
24
|
+
thing.in_context_of?(@context) &&
|
25
|
+
thing.with?(ahash ||= Hash[*attrs])
|
26
|
+
@docs << Document.new(thing.data_class.new,@context,thing)
|
32
27
|
end
|
33
28
|
|
29
|
+
@docs.each { |doc| doc.start_element(name,attrs) }
|
30
|
+
|
34
31
|
if !attrs.empty? && maps = @mapping.attributes[@stack]
|
35
32
|
maps.values_at(*(ahash ||= Hash[*attrs]).keys).compact.each do |m|
|
36
|
-
if !@
|
37
|
-
|
38
|
-
|
39
|
-
|
33
|
+
if !@parsed.include?(m.object_id) &&
|
34
|
+
m.in_context_of?(@context) &&
|
35
|
+
m.with?(ahash)
|
40
36
|
@object.__send__(m.accessor, m.cast(ahash[m.at]))
|
41
|
-
@
|
37
|
+
@parsed << m.object_id unless m.collection?
|
42
38
|
end
|
43
39
|
end
|
44
40
|
end
|
45
41
|
|
46
|
-
if
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
@
|
51
|
-
@chars = ""
|
42
|
+
if e = @mapping.elements[@stack] and
|
43
|
+
!@parsed.include?(e.object_id) &&
|
44
|
+
e.in_context_of?(@context) &&
|
45
|
+
e.with?(ahash ||= Hash[*attrs])
|
46
|
+
@elements << [e,""]
|
52
47
|
end
|
53
48
|
|
54
49
|
end
|
55
50
|
|
56
51
|
def end_element(name)
|
57
52
|
|
58
|
-
if @
|
59
|
-
|
60
|
-
@
|
61
|
-
@
|
62
|
-
@element = nil
|
53
|
+
if e = @elements.last and e.first.path == @stack
|
54
|
+
e,chars = *@elements.pop
|
55
|
+
@object.__send__(e.accessor, e.cast(chars))
|
56
|
+
@parsed << e.object_id unless e.collection?
|
63
57
|
end
|
64
58
|
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
end
|
59
|
+
@docs.each { |doc| doc.end_element(name) }
|
60
|
+
|
61
|
+
if doc = @docs.last and doc.thing.path == @stack
|
62
|
+
@object.__send__(doc.thing.accessor, doc.object)
|
63
|
+
@parsed << doc.thing.object_id unless doc.thing.collection?
|
64
|
+
@docs.pop
|
72
65
|
end
|
73
66
|
|
74
67
|
@stack.pop
|
@@ -76,12 +69,12 @@ module SMG #:nodoc:
|
|
76
69
|
end
|
77
70
|
|
78
71
|
def characters(string)
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
72
|
+
@docs.each { |doc| doc.characters(string) }
|
73
|
+
@elements.each { |e| e.last << string }
|
74
|
+
end
|
75
|
+
|
76
|
+
def cdata_block(string)
|
77
|
+
characters(string)
|
85
78
|
end
|
86
79
|
|
87
80
|
end
|
data/lib/smg/mapping.rb
CHANGED
data/lib/smg/version.rb
CHANGED
data/spec/collect_spec.rb
CHANGED
@@ -116,7 +116,7 @@ describe SMG::Model, ".collect", "when :class option represents SMG::Resource" d
|
|
116
116
|
@data = data = File.read(FIXTURES_DIR + 'discogs/Genosha+Recordings.xml')
|
117
117
|
end
|
118
118
|
|
119
|
-
before :
|
119
|
+
before :each do
|
120
120
|
@release_class = Class.new { include SMG::Resource }
|
121
121
|
@release_class.extract 'release' , :at => :id , :as => :discogs_id
|
122
122
|
@release_class.extract 'release' , :at => :status
|
@@ -206,7 +206,7 @@ describe SMG::Model, ".collect", "with nested collections" do
|
|
206
206
|
@data = data = File.read(FIXTURES_DIR + 'discogs/948224.xml')
|
207
207
|
end
|
208
208
|
|
209
|
-
before :
|
209
|
+
before :each do
|
210
210
|
@artist_class = Class.new { include SMG::Resource }
|
211
211
|
@artist_class.root 'artist'
|
212
212
|
@artist_class.extract :name
|
@@ -217,38 +217,56 @@ describe SMG::Model, ".collect", "with nested collections" do
|
|
217
217
|
@track_class.extract :position
|
218
218
|
@track_class.extract :title
|
219
219
|
@track_class.extract :duration
|
220
|
-
@track_class.collect 'extraartists/artist/name', :as => :extra_artist_names
|
221
220
|
@track_class.collect 'extraartists/artist', :as => :extra_artists, :class => @artist_class
|
222
221
|
end
|
223
222
|
|
224
|
-
|
225
|
-
@
|
226
|
-
@
|
227
|
-
@klass.collect 'tracklist/track/title' , :as => :tracklist
|
228
|
-
release = @klass.parse(@data)
|
229
|
-
|
230
|
-
release.tracklist.should be_an_instance_of ::Array
|
231
|
-
release.tracklist.size.should == 6
|
232
|
-
release.tracklist.should == ["Butterfly V.I.P. (VIP Edit By Ophidian)", "Butterfly V.I.P. (Interlude By Cubist Boy & Tapage)", "Butterfly V.I.P. (Original Version)", "Hammerhead V.I.P. (VIP Edit By Ophidian)", "Hammerhead V.I.P. (Interlude By Cubist Boy & Tapage)", "Hammerhead V.I.P. (Original Version)"]
|
223
|
+
after :each do
|
224
|
+
@release.tracks.should be_an_instance_of ::Array
|
225
|
+
@release.tracks.size.should == 6
|
233
226
|
|
234
|
-
release.tracks
|
235
|
-
release.tracks.size.should == 6
|
236
|
-
|
237
|
-
track = release.tracks[1]
|
227
|
+
track = @release.tracks[1]
|
238
228
|
track.position.should == 'A2'
|
239
229
|
track.title.should == 'Butterfly V.I.P. (Interlude By Cubist Boy & Tapage)'
|
240
230
|
track.duration.should == '1:24'
|
241
231
|
|
242
|
-
track.extra_artist_names.should be_an_instance_of ::Array
|
243
|
-
track.extra_artist_names.size.should == 2
|
244
|
-
track.extra_artist_names.should == ['Cubist Boy', 'Tapage']
|
245
|
-
|
246
232
|
track.extra_artists.should be_an_instance_of ::Array
|
247
233
|
track.extra_artists.size.should == 2
|
248
234
|
track.extra_artists[1].name.should == 'Tapage'
|
249
235
|
track.extra_artists[1].role.should == 'Co-producer'
|
250
236
|
end
|
251
237
|
|
238
|
+
it "supports nested collections" do
|
239
|
+
@klass.root 'resp/release'
|
240
|
+
@klass.collect 'tracklist/track', :as => :tracks, :class => @track_class
|
241
|
+
|
242
|
+
@release = @klass.parse(@data)
|
243
|
+
end
|
244
|
+
|
245
|
+
it "handles each collection independently" do
|
246
|
+
|
247
|
+
@track_class.collect 'extraartists/artist/name', :as => :extra_artist_names
|
248
|
+
|
249
|
+
@klass.root 'resp/release/tracklist'
|
250
|
+
@klass.collect 'track' , :as => :tracks, :class => @track_class
|
251
|
+
@klass.collect 'track/title' , :as => :tracklist
|
252
|
+
@klass.collect 'track/extraartists/artist' , :as => :extra_artists, :class => @artist_class
|
253
|
+
|
254
|
+
@release = @klass.parse(@data)
|
255
|
+
|
256
|
+
@release.tracklist.should be_an_instance_of ::Array
|
257
|
+
@release.tracklist.size.should == 6
|
258
|
+
@release.tracklist.should == ["Butterfly V.I.P. (VIP Edit By Ophidian)", "Butterfly V.I.P. (Interlude By Cubist Boy & Tapage)", "Butterfly V.I.P. (Original Version)", "Hammerhead V.I.P. (VIP Edit By Ophidian)", "Hammerhead V.I.P. (Interlude By Cubist Boy & Tapage)", "Hammerhead V.I.P. (Original Version)"]
|
259
|
+
|
260
|
+
@release.tracks.should be_an_instance_of ::Array
|
261
|
+
@release.tracks.size.should == 6
|
262
|
+
|
263
|
+
@release.extra_artists.should be_an_instance_of ::Array
|
264
|
+
@release.extra_artists.size.should == 6
|
265
|
+
@release.extra_artists[2].name.should == 'Tapage'
|
266
|
+
@release.extra_artists[2].role.should == 'Co-producer'
|
267
|
+
|
268
|
+
end
|
269
|
+
|
252
270
|
end
|
253
271
|
|
254
272
|
# EOF
|
data/spec/extract_spec.rb
CHANGED
@@ -197,4 +197,23 @@ describe SMG::Model, ".extract" do
|
|
197
197
|
|
198
198
|
end
|
199
199
|
|
200
|
+
describe SMG::Model, ".extract" do
|
201
|
+
|
202
|
+
before :each do
|
203
|
+
@klass = Class.new { include SMG::Resource }
|
204
|
+
@data = "<thing>just<another>yetanother</another>spec</thing>"
|
205
|
+
end
|
206
|
+
|
207
|
+
it "handles each element independently" do
|
208
|
+
@klass.extract :thing
|
209
|
+
parsed = @klass.parse(@data)
|
210
|
+
parsed.thing.should == "justyetanotherspec"
|
211
|
+
|
212
|
+
@klass.extract "thing/another"
|
213
|
+
parsed = @klass.parse(@data)
|
214
|
+
parsed.thing.should == "justyetanotherspec" # NOT "justspec"
|
215
|
+
parsed.another.should == "yetanother"
|
216
|
+
end
|
217
|
+
|
218
|
+
end
|
200
219
|
# EOF
|
metadata
CHANGED
@@ -5,8 +5,8 @@ version: !ruby/object:Gem::Version
|
|
5
5
|
segments:
|
6
6
|
- 0
|
7
7
|
- 2
|
8
|
-
-
|
9
|
-
version: 0.2.
|
8
|
+
- 1
|
9
|
+
version: 0.2.1
|
10
10
|
platform: ruby
|
11
11
|
authors:
|
12
12
|
- SSDany
|
@@ -14,7 +14,7 @@ autorequire:
|
|
14
14
|
bindir: bin
|
15
15
|
cert_chain: []
|
16
16
|
|
17
|
-
date: 2010-06-
|
17
|
+
date: 2010-06-14 00:00:00 +04:00
|
18
18
|
default_executable:
|
19
19
|
dependencies:
|
20
20
|
- !ruby/object:Gem::Dependency
|
@@ -69,6 +69,7 @@ files:
|
|
69
69
|
- lib/smg/resource.rb
|
70
70
|
- lib/smg/version.rb
|
71
71
|
- lib/smg.rb
|
72
|
+
- examples/crazy.rb
|
72
73
|
- examples/discogs/label.rb
|
73
74
|
- examples/discogs/search.rb
|
74
75
|
- examples/helper.rb
|