smg 0.2.1 → 0.2.2

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.
Files changed (42) hide show
  1. data/README.rdoc +1 -1
  2. data/lib/smg/http.rb +23 -24
  3. data/lib/smg/http/exceptions.rb +5 -9
  4. data/lib/smg/http/hooks.rb +43 -0
  5. data/lib/smg/http/request.rb +23 -2
  6. data/lib/smg/mapping.rb +1 -3
  7. data/lib/smg/mapping/element.rb +1 -5
  8. data/lib/smg/mapping/typecasts.rb +1 -1
  9. data/lib/smg/model.rb +4 -4
  10. data/lib/smg/version.rb +1 -1
  11. metadata +32 -37
  12. data/examples/crazy.rb +0 -37
  13. data/examples/discogs/label.rb +0 -62
  14. data/examples/discogs/search.rb +0 -60
  15. data/examples/helper.rb +0 -10
  16. data/examples/plant.rb +0 -88
  17. data/examples/twitter.rb +0 -38
  18. data/examples/weather.rb +0 -147
  19. data/spec/collect_spec.rb +0 -272
  20. data/spec/context_spec.rb +0 -189
  21. data/spec/extract_spec.rb +0 -219
  22. data/spec/filtering_spec.rb +0 -164
  23. data/spec/fixtures/discogs/948224.xml +0 -1
  24. data/spec/fixtures/discogs/Enzyme+Records.xml +0 -9
  25. data/spec/fixtures/discogs/Genosha+Recordings.xml +0 -13
  26. data/spec/fixtures/discogs/Ophidian.xml +0 -6
  27. data/spec/fixtures/fake/malus.xml +0 -18
  28. data/spec/fixtures/fake/valve.xml +0 -8
  29. data/spec/fixtures/twitter/pipopolam.xml +0 -46
  30. data/spec/fixtures/yahoo.weather.com.xml +0 -50
  31. data/spec/http/request_spec.rb +0 -186
  32. data/spec/http/shared/automatic.rb +0 -43
  33. data/spec/http/shared/non_automatic.rb +0 -36
  34. data/spec/http/shared/redirectable.rb +0 -30
  35. data/spec/http_spec.rb +0 -76
  36. data/spec/lib/helpers/http_helpers.rb +0 -27
  37. data/spec/lib/matchers/instance_methods.rb +0 -38
  38. data/spec/mapping/element_spec.rb +0 -241
  39. data/spec/mapping/typecasts_spec.rb +0 -52
  40. data/spec/resource_spec.rb +0 -30
  41. data/spec/root_spec.rb +0 -26
  42. data/spec/spec_helper.rb +0 -23
