smg 0.2.0 → 0.2.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -19,7 +19,8 @@ http://github.com/SSDany/smg/tree/master/examples
19
19
 
20
20
  == REQUIREMENTS:
21
21
 
22
- nokogiri (>=1.3)
22
+ * nokogiri (>=1.3)
23
+ * addressable (>=2.1.1)
23
24
 
24
25
  == LICENSE:
25
26
 
@@ -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
@@ -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
 
@@ -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
- @chars = ""
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 doc = @docs.last
24
- doc.start_element(name, attrs)
25
- elsif (thing = @mapping.nested[@stack]) &&
26
- !@mapping.parsed.include?(thing.object_id) &&
27
- thing.in_context_of?(@context) &&
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 !@mapping.parsed.include?(m.object_id) &&
37
- m.in_context_of?(@context) &&
38
- m.with?(ahash)
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
- @mapping.parsed << m.object_id unless m.collection?
37
+ @parsed << m.object_id unless m.collection?
42
38
  end
43
39
  end
44
40
  end
45
41
 
46
- if (e = @mapping.elements[@stack]) &&
47
- !@mapping.parsed.include?(e.object_id) &&
48
- e.in_context_of?(@context) &&
49
- e.with?(ahash ||= Hash[*attrs])
50
- @element = e
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 @element
59
- @object.__send__(@element.accessor, @element.cast(@chars))
60
- @mapping.parsed << @element.object_id unless @element.collection?
61
- @chars = ""
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
- if doc = @docs.last
66
- doc.end_element(name)
67
- if (t = doc.thing).path == @stack
68
- @object.__send__(t.accessor, doc.object)
69
- @docs.pop
70
- @mapping.parsed << t.object_id unless t.collection?
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
- if doc = @docs.last
80
- doc.characters(string)
81
- @chars << string
82
- elsif @element
83
- @chars << string
84
- end
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
@@ -34,12 +34,6 @@ module SMG #:nodoc:
34
34
  @root = normalize_path(path)
35
35
  end
36
36
 
37
- def refresh!
38
- @parsed ||= []
39
- @parsed.clear
40
- nil
41
- end
42
-
43
37
  private
44
38
 
45
39
  def normalize_path(path)
@@ -1,5 +1,5 @@
1
1
  module SMG
2
- VERSION = '0.1.0'
2
+ VERSION = '0.2.1'
3
3
  end
4
4
 
5
5
  # EOF
@@ -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 :all do
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 :all do
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
- it "supports nested collections" do
225
- @klass.root 'resp/release'
226
- @klass.collect 'tracklist/track' , :as => :tracks, :class => @track_class
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.should be_an_instance_of ::Array
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
@@ -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
- - 0
9
- version: 0.2.0
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-13 00:00:00 +04:00
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