smg 0.2.0 → 0.2.1
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/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
|