monster_mash 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.document +5 -0
- data/.gitignore +21 -0
- data/LICENSE +20 -0
- data/README.rdoc +19 -0
- data/Rakefile +48 -0
- data/VERSION +1 -0
- data/lib/monster_mash.rb +8 -0
- data/lib/monster_mash/base.rb +111 -0
- data/lib/monster_mash/inheritable_attributes.rb +25 -0
- data/lib/monster_mash/instance_exec.rb +33 -0
- data/lib/monster_mash/request.rb +81 -0
- data/monster_mash.gemspec +69 -0
- data/spec/cache/errors/578ef7e62373286feb3e35a6042555a6c0dcde08.cache +22 -0
- data/spec/cache/google/cfd676f5f3b7aefc1b4a9038eb4a4de00d2608c8.cache +26 -0
- data/spec/monster_mash/base_spec.rb +225 -0
- data/spec/monster_mash/request_spec.rb +109 -0
- data/spec/spec.opts +2 -0
- data/spec/spec_helper.rb +12 -0
- metadata +123 -0
data/.document
ADDED
data/.gitignore
ADDED
data/LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright (c) 2009 David Balatero
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.rdoc
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
= monster_mash
|
2
|
+
|
3
|
+
* Typhoeus is an ancient monster.
|
4
|
+
* A monster mash is a dance party.
|
5
|
+
* This library inspired by John Nunemaker's awesomely useful HTTParty.
|
6
|
+
|
7
|
+
== Note on Patches/Pull Requests
|
8
|
+
|
9
|
+
* Fork the project.
|
10
|
+
* Make your feature addition or bug fix.
|
11
|
+
* Add tests for it. This is important so I don't break it in a
|
12
|
+
future version unintentionally.
|
13
|
+
* Commit, do not mess with rakefile, version, or history.
|
14
|
+
(if you want to have your own version, that is fine but bump version in a commit by itself I can ignore when I pull)
|
15
|
+
* Send me a pull request. Bonus points for topic branches.
|
16
|
+
|
17
|
+
== Copyright
|
18
|
+
|
19
|
+
Copyright (c) 2010 David Balatero. See LICENSE for details.
|
data/Rakefile
ADDED
@@ -0,0 +1,48 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'rake'
|
3
|
+
|
4
|
+
begin
|
5
|
+
require 'jeweler'
|
6
|
+
Jeweler::Tasks.new do |gem|
|
7
|
+
gem.name = "monster_mash"
|
8
|
+
gem.summary = %Q{Provides a fun HTTP interface on top of Typhoeus!}
|
9
|
+
gem.description = %Q{Provides a fun HTTP interface on top of Typhoeus!}
|
10
|
+
gem.email = "dbalatero@gmail.com"
|
11
|
+
gem.homepage = "http://github.com/dbalatero/monster_mash"
|
12
|
+
gem.authors = ["David Balatero"]
|
13
|
+
gem.add_dependency "typhoeus", ">= 0.1.23"
|
14
|
+
gem.add_development_dependency "rspec", ">= 1.2.9"
|
15
|
+
gem.add_development_dependency "typhoeus_spec_cache", ">= 0.2.1"
|
16
|
+
# gem is a Gem::Specification... see http://www.rubygems.org/read/chapter/20 for additional settings
|
17
|
+
end
|
18
|
+
Jeweler::GemcutterTasks.new
|
19
|
+
rescue LoadError
|
20
|
+
puts "Jeweler (or a dependency) not available. Install it with: gem install jeweler"
|
21
|
+
end
|
22
|
+
|
23
|
+
require 'spec/rake/spectask'
|
24
|
+
Spec::Rake::SpecTask.new(:spec) do |spec|
|
25
|
+
spec.libs << 'lib' << 'spec'
|
26
|
+
spec.spec_files = FileList['spec/**/*_spec.rb']
|
27
|
+
end
|
28
|
+
|
29
|
+
Spec::Rake::SpecTask.new(:rcov) do |spec|
|
30
|
+
spec.libs << 'lib' << 'spec'
|
31
|
+
spec.pattern = 'spec/**/*_spec.rb'
|
32
|
+
spec.rcov = true
|
33
|
+
spec.rcov_opts = ['--exclude', 'spec,lib/monster_mash/instance_exec.rb']
|
34
|
+
end
|
35
|
+
|
36
|
+
task :spec => :check_dependencies
|
37
|
+
|
38
|
+
task :default => :spec
|
39
|
+
|
40
|
+
require 'rake/rdoctask'
|
41
|
+
Rake::RDocTask.new do |rdoc|
|
42
|
+
version = File.exist?('VERSION') ? File.read('VERSION') : ""
|
43
|
+
|
44
|
+
rdoc.rdoc_dir = 'rdoc'
|
45
|
+
rdoc.title = "monster_mash #{version}"
|
46
|
+
rdoc.rdoc_files.include('README*')
|
47
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
48
|
+
end
|
data/VERSION
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
0.1.0
|
data/lib/monster_mash.rb
ADDED
@@ -0,0 +1,111 @@
|
|
1
|
+
module MonsterMash
|
2
|
+
class HTTPError < StandardError
|
3
|
+
attr_accessor :response
|
4
|
+
end
|
5
|
+
|
6
|
+
class Base
|
7
|
+
include ClassLevelInheritableAttributes
|
8
|
+
inheritable_attributes :defaults
|
9
|
+
|
10
|
+
attr_accessor :hydra
|
11
|
+
attr_accessor :options
|
12
|
+
|
13
|
+
def initialize(hydra, options = {})
|
14
|
+
self.hydra = hydra
|
15
|
+
self.options = options
|
16
|
+
end
|
17
|
+
|
18
|
+
def self.get(name, &setup_block)
|
19
|
+
build_method(:get, name, &setup_block)
|
20
|
+
end
|
21
|
+
|
22
|
+
def self.post(name, &setup_block)
|
23
|
+
build_method(:post, name, &setup_block)
|
24
|
+
end
|
25
|
+
|
26
|
+
def self.put(name, &setup_block)
|
27
|
+
build_method(:put, name, &setup_block)
|
28
|
+
end
|
29
|
+
|
30
|
+
def self.delete(name, &setup_block)
|
31
|
+
build_method(:delete, name, &setup_block)
|
32
|
+
end
|
33
|
+
|
34
|
+
def self.defaults(&block)
|
35
|
+
if block_given?
|
36
|
+
@defaults = block
|
37
|
+
else
|
38
|
+
@defaults
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
def self.build_method(http_method, name, &setup_block) # :nodoc:
|
43
|
+
if respond_to?(name)
|
44
|
+
raise ArgumentError, "The method name \"#{name}\" is in use!"
|
45
|
+
else
|
46
|
+
method_name = "__real__" << name.to_s
|
47
|
+
define_method(method_name) do |block, *args|
|
48
|
+
self.class.execute(http_method, self.hydra, block, *args, &setup_block)
|
49
|
+
end
|
50
|
+
|
51
|
+
# Define the real instance method for this, and proxy
|
52
|
+
# to the __real__method.
|
53
|
+
class_eval <<-EOF
|
54
|
+
def #{name}(*args, &block)
|
55
|
+
#{method_name}(block, *args)
|
56
|
+
end
|
57
|
+
EOF
|
58
|
+
|
59
|
+
(class << self; self; end).instance_eval do
|
60
|
+
define_method(name) do |*args|
|
61
|
+
execute(http_method, nil, nil, *args, &setup_block)
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
def self.check_response_and_raise!(response)
|
68
|
+
code = response.code.to_i
|
69
|
+
if code < 200 or code >= 400
|
70
|
+
error = MonsterMash::HTTPError.new("Got bad HTTP response! code: #{code}")
|
71
|
+
error.response = response
|
72
|
+
raise error
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
private
|
77
|
+
def self.execute(http_method, hydra, block, *args, &setup_block)
|
78
|
+
# Create the request with defaults.
|
79
|
+
request = MonsterMash::Request.new(http_method, &defaults)
|
80
|
+
|
81
|
+
# Add in user-set values.
|
82
|
+
request.execute_dsl(*args, &setup_block)
|
83
|
+
|
84
|
+
# Validate request.
|
85
|
+
if request.valid?
|
86
|
+
if hydra.nil?
|
87
|
+
# serial request.
|
88
|
+
response = request.run_serial_request
|
89
|
+
request.handler.call(response)
|
90
|
+
else
|
91
|
+
# parallel hydra request.
|
92
|
+
typhoeus_request = request.build_request
|
93
|
+
typhoeus_request.on_complete do |response|
|
94
|
+
result, error = nil, nil
|
95
|
+
begin
|
96
|
+
result = request.handler.call(response)
|
97
|
+
rescue => e
|
98
|
+
error = e
|
99
|
+
end
|
100
|
+
block.call(result, error)
|
101
|
+
end
|
102
|
+
hydra.queue(typhoeus_request)
|
103
|
+
end
|
104
|
+
else
|
105
|
+
raise MonsterMash::InvalidRequest,
|
106
|
+
"Invalid request definition for #{name}:\n" <<
|
107
|
+
request.errors.collect { |e| " * #{e}" }.join("\n")
|
108
|
+
end
|
109
|
+
end
|
110
|
+
end
|
111
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
module ClassLevelInheritableAttributes
|
2
|
+
def self.included(base)
|
3
|
+
base.extend(ClassMethods)
|
4
|
+
end
|
5
|
+
|
6
|
+
module ClassMethods
|
7
|
+
def inheritable_attributes(*args)
|
8
|
+
@inheritable_attributes ||= [:inheritable_attributes]
|
9
|
+
@inheritable_attributes += args
|
10
|
+
args.each do |arg|
|
11
|
+
class_eval %(
|
12
|
+
class << self; attr_accessor :#{arg} end
|
13
|
+
)
|
14
|
+
end
|
15
|
+
@inheritable_attributes
|
16
|
+
end
|
17
|
+
|
18
|
+
def inherited(subclass)
|
19
|
+
@inheritable_attributes.each do |inheritable_attribute|
|
20
|
+
instance_var = "@#{inheritable_attribute}"
|
21
|
+
subclass.instance_variable_set(instance_var, instance_variable_get(instance_var))
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
# This patch allows calling of instance_exec in Ruby implementations
|
2
|
+
# below 1.8.7.
|
3
|
+
#
|
4
|
+
# Patch taken from activesupport.
|
5
|
+
|
6
|
+
class Object
|
7
|
+
unless defined? instance_exec # 1.9, < 1.8.7
|
8
|
+
module InstanceExecMethods #:nodoc:
|
9
|
+
end
|
10
|
+
include InstanceExecMethods
|
11
|
+
|
12
|
+
# Evaluate the block with the given arguments within the context of
|
13
|
+
# this object, so self is set to the method receiver.
|
14
|
+
#
|
15
|
+
# From Mauricio's http://eigenclass.org/hiki/bounded+space+instance_exec
|
16
|
+
def instance_exec(*args, &block)
|
17
|
+
begin
|
18
|
+
old_critical, Thread.critical = Thread.critical, true
|
19
|
+
n = 0
|
20
|
+
n += 1 while respond_to?(method_name = "__instance_exec#{n}")
|
21
|
+
InstanceExecMethods.module_eval { define_method(method_name, &block) }
|
22
|
+
ensure
|
23
|
+
Thread.critical = old_critical
|
24
|
+
end
|
25
|
+
|
26
|
+
begin
|
27
|
+
send(method_name, *args)
|
28
|
+
ensure
|
29
|
+
InstanceExecMethods.module_eval { remove_method(method_name) } rescue nil
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,81 @@
|
|
1
|
+
module MonsterMash
|
2
|
+
class InvalidRequest < StandardError; end
|
3
|
+
|
4
|
+
class Request
|
5
|
+
attr_accessor :options
|
6
|
+
attr_accessor :errors
|
7
|
+
|
8
|
+
def initialize(http_method, *args, &block)
|
9
|
+
@handler = nil
|
10
|
+
@value = nil
|
11
|
+
|
12
|
+
self.options = { :method => http_method }
|
13
|
+
execute_dsl(*args, &block)
|
14
|
+
end
|
15
|
+
|
16
|
+
def execute_dsl(*args, &block)
|
17
|
+
instance_exec(*args, &block) if block_given?
|
18
|
+
end
|
19
|
+
|
20
|
+
def build_request
|
21
|
+
Typhoeus::Request.new(self.uri, self.options)
|
22
|
+
end
|
23
|
+
|
24
|
+
def run_serial_request
|
25
|
+
Typhoeus::Request.run(self.uri, self.options)
|
26
|
+
end
|
27
|
+
|
28
|
+
def valid?
|
29
|
+
self.errors = []
|
30
|
+
|
31
|
+
if !handler
|
32
|
+
self.errors << 'You need to set a handler block.'
|
33
|
+
end
|
34
|
+
|
35
|
+
if !uri
|
36
|
+
self.errors << 'You need to set a uri.'
|
37
|
+
end
|
38
|
+
|
39
|
+
self.errors.empty?
|
40
|
+
end
|
41
|
+
|
42
|
+
def uri(value = nil)
|
43
|
+
if value
|
44
|
+
@uri = value
|
45
|
+
end
|
46
|
+
@uri
|
47
|
+
end
|
48
|
+
|
49
|
+
def handler(&block)
|
50
|
+
if block_given?
|
51
|
+
@handler = block
|
52
|
+
end
|
53
|
+
@handler
|
54
|
+
end
|
55
|
+
|
56
|
+
# Typhoeus options.
|
57
|
+
[:body, :headers, :timeout, :cache_timeout, :params,
|
58
|
+
:user_agent, :follow_location, :max_redirects,
|
59
|
+
:proxy, :disable_ssl_peer_verification].each do |method|
|
60
|
+
class_eval <<-EOF
|
61
|
+
def #{method}(value = nil, &block)
|
62
|
+
assign_or_return_option!(:#{method}, value, &block)
|
63
|
+
end
|
64
|
+
EOF
|
65
|
+
end
|
66
|
+
|
67
|
+
private
|
68
|
+
def assign_or_return_option!(name, value = nil)
|
69
|
+
symbolized_name = name.to_sym
|
70
|
+
if value
|
71
|
+
if self.options[symbolized_name].respond_to?(:merge) and value.respond_to?(:merge)
|
72
|
+
self.options[symbolized_name].merge!(value)
|
73
|
+
else
|
74
|
+
self.options[symbolized_name] = value
|
75
|
+
end
|
76
|
+
else
|
77
|
+
self.options[symbolized_name]
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
@@ -0,0 +1,69 @@
|
|
1
|
+
# Generated by jeweler
|
2
|
+
# DO NOT EDIT THIS FILE DIRECTLY
|
3
|
+
# Instead, edit Jeweler::Tasks in Rakefile, and run the gemspec command
|
4
|
+
# -*- encoding: utf-8 -*-
|
5
|
+
|
6
|
+
Gem::Specification.new do |s|
|
7
|
+
s.name = %q{monster_mash}
|
8
|
+
s.version = "0.1.0"
|
9
|
+
|
10
|
+
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
|
+
s.authors = ["David Balatero"]
|
12
|
+
s.date = %q{2010-05-04}
|
13
|
+
s.description = %q{Provides a fun HTTP interface on top of Typhoeus!}
|
14
|
+
s.email = %q{dbalatero@gmail.com}
|
15
|
+
s.extra_rdoc_files = [
|
16
|
+
"LICENSE",
|
17
|
+
"README.rdoc"
|
18
|
+
]
|
19
|
+
s.files = [
|
20
|
+
".document",
|
21
|
+
".gitignore",
|
22
|
+
"LICENSE",
|
23
|
+
"README.rdoc",
|
24
|
+
"Rakefile",
|
25
|
+
"VERSION",
|
26
|
+
"lib/monster_mash.rb",
|
27
|
+
"lib/monster_mash/base.rb",
|
28
|
+
"lib/monster_mash/inheritable_attributes.rb",
|
29
|
+
"lib/monster_mash/instance_exec.rb",
|
30
|
+
"lib/monster_mash/request.rb",
|
31
|
+
"monster_mash.gemspec",
|
32
|
+
"spec/cache/errors/578ef7e62373286feb3e35a6042555a6c0dcde08.cache",
|
33
|
+
"spec/cache/google/cfd676f5f3b7aefc1b4a9038eb4a4de00d2608c8.cache",
|
34
|
+
"spec/monster_mash/base_spec.rb",
|
35
|
+
"spec/monster_mash/request_spec.rb",
|
36
|
+
"spec/spec.opts",
|
37
|
+
"spec/spec_helper.rb"
|
38
|
+
]
|
39
|
+
s.homepage = %q{http://github.com/dbalatero/monster_mash}
|
40
|
+
s.rdoc_options = ["--charset=UTF-8"]
|
41
|
+
s.require_paths = ["lib"]
|
42
|
+
s.rubygems_version = %q{1.3.6}
|
43
|
+
s.summary = %q{Provides a fun HTTP interface on top of Typhoeus!}
|
44
|
+
s.test_files = [
|
45
|
+
"spec/monster_mash/base_spec.rb",
|
46
|
+
"spec/monster_mash/request_spec.rb",
|
47
|
+
"spec/spec_helper.rb"
|
48
|
+
]
|
49
|
+
|
50
|
+
if s.respond_to? :specification_version then
|
51
|
+
current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
|
52
|
+
s.specification_version = 3
|
53
|
+
|
54
|
+
if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
|
55
|
+
s.add_runtime_dependency(%q<typhoeus>, [">= 0.1.23"])
|
56
|
+
s.add_development_dependency(%q<rspec>, [">= 1.2.9"])
|
57
|
+
s.add_development_dependency(%q<typhoeus_spec_cache>, [">= 0.2.1"])
|
58
|
+
else
|
59
|
+
s.add_dependency(%q<typhoeus>, [">= 0.1.23"])
|
60
|
+
s.add_dependency(%q<rspec>, [">= 1.2.9"])
|
61
|
+
s.add_dependency(%q<typhoeus_spec_cache>, [">= 0.2.1"])
|
62
|
+
end
|
63
|
+
else
|
64
|
+
s.add_dependency(%q<typhoeus>, [">= 0.1.23"])
|
65
|
+
s.add_dependency(%q<rspec>, [">= 1.2.9"])
|
66
|
+
s.add_dependency(%q<typhoeus_spec_cache>, [">= 0.2.1"])
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
@@ -0,0 +1,22 @@
|
|
1
|
+
u:Typhoeus::Response---
|
2
|
+
:headers: |
|
3
|
+
HTTP/1.1 200 OK
|
4
|
+
Cache-Control: no-cache, no-store, max-age=0, must-revalidate
|
5
|
+
Pragma: no-cache
|
6
|
+
Expires: Fri, 01 Jan 1990 00:00:00 GMT
|
7
|
+
Date: Thu, 29 Apr 2010 20:07:27 GMT
|
8
|
+
Content-Type: text/javascript; charset=utf-8
|
9
|
+
X-Embedded-Status: 200
|
10
|
+
X-Content-Type-Options: nosniff
|
11
|
+
X-Frame-Options: SAMEORIGIN
|
12
|
+
X-XSS-Protection: 1; mode=block
|
13
|
+
Server: GSE
|
14
|
+
Transfer-Encoding: chunked
|
15
|
+
|
16
|
+
|
17
|
+
:code: 200
|
18
|
+
:start_time:
|
19
|
+
:requested_http_method:
|
20
|
+
:time: 0.190228
|
21
|
+
:requested_url:
|
22
|
+
:body: "{\"responseData\": {\"results\":[{\"GsearchResultClass\":\"GwebSearch\",\"unescapedUrl\":\"http://twitter.com/dbalatero\",\"url\":\"http://twitter.com/dbalatero\",\"visibleUrl\":\"twitter.com\",\"cacheUrl\":\"http://www.google.com/search?q\\u003dcache:I2apuxLuvJEJ:twitter.com\",\"title\":\"\\u003cb\\u003eDavid Balatero\\u003c/b\\u003e (dbalatero) on Twitter\",\"titleNoFormatting\":\"David Balatero (dbalatero) on Twitter\",\"content\":\"Get short, timely messages from \\u003cb\\u003eDavid Balatero\\u003c/b\\u003e. \\u003cb\\u003e...\\u003c/b\\u003e Name \\u003cb\\u003eDavid Balatero\\u003c/b\\u003e; Location Seattle, WA; Web http://bitwax.cd; Bio computers, cello, bass, startups , \\u003cb\\u003e...\\u003c/b\\u003e\"},{\"GsearchResultClass\":\"GwebSearch\",\"unescapedUrl\":\"http://twitter.com/travismc\",\"url\":\"http://twitter.com/travismc\",\"visibleUrl\":\"twitter.com\",\"cacheUrl\":\"http://www.google.com/search?q\\u003dcache:1i1-2yJ6lVMJ:twitter.com\",\"title\":\"Travis McCoy (travismc) on Twitter\",\"titleNoFormatting\":\"Travis McCoy (travismc) on Twitter\",\"content\":\"Bill Ferrell \\u0026middot; Denis Sosnovtsev \\u0026middot; Noah Weiss \\u0026middot; David Wu \\u0026middot; Esther Gregory \\u0026middot; Karl \\u003cb\\u003e...\\u003c/b\\u003e \\u003cb\\u003eDavid Balatero\\u003c/b\\u003e \\u0026middot; knifefight \\u0026middot; aalevy \\u0026middot; Zach Maier \\u0026middot; Natasha Z. Dadabhoy \\u003cb\\u003e...\\u003c/b\\u003e\"},{\"GsearchResultClass\":\"GwebSearch\",\"unescapedUrl\":\"http://github.com/dbalatero\",\"url\":\"http://github.com/dbalatero\",\"visibleUrl\":\"github.com\",\"cacheUrl\":\"http://www.google.com/search?q\\u003dcache:Hpe7-K1FTgoJ:github.com\",\"title\":\"dbalatero\\u0026#39;s Profile - GitHub\",\"titleNoFormatting\":\"dbalatero\\u0026#39;s Profile - GitHub\",\"content\":\"dbalatero (\\u003cb\\u003eDavid Balatero\\u003c/b\\u003e). You\\u0026#39;re not logged in! Login \\u0026middot; Pricing \\u0026amp; Signup. Name : \\u003cb\\u003eDavid Balatero\\u003c/b\\u003e. Email. Location: Seattle, WA. Member Since: Mar 02, 2009 \\u003cb\\u003e...\\u003c/b\\u003e\"},{\"GsearchResultClass\":\"GwebSearch\",\"unescapedUrl\":\"http://github.com/dbalatero/httparty\",\"url\":\"http://github.com/dbalatero/httparty\",\"visibleUrl\":\"github.com\",\"cacheUrl\":\"http://www.google.com/search?q\\u003dcache:j0vOD5Dd_V0J:github.com\",\"title\":\"dbalatero\\u0026#39;s httparty at master - GitHub\",\"titleNoFormatting\":\"dbalatero\\u0026#39;s httparty at master - GitHub\",\"content\":\"\\u003cb\\u003eDavid Balatero\\u003c/b\\u003e (author). Wed Jul 22 20:28:48 -0700 2009 \\u003cb\\u003e...\\u003c/b\\u003e [\\u003cb\\u003eDavid Balatero\\u003c/b\\u003e]. directory, bin/, Fri Jan 30 21:33:45 -0800 2009, JSON gem no longer dependency \\u003cb\\u003e...\\u003c/b\\u003e\"},{\"GsearchResultClass\":\"GwebSearch\",\"unescapedUrl\":\"http://www.plurk.com/dibid\",\"url\":\"http://www.plurk.com/dibid\",\"visibleUrl\":\"www.plurk.com\",\"cacheUrl\":\"http://www.google.com/search?q\\u003dcache:NTXaJyXNG6gJ:www.plurk.com\",\"title\":\"christine - \\u003cb\\u003eDavid Balatero\\u003c/b\\u003e [dibid] on Plurk\",\"titleNoFormatting\":\"christine - David Balatero [dibid] on Plurk\",\"content\":\"christine - \\u003cb\\u003eDavid Balatero\\u003c/b\\u003e [dibid] on Plurk. \\u003cb\\u003e...\\u003c/b\\u003e \\u003cb\\u003eDavid Balatero\\u003c/b\\u003e. male. Macasandig, Philippines. ako c david but my friends call me balat. :). Relationship: \\u003cb\\u003e...\\u003c/b\\u003e\"},{\"GsearchResultClass\":\"GwebSearch\",\"unescapedUrl\":\"http://www.myspace.com/coalminefiresband\",\"url\":\"http://www.myspace.com/coalminefiresband\",\"visibleUrl\":\"www.myspace.com\",\"cacheUrl\":\"http://www.google.com/search?q\\u003dcache:d5INhINdcT8J:www.myspace.com\",\"title\":\"Coal Mine Fires on MySpace Music - Free Streaming MP3s, Pictures \\u003cb\\u003e...\\u003c/b\\u003e\",\"titleNoFormatting\":\"Coal Mine Fires on MySpace Music - Free Streaming MP3s, Pictures ...\",\"content\":\"\\u003cb\\u003eDavid Balatero\\u003c/b\\u003e - Cello, Double-Bass Abram Shriner - Bass Electrique, \\u003cb\\u003e...\\u003c/b\\u003e My live setup currently consists of \\u003cb\\u003eDavid Balatero\\u003c/b\\u003e, Jack Shriner, and Rob Hanlon. \\u003cb\\u003e...\\u003c/b\\u003e\"},{\"GsearchResultClass\":\"GwebSearch\",\"unescapedUrl\":\"http://www.bassmasta.net/w/wooten_victor/132800.html\",\"url\":\"http://www.bassmasta.net/w/wooten_victor/132800.html\",\"visibleUrl\":\"www.bassmasta.net\",\"cacheUrl\":\"http://www.google.com/search?q\\u003dcache:x-_ddwmFZiUJ:www.bassmasta.net\",\"title\":\"Yinin And Yangin Bass Tab \xE2\x80\x94 (by Wooten Victor)\",\"titleNoFormatting\":\"Yinin And Yangin Bass Tab \xE2\x80\x94 (by Wooten Victor)\",\"content\":\"Tabbed by \\u003cb\\u003eDavid Balatero\\u003c/b\\u003e [\\u003cb\\u003edavid\\u003c/b\\u003e.\\u003cb\\u003ebalatero\\u003c/b\\u003e@attbi.com] May 2, 2002 | http://www. davidbalatero.com #################################################### \\u003cb\\u003e...\\u003c/b\\u003e\"},{\"GsearchResultClass\":\"GwebSearch\",\"unescapedUrl\":\"http://rubylearning.com/blog/2009/06/24/follow-10-rubyists-using-sinatra-on-twitter/\",\"url\":\"http://rubylearning.com/blog/2009/06/24/follow-10-rubyists-using-sinatra-on-twitter/\",\"visibleUrl\":\"rubylearning.com\",\"cacheUrl\":\"http://www.google.com/search?q\\u003dcache:geLCCIZP4EUJ:rubylearning.com\",\"title\":\"Follow 10+ Rubyists using Sinatra on Twitter\",\"titleNoFormatting\":\"Follow 10+ Rubyists using Sinatra on Twitter\",\"content\":\"Jun 24, 2009 \\u003cb\\u003e...\\u003c/b\\u003e \\u003cb\\u003eDavid Balatero\\u003c/b\\u003e June 25, 2009 at 9:59 pm. I\\u0026#39;m using Sinatra as well \xE2\x80\x94 http:// twitter.com/dbalatero \\u003cb\\u003e...\\u003c/b\\u003e\"}],\"cursor\":{\"pages\":[{\"start\":\"0\",\"label\":1},{\"start\":\"8\",\"label\":2},{\"start\":\"16\",\"label\":3},{\"start\":\"24\",\"label\":4},{\"start\":\"32\",\"label\":5},{\"start\":\"40\",\"label\":6},{\"start\":\"48\",\"label\":7},{\"start\":\"56\",\"label\":8}],\"estimatedResultCount\":\"1230\",\"currentPageIndex\":0,\"moreResultsUrl\":\"http://www.google.com/search?oe\\u003dutf8\\u0026ie\\u003dutf8\\u0026source\\u003duds\\u0026start\\u003d0\\u0026hl\\u003den\\u0026q\\u003ddavid+balatero\"}}, \"responseDetails\": null, \"responseStatus\": 200}"
|
@@ -0,0 +1,26 @@
|
|
1
|
+
u:Typhoeus::Response�---
|
2
|
+
:headers: !str
|
3
|
+
str: |
|
4
|
+
HTTP/1.1 200 OK
|
5
|
+
Cache-Control: no-cache, no-store, max-age=0, must-revalidate
|
6
|
+
Pragma: no-cache
|
7
|
+
Expires: Fri, 01 Jan 1990 00:00:00 GMT
|
8
|
+
Date: Thu, 29 Apr 2010 17:43:10 GMT
|
9
|
+
Content-Type: text/javascript; charset=utf-8
|
10
|
+
X-Embedded-Status: 200
|
11
|
+
X-Content-Type-Options: nosniff
|
12
|
+
X-Frame-Options: SAMEORIGIN
|
13
|
+
X-XSS-Protection: 1; mode=block
|
14
|
+
Server: GSE
|
15
|
+
Transfer-Encoding: chunked
|
16
|
+
|
17
|
+
|
18
|
+
"@_rails_html_safe": false
|
19
|
+
:code: 200
|
20
|
+
:start_time:
|
21
|
+
:requested_http_method:
|
22
|
+
:time: 0.237358
|
23
|
+
:requested_url:
|
24
|
+
:body: !str
|
25
|
+
str: "{\"responseData\": {\"results\":[{\"GsearchResultClass\":\"GwebSearch\",\"unescapedUrl\":\"http://www.genealogytoday.com/surname/finder.mv?Surname\\u003dBalatero\",\"url\":\"http://www.genealogytoday.com/surname/finder.mv%3FSurname%3DBalatero\",\"visibleUrl\":\"www.genealogytoday.com\",\"cacheUrl\":\"http://www.google.com/search?q\\u003dcache:5Q-lzaN1lD8J:www.genealogytoday.com\",\"title\":\"\\u003cb\\u003eBalatero\\u003c/b\\u003e Genealogy and Family Tree Resources - Surname Finder\",\"titleNoFormatting\":\"Balatero Genealogy and Family Tree Resources - Surname Finder\",\"content\":\"Free checklist of \\u003cb\\u003eBalatero\\u003c/b\\u003e resources, including online databases, obituaries, surname histories, census and military records, and \\u003cb\\u003eBalatero\\u003c/b\\u003e message boards.\"},{\"GsearchResultClass\":\"GwebSearch\",\"unescapedUrl\":\"http://suzukiassociation.org/author/b/barbara-balatero/\",\"url\":\"http://suzukiassociation.org/author/b/barbara-balatero/\",\"visibleUrl\":\"suzukiassociation.org\",\"cacheUrl\":\"http://www.google.com/search?q\\u003dcache:e20ZSip7HqkJ:suzukiassociation.org\",\"title\":\"Barbara \\u003cb\\u003eBalatero\\u003c/b\\u003e | Authors | Journal | Suzuki Association of the \\u003cb\\u003e...\\u003c/b\\u003e\",\"titleNoFormatting\":\"Barbara Balatero | Authors | Journal | Suzuki Association of the ...\",\"content\":\"Barbara \\u003cb\\u003eBalatero\\u003c/b\\u003e graduated from Oberlin Conservatory with a Bachelors Degree in Cello Performance and a Masters of Music in Teaching where she studied cello \\u003cb\\u003e...\\u003c/b\\u003e\"},{\"GsearchResultClass\":\"GwebSearch\",\"unescapedUrl\":\"http://twitter.com/dbalatero\",\"url\":\"http://twitter.com/dbalatero\",\"visibleUrl\":\"twitter.com\",\"cacheUrl\":\"http://www.google.com/search?q\\u003dcache:I2apuxLuvJEJ:twitter.com\",\"title\":\"David \\u003cb\\u003eBalatero\\u003c/b\\u003e (dbalatero) on Twitter\",\"titleNoFormatting\":\"David Balatero (dbalatero) on Twitter\",\"content\":\"Get short, timely messages from David \\u003cb\\u003eBalatero\\u003c/b\\u003e. \\u003cb\\u003e...\\u003c/b\\u003e Name David \\u003cb\\u003eBalatero\\u003c/b\\u003e; Location Seattle, WA; Web http://bitwax.cd; Bio computers, cello, bass, startups , \\u003cb\\u003e...\\u003c/b\\u003e\"},{\"GsearchResultClass\":\"GwebSearch\",\"unescapedUrl\":\"http://github.com/dbalatero\",\"url\":\"http://github.com/dbalatero\",\"visibleUrl\":\"github.com\",\"cacheUrl\":\"http://www.google.com/search?q\\u003dcache:Hpe7-K1FTgoJ:github.com\",\"title\":\"dbalatero\\u0026#39;s Profile - GitHub\",\"titleNoFormatting\":\"dbalatero\\u0026#39;s Profile - GitHub\",\"content\":\"dbalatero (David \\u003cb\\u003eBalatero\\u003c/b\\u003e). You\\u0026#39;re not logged in! Login \\u0026middot; Pricing \\u0026amp; Signup. Name : David \\u003cb\\u003eBalatero\\u003c/b\\u003e. Email. Location: Seattle, WA. Member Since: Mar 02, 2009 \\u003cb\\u003e...\\u003c/b\\u003e\"},{\"GsearchResultClass\":\"GwebSearch\",\"unescapedUrl\":\"http://www.facebook.com/profile.php?id\\u003d100000758484772\",\"url\":\"http://www.facebook.com/profile.php%3Fid%3D100000758484772\",\"visibleUrl\":\"www.facebook.com\",\"cacheUrl\":\"http://www.google.com/search?q\\u003dcache:WmqpSliPP2UJ:www.facebook.com\",\"title\":\"Elkie \\u003cb\\u003eBalatero\\u003c/b\\u003e | Facebook\",\"titleNoFormatting\":\"Elkie Balatero | Facebook\",\"content\":\"Elkie \\u003cb\\u003eBalatero\\u003c/b\\u003e is on Facebook. Join Facebook to connect with Elkie \\u003cb\\u003eBalatero\\u003c/b\\u003e and others you may know. Facebook gives people the power to share and makes the \\u003cb\\u003e...\\u003c/b\\u003e\"},{\"GsearchResultClass\":\"GwebSearch\",\"unescapedUrl\":\"http://www.travelpuertogalera.com/balatero.htm\",\"url\":\"http://www.travelpuertogalera.com/balatero.htm\",\"visibleUrl\":\"www.travelpuertogalera.com\",\"cacheUrl\":\"http://www.google.com/search?q\\u003dcache:AcJwGQZoG8cJ:www.travelpuertogalera.com\",\"title\":\"Puerto Galera/\\u003cb\\u003eBalatero\\u003c/b\\u003e\",\"titleNoFormatting\":\"Puerto Galera/Balatero\",\"content\":\"and other establishments in \\u003cb\\u003eBalatero\\u003c/b\\u003e, Puerto Galera, Oriental Mindoro, the Philippines \\u003cb\\u003e....\\u003c/b\\u003e Nagura Beach Resort, \\u003cb\\u003eBalatero\\u003c/b\\u003e, Cellular Tel. 0917-6411705 \\u003cb\\u003e...\\u003c/b\\u003e\"},{\"GsearchResultClass\":\"GwebSearch\",\"unescapedUrl\":\"http://members.virtualtourist.com/m/22b26/158575/\",\"url\":\"http://members.virtualtourist.com/m/22b26/158575/\",\"visibleUrl\":\"members.virtualtourist.com\",\"cacheUrl\":\"http://www.google.com/search?q\\u003dcache:AvJUiChXSyUJ:members.virtualtourist.com\",\"title\":\"\\u003cb\\u003eBalatero\\u003c/b\\u003e - \\u003cb\\u003eBalatero\\u003c/b\\u003e, Philippines - VirtualTourist.com\",\"titleNoFormatting\":\"Balatero - Balatero, Philippines - VirtualTourist.com\",\"content\":\"\\u003cb\\u003eBalatero\\u003c/b\\u003e travel tips, recommendations, reviews, photos and more from VirtualTourist member, StefanosS. Get insider travel tips for \\u003cb\\u003eBalatero\\u003c/b\\u003e, \\u003cb\\u003e...\\u003c/b\\u003e\"},{\"GsearchResultClass\":\"GwebSearch\",\"unescapedUrl\":\"http://www.meetup.com/UWStartupWeekend/members/11927921/\",\"url\":\"http://www.meetup.com/UWStartupWeekend/members/11927921/\",\"visibleUrl\":\"www.meetup.com\",\"cacheUrl\":\"http://www.google.com/search?q\\u003dcache:xoC5EPOYVk0J:www.meetup.com\",\"title\":\"Katy \\u003cb\\u003eBalatero\\u003c/b\\u003e - UW Startup Weekend (Seattle, WA) - Meetup.com\",\"titleNoFormatting\":\"Katy Balatero - UW Startup Weekend (Seattle, WA) - Meetup.com\",\"content\":\"Apr 19, 2010 \\u003cb\\u003e...\\u003c/b\\u003e I\\u0026#39;ma graduate student at the UW studying digital media communications. I don\\u0026#39;t have a solid startup idea, but I am interested in finding a \\u003cb\\u003e...\\u003c/b\\u003e\"}],\"cursor\":{\"pages\":[{\"start\":\"0\",\"label\":1},{\"start\":\"8\",\"label\":2},{\"start\":\"16\",\"label\":3},{\"start\":\"24\",\"label\":4},{\"start\":\"32\",\"label\":5},{\"start\":\"40\",\"label\":6},{\"start\":\"48\",\"label\":7},{\"start\":\"56\",\"label\":8}],\"estimatedResultCount\":\"3230\",\"currentPageIndex\":0,\"moreResultsUrl\":\"http://www.google.com/search?oe\\u003dutf8\\u0026ie\\u003dutf8\\u0026source\\u003duds\\u0026start\\u003d0\\u0026hl\\u003den\\u0026q\\u003dbalatero\"}}, \"responseDetails\": null, \"responseStatus\": 200}"
|
26
|
+
"@_rails_html_safe": false
|
@@ -0,0 +1,225 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/../spec_helper'
|
2
|
+
|
3
|
+
class MockApi < MonsterMash::Base
|
4
|
+
end
|
5
|
+
|
6
|
+
describe MonsterMash::Base do
|
7
|
+
describe "inheriting defaults from superclasses" do
|
8
|
+
class A < MonsterMash::Base
|
9
|
+
defaults do
|
10
|
+
cache_timeout 9999
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
class B < A
|
15
|
+
end
|
16
|
+
|
17
|
+
class C < A
|
18
|
+
defaults do
|
19
|
+
cache_timeout 100
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
it "should propagate defaults to B" do
|
24
|
+
B.defaults.should == A.defaults
|
25
|
+
end
|
26
|
+
|
27
|
+
it "should allow override of defaults by C" do
|
28
|
+
C.defaults.should_not == A.defaults
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
describe "#self.defaults" do
|
33
|
+
it "should default to nil" do
|
34
|
+
MockApi.defaults.should == nil
|
35
|
+
end
|
36
|
+
|
37
|
+
it "should save a defaults proc in the class" do
|
38
|
+
defaults_block = lambda { nil }
|
39
|
+
MockApi.defaults(&defaults_block)
|
40
|
+
|
41
|
+
MockApi.defaults.should == defaults_block
|
42
|
+
MonsterMash::Base.defaults.should == nil
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
describe "#get" do
|
47
|
+
it "should proxy to build_method" do
|
48
|
+
MockApi.should_receive(:build_method).
|
49
|
+
with(:get, :method_name)
|
50
|
+
MockApi.get(:method_name) { nil }
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
describe "#post" do
|
55
|
+
it "should proxy to build_method" do
|
56
|
+
MockApi.should_receive(:build_method).
|
57
|
+
with(:post, :method_name)
|
58
|
+
MockApi.post(:method_name) { nil }
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
describe "#put" do
|
63
|
+
it "should proxy to build_method" do
|
64
|
+
MockApi.should_receive(:build_method).
|
65
|
+
with(:put, :method_name)
|
66
|
+
MockApi.put(:method_name) { nil }
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
describe "#check_response_and_raise!" do
|
71
|
+
before(:each) do
|
72
|
+
@response = mock('response')
|
73
|
+
end
|
74
|
+
|
75
|
+
it "should raise if a response has a code in the wrong range" do
|
76
|
+
bad_codes = [0, 404, 500, 403, 410, 400]
|
77
|
+
bad_codes.each do |code|
|
78
|
+
@response.stub!(:code).and_return(code)
|
79
|
+
lambda {
|
80
|
+
MonsterMash::Base.check_response_and_raise!(@response)
|
81
|
+
}.should raise_error(MonsterMash::HTTPError)
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
it "should not raise if a response has good codes" do
|
86
|
+
good_codes = [200, 204, 301, 302]
|
87
|
+
good_codes.each do |code|
|
88
|
+
@response.stub!(:code).and_return(code)
|
89
|
+
lambda {
|
90
|
+
MonsterMash::Base.check_response_and_raise!(@response)
|
91
|
+
}.should_not raise_error(MonsterMash::HTTPError)
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
it "should propagate the response object with the error" do
|
96
|
+
@response.stub!(:code).and_return(400)
|
97
|
+
error = nil
|
98
|
+
begin
|
99
|
+
MonsterMash::Base.check_response_and_raise!(@response)
|
100
|
+
rescue => e
|
101
|
+
error = e
|
102
|
+
end
|
103
|
+
error.response.should == @response
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
107
|
+
describe "#delete" do
|
108
|
+
it "should proxy to build_method" do
|
109
|
+
MockApi.should_receive(:build_method).
|
110
|
+
with(:delete, :method_name)
|
111
|
+
MockApi.delete(:method_name) { nil }
|
112
|
+
end
|
113
|
+
end
|
114
|
+
|
115
|
+
describe "#self.build_method" do
|
116
|
+
before(:all) do
|
117
|
+
@hydra = mock('hydra')
|
118
|
+
unless MockApi.respond_to?(:my_method)
|
119
|
+
MockApi.build_method(:get, :my_method) do
|
120
|
+
uri 'http://google.com'
|
121
|
+
end
|
122
|
+
end
|
123
|
+
end
|
124
|
+
|
125
|
+
it "should create an instance (async parallel HTTP) method" do
|
126
|
+
api = MockApi.new(@hydra)
|
127
|
+
api.should respond_to(:my_method)
|
128
|
+
end
|
129
|
+
|
130
|
+
it "should create a class (sync serial HTTP) method" do
|
131
|
+
MockApi.should respond_to(:my_method)
|
132
|
+
end
|
133
|
+
|
134
|
+
it "should raise an error if the name is in use" do
|
135
|
+
lambda {
|
136
|
+
MockApi.build_method(:get, :my_method) { nil }
|
137
|
+
}.should raise_error(ArgumentError)
|
138
|
+
end
|
139
|
+
|
140
|
+
describe "checking validity" do
|
141
|
+
it "should raise errors if the request is not valid" do
|
142
|
+
api = MockApi.new(@hydra)
|
143
|
+
lambda {
|
144
|
+
api.my_method
|
145
|
+
}.should raise_error(MonsterMash::InvalidRequest)
|
146
|
+
end
|
147
|
+
end
|
148
|
+
|
149
|
+
describe "error propagation" do
|
150
|
+
typhoeus_spec_cache("spec/cache/errors") do |hydra|
|
151
|
+
before(:all) do
|
152
|
+
class CustomMockError < StandardError; end
|
153
|
+
|
154
|
+
MockApi.build_method(:get, :google_json2) do |search|
|
155
|
+
uri 'http://ajax.googleapis.com/ajax/services/search/web'
|
156
|
+
params({
|
157
|
+
'v' => '1.0',
|
158
|
+
'q' => search,
|
159
|
+
'rsz' => 'large'
|
160
|
+
})
|
161
|
+
cache_timeout 999999
|
162
|
+
handler do |response|
|
163
|
+
raise CustomMockError, "my error"
|
164
|
+
end
|
165
|
+
end
|
166
|
+
end
|
167
|
+
|
168
|
+
it "should raise an error in a serial request" do
|
169
|
+
lambda {
|
170
|
+
MockApi.google_json2('david balatero')
|
171
|
+
}.should raise_error(CustomMockError)
|
172
|
+
end
|
173
|
+
|
174
|
+
it "should propagate the error to the block in parallel request" do
|
175
|
+
api = MockApi.new(hydra)
|
176
|
+
propagated_error = nil
|
177
|
+
api.google_json2('david balatero') do |urls, error|
|
178
|
+
propagated_error = error
|
179
|
+
end
|
180
|
+
propagated_error.should be_an_instance_of(CustomMockError)
|
181
|
+
end
|
182
|
+
end
|
183
|
+
end
|
184
|
+
|
185
|
+
describe "a valid method" do
|
186
|
+
typhoeus_spec_cache("spec/cache/google") do |hydra|
|
187
|
+
before(:all) do
|
188
|
+
MockApi.build_method(:get, :google_json) do |search|
|
189
|
+
uri 'http://ajax.googleapis.com/ajax/services/search/web'
|
190
|
+
params({
|
191
|
+
'v' => '1.0',
|
192
|
+
'q' => search,
|
193
|
+
'rsz' => 'large'
|
194
|
+
})
|
195
|
+
cache_timeout 999999
|
196
|
+
handler do |response|
|
197
|
+
json = JSON.parse(response.body)
|
198
|
+
json['responseData']['results'].map do |result|
|
199
|
+
result['url']
|
200
|
+
end
|
201
|
+
end
|
202
|
+
end
|
203
|
+
end
|
204
|
+
|
205
|
+
it "should do a serial query correctly" do
|
206
|
+
saved_urls = MockApi.google_json('balatero')
|
207
|
+
saved_urls.should have(8).things
|
208
|
+
end
|
209
|
+
|
210
|
+
it "should do a query correctly" do
|
211
|
+
saved_urls = nil
|
212
|
+
api = MockApi.new(hydra)
|
213
|
+
api.google_json('balatero') do |urls, error|
|
214
|
+
if !error
|
215
|
+
saved_urls = urls
|
216
|
+
end
|
217
|
+
end
|
218
|
+
hydra.run
|
219
|
+
|
220
|
+
saved_urls.should have(8).things
|
221
|
+
end
|
222
|
+
end
|
223
|
+
end
|
224
|
+
end
|
225
|
+
end
|
@@ -0,0 +1,109 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/../spec_helper'
|
2
|
+
|
3
|
+
describe MonsterMash::Request do
|
4
|
+
describe "#new" do
|
5
|
+
it "should evaluate the passed in block in context" do
|
6
|
+
foo = nil
|
7
|
+
bar = nil
|
8
|
+
|
9
|
+
request = MonsterMash::Request.new(:get, "query") do |query|
|
10
|
+
foo = self.class
|
11
|
+
bar = query
|
12
|
+
end
|
13
|
+
foo.should == MonsterMash::Request
|
14
|
+
bar.should == 'query'
|
15
|
+
end
|
16
|
+
|
17
|
+
it "should save the method" do
|
18
|
+
request = MonsterMash::Request.new(:get)
|
19
|
+
request.options[:method].should == :get
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
describe "adding to default params" do
|
24
|
+
before(:each) do
|
25
|
+
@request = MonsterMash::Request.new(:get) do
|
26
|
+
params :api_key => 'fdsa',
|
27
|
+
:format => 'json'
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
it "should merge in the params hash" do
|
32
|
+
@request.execute_dsl do
|
33
|
+
params :format => 'xml',
|
34
|
+
:a => 'ok',
|
35
|
+
:b => 'ok2'
|
36
|
+
end
|
37
|
+
|
38
|
+
@request.options[:params].should == {
|
39
|
+
:api_key => 'fdsa',
|
40
|
+
:format => 'xml',
|
41
|
+
:a => 'ok',
|
42
|
+
:b => 'ok2'
|
43
|
+
}
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
describe "#handler" do
|
48
|
+
before(:each) do
|
49
|
+
@request = MonsterMash::Request.new(:get)
|
50
|
+
end
|
51
|
+
|
52
|
+
it "should set the handler" do
|
53
|
+
block = lambda { nil }
|
54
|
+
@request.handler(&block)
|
55
|
+
@request.handler.should == block
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
describe "#valid?" do
|
60
|
+
before(:each) do
|
61
|
+
@request = MonsterMash::Request.new(:get)
|
62
|
+
end
|
63
|
+
|
64
|
+
it "should be valid if there is a URI and a handler" do
|
65
|
+
@request.uri "http://google.com"
|
66
|
+
@request.handler { |response| puts response.body }
|
67
|
+
@request.should be_valid
|
68
|
+
end
|
69
|
+
|
70
|
+
it "should not be valid if there is missing handler" do
|
71
|
+
@request.uri "http://google.com"
|
72
|
+
@request.should_not be_valid
|
73
|
+
@request.errors.should have(1).thing
|
74
|
+
end
|
75
|
+
|
76
|
+
it "should not be valid if there is a missing uri" do
|
77
|
+
@request.handler { |response| puts response.body }
|
78
|
+
@request.should_not be_valid
|
79
|
+
@request.errors.should have(1).thing
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
describe "#uri" do
|
84
|
+
before(:each) do
|
85
|
+
@request = MonsterMash::Request.new(:get)
|
86
|
+
end
|
87
|
+
|
88
|
+
it "should set the uri, and return it" do
|
89
|
+
@request.uri "http://google.com"
|
90
|
+
@request.uri.should == "http://google.com"
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
describe "method_missing methods" do
|
95
|
+
before(:each) do
|
96
|
+
@request = MonsterMash::Request.new(:get)
|
97
|
+
end
|
98
|
+
|
99
|
+
it "should set a correct value" do
|
100
|
+
@request.timeout 100
|
101
|
+
@request.options[:timeout].should == 100
|
102
|
+
end
|
103
|
+
|
104
|
+
it "should have a getter" do
|
105
|
+
@request.timeout 100
|
106
|
+
@request.timeout.should == 100
|
107
|
+
end
|
108
|
+
end
|
109
|
+
end
|
data/spec/spec.opts
ADDED
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,12 @@
|
|
1
|
+
$LOAD_PATH.unshift(File.dirname(__FILE__))
|
2
|
+
$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
|
3
|
+
require 'monster_mash'
|
4
|
+
require 'spec'
|
5
|
+
require 'spec/autorun'
|
6
|
+
require 'typhoeus_spec_cache'
|
7
|
+
require 'json'
|
8
|
+
|
9
|
+
Spec::Runner.configure do |config|
|
10
|
+
config.include(Typhoeus::SpecCacheMacros::InstanceMethods)
|
11
|
+
config.extend(Typhoeus::SpecCacheMacros::ClassMethods)
|
12
|
+
end
|
metadata
ADDED
@@ -0,0 +1,123 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: monster_mash
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
prerelease: false
|
5
|
+
segments:
|
6
|
+
- 0
|
7
|
+
- 1
|
8
|
+
- 0
|
9
|
+
version: 0.1.0
|
10
|
+
platform: ruby
|
11
|
+
authors:
|
12
|
+
- David Balatero
|
13
|
+
autorequire:
|
14
|
+
bindir: bin
|
15
|
+
cert_chain: []
|
16
|
+
|
17
|
+
date: 2010-05-04 00:00:00 -07:00
|
18
|
+
default_executable:
|
19
|
+
dependencies:
|
20
|
+
- !ruby/object:Gem::Dependency
|
21
|
+
name: typhoeus
|
22
|
+
prerelease: false
|
23
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
24
|
+
requirements:
|
25
|
+
- - ">="
|
26
|
+
- !ruby/object:Gem::Version
|
27
|
+
segments:
|
28
|
+
- 0
|
29
|
+
- 1
|
30
|
+
- 23
|
31
|
+
version: 0.1.23
|
32
|
+
type: :runtime
|
33
|
+
version_requirements: *id001
|
34
|
+
- !ruby/object:Gem::Dependency
|
35
|
+
name: rspec
|
36
|
+
prerelease: false
|
37
|
+
requirement: &id002 !ruby/object:Gem::Requirement
|
38
|
+
requirements:
|
39
|
+
- - ">="
|
40
|
+
- !ruby/object:Gem::Version
|
41
|
+
segments:
|
42
|
+
- 1
|
43
|
+
- 2
|
44
|
+
- 9
|
45
|
+
version: 1.2.9
|
46
|
+
type: :development
|
47
|
+
version_requirements: *id002
|
48
|
+
- !ruby/object:Gem::Dependency
|
49
|
+
name: typhoeus_spec_cache
|
50
|
+
prerelease: false
|
51
|
+
requirement: &id003 !ruby/object:Gem::Requirement
|
52
|
+
requirements:
|
53
|
+
- - ">="
|
54
|
+
- !ruby/object:Gem::Version
|
55
|
+
segments:
|
56
|
+
- 0
|
57
|
+
- 2
|
58
|
+
- 1
|
59
|
+
version: 0.2.1
|
60
|
+
type: :development
|
61
|
+
version_requirements: *id003
|
62
|
+
description: Provides a fun HTTP interface on top of Typhoeus!
|
63
|
+
email: dbalatero@gmail.com
|
64
|
+
executables: []
|
65
|
+
|
66
|
+
extensions: []
|
67
|
+
|
68
|
+
extra_rdoc_files:
|
69
|
+
- LICENSE
|
70
|
+
- README.rdoc
|
71
|
+
files:
|
72
|
+
- .document
|
73
|
+
- .gitignore
|
74
|
+
- LICENSE
|
75
|
+
- README.rdoc
|
76
|
+
- Rakefile
|
77
|
+
- VERSION
|
78
|
+
- lib/monster_mash.rb
|
79
|
+
- lib/monster_mash/base.rb
|
80
|
+
- lib/monster_mash/inheritable_attributes.rb
|
81
|
+
- lib/monster_mash/instance_exec.rb
|
82
|
+
- lib/monster_mash/request.rb
|
83
|
+
- monster_mash.gemspec
|
84
|
+
- spec/cache/errors/578ef7e62373286feb3e35a6042555a6c0dcde08.cache
|
85
|
+
- spec/cache/google/cfd676f5f3b7aefc1b4a9038eb4a4de00d2608c8.cache
|
86
|
+
- spec/monster_mash/base_spec.rb
|
87
|
+
- spec/monster_mash/request_spec.rb
|
88
|
+
- spec/spec.opts
|
89
|
+
- spec/spec_helper.rb
|
90
|
+
has_rdoc: true
|
91
|
+
homepage: http://github.com/dbalatero/monster_mash
|
92
|
+
licenses: []
|
93
|
+
|
94
|
+
post_install_message:
|
95
|
+
rdoc_options:
|
96
|
+
- --charset=UTF-8
|
97
|
+
require_paths:
|
98
|
+
- lib
|
99
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
100
|
+
requirements:
|
101
|
+
- - ">="
|
102
|
+
- !ruby/object:Gem::Version
|
103
|
+
segments:
|
104
|
+
- 0
|
105
|
+
version: "0"
|
106
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
107
|
+
requirements:
|
108
|
+
- - ">="
|
109
|
+
- !ruby/object:Gem::Version
|
110
|
+
segments:
|
111
|
+
- 0
|
112
|
+
version: "0"
|
113
|
+
requirements: []
|
114
|
+
|
115
|
+
rubyforge_project:
|
116
|
+
rubygems_version: 1.3.6
|
117
|
+
signing_key:
|
118
|
+
specification_version: 3
|
119
|
+
summary: Provides a fun HTTP interface on top of Typhoeus!
|
120
|
+
test_files:
|
121
|
+
- spec/monster_mash/base_spec.rb
|
122
|
+
- spec/monster_mash/request_spec.rb
|
123
|
+
- spec/spec_helper.rb
|