monster_mash 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
data/.document ADDED
@@ -0,0 +1,5 @@
1
+ README.rdoc
2
+ lib/**/*.rb
3
+ bin/*
4
+ features/**/*.feature
5
+ LICENSE
data/.gitignore ADDED
@@ -0,0 +1,21 @@
1
+ ## MAC OS
2
+ .DS_Store
3
+
4
+ ## TEXTMATE
5
+ *.tmproj
6
+ tmtags
7
+
8
+ ## EMACS
9
+ *~
10
+ \#*
11
+ .\#*
12
+
13
+ ## VIM
14
+ *.swp
15
+
16
+ ## PROJECT::GENERAL
17
+ coverage
18
+ rdoc
19
+ pkg
20
+
21
+ ## PROJECT::SPECIFIC
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
@@ -0,0 +1,8 @@
1
+ require 'typhoeus'
2
+
3
+ require File.dirname(__FILE__) + '/monster_mash/inheritable_attributes'
4
+ files = Dir.glob(File.dirname(__FILE__) + '/**/*.rb')
5
+ files.each { |f| require f }
6
+
7
+ module MonsterMash
8
+ end
@@ -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
@@ -0,0 +1,2 @@
1
+ --color
2
+ -b
@@ -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