@@ -1,76 +0,0 @@
1
- require File.expand_path File.join(File.dirname(__FILE__), 'spec_helper')
2
-
3
- describe SMG::HTTP::Model, ".uri_for" do
4
-
5
- before :all do
6
- @klass = Class.new { include SMG::Resource, SMG::HTTP }
7
- @klass.site "http://www.example.org"
8
- @klass.params "developer" => "Valve"
9
- end
10
-
11
- it "appends a path to the base URI" do
12
- uri = @klass.send(:uri_for, "search")
13
- uri.host.should == "www.example.org"
14
- uri.path.should == "/search"
15
- uri.query_values.should == {"developer" => "Valve"}
16
- end
17
-
18
- it "appends a query to the base URI" do
19
- uri = @klass.send(:uri_for, "search", {"cake" => "Lie"})
20
- uri.host.should == "www.example.org"
21
- uri.path.should == "/search"
22
- uri.query_values.should == {"developer" => "Valve", "cake" => "Lie"}
23
- end
24
-
25
- end
26
-
27
- describe SMG::HTTP::Model do
28
-
29
- before :all do
30
- @klass = Class.new { include SMG::Resource, SMG::HTTP }
31
- @klass.site "http://www.example.org"
32
- @klass.params "developer" => "Valve"
33
- @klass.extract "game/name"
34
- end
35
-
36
- Hash[[:get, :post, :put, :delete, :head].zip(SMG::HTTP::Request::VERBS)].each do |sym,verb|
37
- describe ".#{sym}" do
38
-
39
- before :each do
40
- @response = Net::HTTPOK.new('1.1', 200, "OK")
41
- @response.stub!(:body).and_return("<game><name>Portal</name></game>")
42
- end
43
-
44
- before :each do
45
- @request = mock('request')
46
- @request.stub!(:perform).and_return(@response)
47
- end
48
-
49
- before :each do
50
- @headers = {"Accept-Encoding" => "gzip,deflate;*;q=0"}
51
- @options = {:query => {"cake" => "LIE"}, :headers => @headers}
52
- SMG::HTTP::Request.should_receive(:new).
53
- with(verb, instance_of(Addressable::URI), {:headers => @headers}).
54
- and_return(@request)
55
- end
56
-
57
- it "performs #{sym.to_s.upcase} request" do
58
- @klass.send(sym, "game", @options)
59
- end
60
-
61
- it "parses response' body when no block given" do
62
- @game = @klass.send(sym, "game", @options)
63
- @game.name.should == "Portal"
64
- end
65
-
66
- it "yields response and parses the block returning value when block given" do
67
- @game = @klass.send(sym, "game", @options) { |response| "<game><name>Portal2</name></game>" }
68
- @game.name.should == "Portal2"
69
- end
70
-
71
- end
72
- end
73
-
74
- end
75
-
76
- # EOF
@@ -1,27 +0,0 @@
1
- module Spec #:nodoc:
2
- module Helpers #:nodoc:
3
- module HTTPHelpers
4
-
5
- def http(uri, proxy = nil)
6
- @http ||= mock('http')
7
- uri = Addressable::URI.parse(uri)
8
- args = (proxy && p = Addressable::URI.parse(proxy)) ?
9
- [uri.host, uri.port, p.host, p.port, p.user, p.password] :
10
- [uri.host, uri.port]
11
-
12
- Net::HTTP.should_receive(:new).with(*args).and_return(@http)
13
- end
14
-
15
- def stub_response(code, message, *args)
16
- response = Net::HTTPResponse::CODE_TO_OBJ[code.to_s].new('1.1', code, message)
17
- response.initialize_http_header(Hash === args.last ? args.pop : {})
18
- response.stub!(:body).and_return(args.join) unless args.empty?
19
- @http.should_receive(:request).and_return response
20
- response
21
- end
22
-
23
- end
24
- end
25
- end
26
-
27
- # EOF
@@ -1,38 +0,0 @@
1
- module Spec #:nodoc:
2
- module Matchers #:nodoc:
3
-
4
- #http://github.com/rubyspec/mspec/blob/master/lib/mspec/matchers/have_instance_method.rb
5
- class HaveInstanceMethodMatcher
6
-
7
- def initialize(method, include_super)
8
- @method = method.to_sym
9
- @include_super = include_super
10
- end
11
-
12
- def matches?(mod)
13
- @mod = mod
14
- mod.instance_methods(@include_super).include?(@method) ||
15
- mod.instance_methods(@include_super).include?(@method.to_s)
16
- end
17
-
18
- def failure_message
19
- ["Expected #{@mod} to have instance method '#{@method.to_s}'",
20
- "but it does not"]
21
- end
22
-
23
- def negative_failure_message
24
- ["Expected #{@mod} NOT to have instance method '#{@method.to_s}'",
25
- "but it does"]
26
- end
27
- end
28
-
29
- module HaveInstanceMethodMixin
30
- def have_instance_method(method, include_super=true)
31
- HaveInstanceMethodMatcher.new method, include_super
32
- end
33
- end
34
-
35
- end
36
- end
37
-
38
- # EOF
@@ -1,241 +0,0 @@
1
- require File.expand_path File.join(File.dirname(__FILE__), '..', 'spec_helper')
2
-
3
- describe SMG::Mapping::Element do
4
-
5
- describe "#initialize" do
6
-
7
- it "respects path" do
8
- e = SMG::Mapping::Element.new(['node','subnode'])
9
- e.name.should == :subnode
10
- e.accessor.should == :subnode=
11
-
12
- e = SMG::Mapping::Element.new(['node','ns:subnode'])
13
- e.name.should == :ns_subnode
14
- e.accessor.should == :ns_subnode=
15
-
16
- e = SMG::Mapping::Element.new(['node','subnode'], :nested => true)
17
- e.name.should == :subnode
18
- e.accessor.should == :subnode=
19
-
20
- e = SMG::Mapping::Element.new(['node','ns:subnode'], :nested => true)
21
- e.name.should == :ns_subnode
22
- e.accessor.should == :ns_subnode=
23
- end
24
-
25
- it "respects namespaces" do
26
- end
27
-
28
- it "respects :at option" do
29
- e = SMG::Mapping::Element.new(['node','subnode'], :at => :something)
30
- e.name.should == :something
31
- e.accessor.should == :something=
32
-
33
- e = SMG::Mapping::Element.new(['node','ns:subnode'], :at => :something)
34
- e.name.should == :something
35
- e.accessor.should == :something=
36
-
37
- e = SMG::Mapping::Element.new(['node','subnode'], :at => :something, :nested => true)
38
- e.name.should == :something
39
- e.accessor.should == :something=
40
-
41
- e = SMG::Mapping::Element.new(['node','ns:subnode'], :at => :something, :nested => true)
42
- e.name.should == :something
43
- e.accessor.should == :something=
44
- end
45
-
46
- it "respects :as option" do
47
- e = SMG::Mapping::Element.new(['node','subnode'], :at => :whatever, :as => :something)
48
- e.name.should == :something
49
- e.accessor.should == :something=
50
-
51
- e = SMG::Mapping::Element.new(['node','ns:subnode'], :at => :whatever, :as => :something)
52
- e.name.should == :something
53
- e.accessor.should == :something=
54
-
55
- e = SMG::Mapping::Element.new(['node','subnode'], :as => :whatever, :nested => true)
56
- e.name.should == :whatever
57
- e.accessor.should == :whatever=
58
-
59
- e = SMG::Mapping::Element.new(['node','ns:subnode'], :as => :whatever, :nested => true)
60
- e.name.should == :whatever
61
- e.accessor.should == :whatever=
62
- end
63
-
64
- it "respects :collection option" do
65
- e = SMG::Mapping::Element.new(['node','subnodes'], :collection => true)
66
- e.name.should == :subnodes
67
- e.accessor.should == :append_to_subnodes
68
-
69
- e = SMG::Mapping::Element.new(['node','ns:subnodes'], :collection => true)
70
- e.name.should == :ns_subnodes
71
- e.accessor.should == :append_to_ns_subnodes
72
-
73
- e = SMG::Mapping::Element.new(['node','subnodes'], :at => :something, :collection => true)
74
- e.name.should == :something
75
- e.accessor.should == :append_to_something
76
-
77
- e = SMG::Mapping::Element.new(['node','ns:subnodes'], :at => :something, :collection => true)
78
- e.name.should == :something
79
- e.accessor.should == :append_to_something
80
-
81
- e = SMG::Mapping::Element.new(['node','subnodes'], :at => :whatever, :as => :something, :collection => true)
82
- e.name.should == :something
83
- e.accessor.should == :append_to_something
84
-
85
- e = SMG::Mapping::Element.new(['node','ns:subnodes'], :at => :whatever, :as => :something, :collection => true)
86
- e.name.should == :something
87
- e.accessor.should == :append_to_something
88
-
89
- e = SMG::Mapping::Element.new(['node','subnodes'], :as => :something, :collection => true)
90
- e.name.should == :something
91
- e.accessor.should == :append_to_something
92
-
93
- e = SMG::Mapping::Element.new(['node','ns:subnodes'], :as => :something, :collection => true)
94
- e.name.should == :something
95
- e.accessor.should == :append_to_something
96
- end
97
-
98
- it "defaults @context to nil" do
99
- e = SMG::Mapping::Element.new(['node','subnode'])
100
- e.context.should be_nil
101
- end
102
-
103
- describe "with :class option" do
104
-
105
- it "defines the @data_class if :class is an SMG::Model" do
106
- klass = Class.new { include SMG::Resource }
107
- e = SMG::Mapping::Element.new(['node'], :class => klass)
108
- e.data_class.should == klass
109
- end
110
-
111
- it "defines the @cast_to if :class is a valid typecast" do
112
- klass = Class.new { include SMG::Resource }
113
- e = SMG::Mapping::Element.new(['node'], :class => :string)
114
- e.cast_to.should == :string
115
- end
116
-
117
- it "raises an ArgumentError otherwise" do
118
- lambda { SMG::Mapping::Element.new(['node'], :class => "bogus!")}.
119
- should raise_error ArgumentError, %r{should be an SMG::Model or a valid typecast}
120
- end
121
-
122
- end
123
-
124
- describe "with :context option" do
125
-
126
- it "defaults @context to nil, if :context is an empty Array" do
127
- e = SMG::Mapping::Element.new(['node'], :context => [])
128
- e.context.should be_nil
129
- end
130
-
131
- it "removes duplicates from @context" do
132
-
133
- e = SMG::Mapping::Element.new(['node'], :context => [:foo, :bar, :baz])
134
- e.context.should == [:foo, :bar, :baz]
135
-
136
- e = SMG::Mapping::Element.new(['node'], :context => [:foo, :bar, :foo, :bar, :baz, :baz])
137
- e.context.should == [:foo, :bar, :baz]
138
-
139
- # undestructive
140
- cct = [:foo, :foo, :bar]
141
- e = SMG::Mapping::Element.new(['node','subnode'], :context => cct)
142
- cct.should == [:foo, :foo, :bar]
143
-
144
- end
145
-
146
- it "raises an ArgumentError, if :context is not an Array of Symbols" do
147
- lambda { e = SMG::Mapping::Element.new(['node'], :context => "something") }.
148
- should raise_error ArgumentError, %r{should be an Array of Symbols}
149
-
150
- lambda { e = SMG::Mapping::Element.new(['node'], :context => [42]) }.
151
- should raise_error ArgumentError, %r{should be an Array of Symbols}
152
- end
153
-
154
- end
155
-
156
- end
157
-
158
- describe "#collection?" do
159
-
160
- it "returns true if Element is a collection" do
161
- e = SMG::Mapping::Element.new(['node','subnode'], :collection => true)
162
- e.should be_a_collection
163
- end
164
-
165
- it "returns false otherwise" do
166
- e = SMG::Mapping::Element.new(['node','subnode'])
167
- e.should_not be_a_collection
168
- end
169
-
170
- end
171
-
172
- describe "#cast" do
173
-
174
- it "does nothing if there's no @cast_to" do
175
- e = SMG::Mapping::Element.new(['node'])
176
- thing = "42"
177
- e.cast(thing).should be_eql thing
178
- end
179
-
180
- it "performs the typecast otherwise" do
181
- e = SMG::Mapping::Element.new(['node'], :class => :integer)
182
- thing = "42"
183
- SMG::Mapping::TypeCasts.should_receive(:[]).with(:integer, thing).and_return("42 (typecasted)")
184
- e.cast(thing).should == "42 (typecasted)"
185
- end
186
-
187
- it "raises an ArgumentError if typecasting fails" do
188
- e = SMG::Mapping::Element.new(['node'], :class => :datetime)
189
- lambda { e.cast('42') }.
190
- should raise_error ArgumentError, %r{"42" is not a valid source for :datetime}
191
- end
192
-
193
- end
194
-
195
- describe "#in_context_of?" do
196
-
197
- it "returns true if @context of an Element is a nil" do
198
- e = SMG::Mapping::Element.new(['node','subnode'])
199
- e.context.should == nil
200
- e.in_context_of?(:whatever).should == true
201
- end
202
-
203
- it "returns true if @context of an Element includes context" do
204
- e = SMG::Mapping::Element.new(['node','subnode'], :context => [:foo])
205
- e.context.should == [:foo]
206
- e.in_context_of?(:foo).should == true
207
- end
208
-
209
- it "returns false otherwise" do
210
- e = SMG::Mapping::Element.new(['node','subnode'], :context => [:foo])
211
- e.context.should == [:foo]
212
- e.in_context_of?(:bar).should == false
213
- end
214
-
215
- end
216
-
217
- describe "#with?" do
218
-
219
- it "returns true if the Hash passed contains @with" do
220
- e = SMG::Mapping::Element.new(['node'], :with => {"id" => "3", "status" => "accepted"})
221
- e.should be_with("id" => "3", "status" => "accepted")
222
- e.should be_with("id" => "3", "status" => "accepted", "key" => "value")
223
- end
224
-
225
- it "returns true if there are no @with conditions" do
226
- e = SMG::Mapping::Element.new(['node','subnode'])
227
- e.with.should == nil
228
- e.should be_with("key" => "value")
229
- end
230
-
231
- it "returns false otherwise" do
232
- e = SMG::Mapping::Element.new(['node'], :with => {"id" => "3", "status" => "accepted"})
233
- e.should_not be_with("status" => "accepted")
234
- e.should_not be_with({})
235
- end
236
-
237
- end
238
-
239
- end
240
-
241
- # EOF
@@ -1,52 +0,0 @@
1
- require File.expand_path File.join(File.dirname(__FILE__), '..', 'spec_helper')
2
-
3
- describe SMG::Mapping::TypeCasts, "[]" do
4
-
5
- it "raises an ArgumentError when typecast is unknown" do
6
- lambda { SMG::Mapping::TypeCasts[:bogus, "42"] }.should raise_error ArgumentError, %r{Can't typecast to :bogus}
7
- end
8
-
9
- it "is able to typecast (Stringable) into Fixnum" do
10
- SMG::Mapping::TypeCasts[:integer, "42"].should == 42
11
- SMG::Mapping::TypeCasts[:integer, nil ].should == 0
12
- end
13
-
14
- it "is able to typecast (Stringable) into Symbol" do
15
- SMG::Mapping::TypeCasts[:symbol, "something"].should == :something
16
- end
17
-
18
- it "is able to typecast (Stringable) into Time" do
19
- source = 'Thu Apr 15 18:16:23 +0400 2010'
20
- value = SMG::Mapping::TypeCasts[:datetime, source]
21
- value.should == Time.parse(source)
22
- end
23
-
24
- it "is able to typecast (Stringable) into Date" do
25
- source = 'Thu Apr 15 18:16:23 +0400 2010'
26
- value = SMG::Mapping::TypeCasts[:date, source]
27
- value.should == Date.parse(source)
28
- end
29
-
30
- it "is able to typecast (Stringable) into URI" do
31
- source = "http://example.org:4567/foo?bar=baz"
32
- value = SMG::Mapping::TypeCasts[:uri, source]
33
- value.should == URI.parse(source)
34
- end
35
-
36
- it "is able to typecast (Stringable) into Float" do
37
- SMG::Mapping::TypeCasts[ :float , nil ].should == 0.00
38
- SMG::Mapping::TypeCasts[ :float , "42." ].should == 42.00
39
- SMG::Mapping::TypeCasts[ :float , ".42" ].should == 0.42
40
- SMG::Mapping::TypeCasts[ :float , "42" ].should == 42.00
41
- end
42
-
43
- it "is able to typecast (Stringable) into Boolean" do
44
- SMG::Mapping::TypeCasts[ :boolean , nil ].should == nil
45
- SMG::Mapping::TypeCasts[ :boolean , "true" ].should == true
46
- SMG::Mapping::TypeCasts[ :boolean , "something" ].should == true
47
- SMG::Mapping::TypeCasts[ :boolean , "false" ].should == false
48
- end
49
-
50
- end
51
-
52
- # EOF
@@ -1,30 +0,0 @@
1
- require File.expand_path File.join(File.dirname(__FILE__), 'spec_helper')
2
-
3
- describe SMG::Resource do
4
-
5
- before :each do
6
- @klass = Class.new { include SMG::Resource }
7
- end
8
-
9
- describe "when included" do
10
-
11
- it "extends class with the SMG::Model" do
12
- @klass.should be_an SMG::Model
13
- end
14
-
15
- end
16
-
17
- describe "#parsed!" do
18
-
19
- it "marks resource as parsed" do
20
- resource = @klass.new
21
- resource.should_not be_parsed
22
- resource.parsed!
23
- resource.should be_parsed
24
- end
25
-
26
- end
27
-
28
- end
29
-
30
- # EOF