monster_mash 0.1.0 → 0.1.1
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +1 -0
- data/README.markdown +146 -0
- data/Rakefile +1 -1
- data/VERSION +1 -1
- data/lib/monster_mash.rb +0 -1
- data/lib/monster_mash/base.rb +12 -5
- data/lib/monster_mash/request.rb +7 -0
- data/monster_mash.gemspec +8 -8
- data/spec/monster_mash/base_spec.rb +18 -13
- data/spec/monster_mash/request_spec.rb +25 -0
- metadata +9 -8
- data/README.rdoc +0 -19
- data/lib/monster_mash/inheritable_attributes.rb +0 -25
data/.gitignore
CHANGED
data/README.markdown
ADDED
@@ -0,0 +1,146 @@
|
|
1
|
+
monster_mash
|
2
|
+
============
|
3
|
+
|
4
|
+
* Typhoeus is an ancient monster.
|
5
|
+
* A monster mash is a dance party.
|
6
|
+
* This library inspired by John Nunemaker's awesomely useful HTTParty.
|
7
|
+
* By law, all Ruby libraries have to have dumbass names.
|
8
|
+
|
9
|
+
This library wraps `Typhoeus` and `Typhoeus::Hydra` and exposes an easy-to-use DSL for quickly building libraries to interact with HTTP resources. Every method you write will automatically export serial (blocking) and parallel (non-blocking) methods, so you can easily parallelize your HTTP code when possible.
|
10
|
+
|
11
|
+
Writing a method
|
12
|
+
----------------
|
13
|
+
|
14
|
+
monster_mash has a Sinatra-like syntax, and lets you build client API methods using the
|
15
|
+
4 HTTP verbs:
|
16
|
+
|
17
|
+
* `get(method_name, &definition_block)`
|
18
|
+
* `post(method_name, &definition_block)`
|
19
|
+
* `put(method_name, &definition_block)`
|
20
|
+
* `delete(method_name, &definition_block)`
|
21
|
+
|
22
|
+
Within each `definition_block`, you can set various Typhoeus options.
|
23
|
+
|
24
|
+
* `uri` **(required)** - the URI to hit
|
25
|
+
* `handler` **(required)** - a block to handle an HTTP response
|
26
|
+
* `params` - hash of URI params
|
27
|
+
* `body` - post body
|
28
|
+
* `headers` - hash of HTTP headers to send
|
29
|
+
* `timeout` - how long to timeout
|
30
|
+
* `cache_timeout` - how long to keep HTTP calls cached
|
31
|
+
* `user_agent` - a User-Agent string to send
|
32
|
+
* `max_redirects` - max number of redirects to follow
|
33
|
+
* `disable_ssl_peer_verification` - whether to disable SSL verification
|
34
|
+
|
35
|
+
Example: Google JSON search
|
36
|
+
---------------------------
|
37
|
+
|
38
|
+
class GoogleJson < MonsterMash::Base
|
39
|
+
VERSION = '1.0'
|
40
|
+
|
41
|
+
# Creates a method called +search+ that takes
|
42
|
+
# a single +query+ parameter.
|
43
|
+
get(:search) do |query|
|
44
|
+
uri "http://ajax.googleapis.com/ajax/services/search/web"
|
45
|
+
params 'v' => VERSION,
|
46
|
+
'q' => query,
|
47
|
+
'rsz' => 'large'
|
48
|
+
handler do |response|
|
49
|
+
json = JSON.parse(response.body)
|
50
|
+
|
51
|
+
# returns results
|
52
|
+
json['responseData']['results']
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
To make serial (blocking) calls using this code, you would then call the class method:
|
58
|
+
|
59
|
+
# blocks
|
60
|
+
results = GoogleJson.search("my search query")
|
61
|
+
results.each do |result|
|
62
|
+
puts result['unescapedUrl']
|
63
|
+
# do other stuff with the response
|
64
|
+
end
|
65
|
+
|
66
|
+
The `search(query)` method returns whatever your `handler` block returns.
|
67
|
+
|
68
|
+
To make parallel (non-blocking) calls, you need an instance of Typhoeus::Hydra:
|
69
|
+
|
70
|
+
hydra = Typhoeus::Hydra.new
|
71
|
+
google = GoogleJson.new(hydra)
|
72
|
+
10.times do
|
73
|
+
google.search("my query") do |results, error|
|
74
|
+
if error
|
75
|
+
# handle error
|
76
|
+
else
|
77
|
+
results.each do |result|
|
78
|
+
puts result['unescapedUrl']
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
# blocks until all 10 queries complete.
|
85
|
+
hydra.run
|
86
|
+
|
87
|
+
Setting defaults
|
88
|
+
----------------
|
89
|
+
|
90
|
+
If you have Typhoeus settings you want to happen for every request, you can set them in a defaults block:
|
91
|
+
|
92
|
+
class GoogleJson < MonsterMash::Base
|
93
|
+
defaults do
|
94
|
+
user_agent "GoogleJson Ruby Library"
|
95
|
+
disable_ssl_peer_verification true
|
96
|
+
end
|
97
|
+
|
98
|
+
# ...
|
99
|
+
end
|
100
|
+
|
101
|
+
As well, if you set `params` or `headers` in the `defaults` block, any `params` or `headers` added later will be `merge`d into the hash.
|
102
|
+
|
103
|
+
class GoogleJson < MonsterMash::Base
|
104
|
+
defaults do
|
105
|
+
params 'api_key' => 'fdas'
|
106
|
+
end
|
107
|
+
|
108
|
+
# The full params hash will look like:
|
109
|
+
# :q => +query+,
|
110
|
+
# :v => '1.0',
|
111
|
+
# :api_key => 'fdas'
|
112
|
+
get(:search) do |query|
|
113
|
+
params 'q' => query,
|
114
|
+
'v' => '1.0'
|
115
|
+
uri "..."
|
116
|
+
handler do |response|
|
117
|
+
# ...
|
118
|
+
end
|
119
|
+
end
|
120
|
+
end
|
121
|
+
|
122
|
+
Error Handling
|
123
|
+
--------------
|
124
|
+
|
125
|
+
* All serial (blocking) methods will simply raise an error if anything wrong happens. You just need to `rescue` said error.
|
126
|
+
* When interacting with Hydra requests, the block you pass to it will receive an error to it if any error was caught during the `handler`'s run. You need to check for the error in your block and handle it there.
|
127
|
+
|
128
|
+
Example Projects using monster_mash
|
129
|
+
-----------------------------------
|
130
|
+
* http://github.com/dbalatero/alchemy_api
|
131
|
+
|
132
|
+
Note on Patches/Pull Requests
|
133
|
+
-----------------------------
|
134
|
+
|
135
|
+
* Fork the project.
|
136
|
+
* Make your feature addition or bug fix.
|
137
|
+
* Add tests for it. This is important so I don't break it in a
|
138
|
+
future version unintentionally.
|
139
|
+
* Commit, do not mess with rakefile, version, or history.
|
140
|
+
(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)
|
141
|
+
* Send me a pull request. Bonus points for topic branches.
|
142
|
+
|
143
|
+
Copyright
|
144
|
+
---------
|
145
|
+
|
146
|
+
Copyright (c) 2010 David Balatero. See LICENSE for details.
|
data/Rakefile
CHANGED
@@ -10,7 +10,7 @@ begin
|
|
10
10
|
gem.email = "dbalatero@gmail.com"
|
11
11
|
gem.homepage = "http://github.com/dbalatero/monster_mash"
|
12
12
|
gem.authors = ["David Balatero"]
|
13
|
-
gem.add_dependency "typhoeus", ">= 0.1.
|
13
|
+
gem.add_dependency "typhoeus", ">= 0.1.25"
|
14
14
|
gem.add_development_dependency "rspec", ">= 1.2.9"
|
15
15
|
gem.add_development_dependency "typhoeus_spec_cache", ">= 0.2.1"
|
16
16
|
# gem is a Gem::Specification... see http://www.rubygems.org/read/chapter/20 for additional settings
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.1.
|
1
|
+
0.1.1
|
data/lib/monster_mash.rb
CHANGED
data/lib/monster_mash/base.rb
CHANGED
@@ -4,9 +4,10 @@ module MonsterMash
|
|
4
4
|
end
|
5
5
|
|
6
6
|
class Base
|
7
|
-
|
8
|
-
|
7
|
+
@defaults = []
|
8
|
+
@has_defaults = false
|
9
9
|
|
10
|
+
attr_accessor :defaults
|
10
11
|
attr_accessor :hydra
|
11
12
|
attr_accessor :options
|
12
13
|
|
@@ -32,8 +33,9 @@ module MonsterMash
|
|
32
33
|
end
|
33
34
|
|
34
35
|
def self.defaults(&block)
|
35
|
-
if block_given?
|
36
|
-
@
|
36
|
+
if block_given? and !@has_defaults
|
37
|
+
@has_defaults = true
|
38
|
+
@defaults << block
|
37
39
|
else
|
38
40
|
@defaults
|
39
41
|
end
|
@@ -73,10 +75,15 @@ module MonsterMash
|
|
73
75
|
end
|
74
76
|
end
|
75
77
|
|
78
|
+
def self.inherited(subclass)
|
79
|
+
subclass.instance_variable_set("@defaults", defaults.dup)
|
80
|
+
end
|
81
|
+
|
76
82
|
private
|
77
83
|
def self.execute(http_method, hydra, block, *args, &setup_block)
|
78
84
|
# Create the request with defaults.
|
79
|
-
request = MonsterMash::Request.new(http_method
|
85
|
+
request = MonsterMash::Request.new(http_method)
|
86
|
+
request.apply_defaults(defaults)
|
80
87
|
|
81
88
|
# Add in user-set values.
|
82
89
|
request.execute_dsl(*args, &setup_block)
|
data/lib/monster_mash/request.rb
CHANGED
@@ -5,6 +5,9 @@ module MonsterMash
|
|
5
5
|
attr_accessor :options
|
6
6
|
attr_accessor :errors
|
7
7
|
|
8
|
+
# Creates a new Request wrapper object.
|
9
|
+
#
|
10
|
+
# @param [Symbol] type of HTTP request - :get, :post, :delete, :put
|
8
11
|
def initialize(http_method, *args, &block)
|
9
12
|
@handler = nil
|
10
13
|
@value = nil
|
@@ -13,6 +16,10 @@ module MonsterMash
|
|
13
16
|
execute_dsl(*args, &block)
|
14
17
|
end
|
15
18
|
|
19
|
+
def apply_defaults(default_blocks)
|
20
|
+
default_blocks.each { |block| execute_dsl(&block) }
|
21
|
+
end
|
22
|
+
|
16
23
|
def execute_dsl(*args, &block)
|
17
24
|
instance_exec(*args, &block) if block_given?
|
18
25
|
end
|
data/monster_mash.gemspec
CHANGED
@@ -5,27 +5,27 @@
|
|
5
5
|
|
6
6
|
Gem::Specification.new do |s|
|
7
7
|
s.name = %q{monster_mash}
|
8
|
-
s.version = "0.1.
|
8
|
+
s.version = "0.1.1"
|
9
9
|
|
10
10
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
11
|
s.authors = ["David Balatero"]
|
12
|
-
s.date = %q{2010-05-
|
12
|
+
s.date = %q{2010-05-15}
|
13
13
|
s.description = %q{Provides a fun HTTP interface on top of Typhoeus!}
|
14
14
|
s.email = %q{dbalatero@gmail.com}
|
15
15
|
s.extra_rdoc_files = [
|
16
16
|
"LICENSE",
|
17
|
-
"README.
|
17
|
+
"README.markdown",
|
18
|
+
"README.markdown.html"
|
18
19
|
]
|
19
20
|
s.files = [
|
20
21
|
".document",
|
21
22
|
".gitignore",
|
22
23
|
"LICENSE",
|
23
|
-
"README.
|
24
|
+
"README.markdown",
|
24
25
|
"Rakefile",
|
25
26
|
"VERSION",
|
26
27
|
"lib/monster_mash.rb",
|
27
28
|
"lib/monster_mash/base.rb",
|
28
|
-
"lib/monster_mash/inheritable_attributes.rb",
|
29
29
|
"lib/monster_mash/instance_exec.rb",
|
30
30
|
"lib/monster_mash/request.rb",
|
31
31
|
"monster_mash.gemspec",
|
@@ -52,16 +52,16 @@ Gem::Specification.new do |s|
|
|
52
52
|
s.specification_version = 3
|
53
53
|
|
54
54
|
if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
|
55
|
-
s.add_runtime_dependency(%q<typhoeus>, [">= 0.1.
|
55
|
+
s.add_runtime_dependency(%q<typhoeus>, [">= 0.1.25"])
|
56
56
|
s.add_development_dependency(%q<rspec>, [">= 1.2.9"])
|
57
57
|
s.add_development_dependency(%q<typhoeus_spec_cache>, [">= 0.2.1"])
|
58
58
|
else
|
59
|
-
s.add_dependency(%q<typhoeus>, [">= 0.1.
|
59
|
+
s.add_dependency(%q<typhoeus>, [">= 0.1.25"])
|
60
60
|
s.add_dependency(%q<rspec>, [">= 1.2.9"])
|
61
61
|
s.add_dependency(%q<typhoeus_spec_cache>, [">= 0.2.1"])
|
62
62
|
end
|
63
63
|
else
|
64
|
-
s.add_dependency(%q<typhoeus>, [">= 0.1.
|
64
|
+
s.add_dependency(%q<typhoeus>, [">= 0.1.25"])
|
65
65
|
s.add_dependency(%q<rspec>, [">= 1.2.9"])
|
66
66
|
s.add_dependency(%q<typhoeus_spec_cache>, [">= 0.2.1"])
|
67
67
|
end
|
@@ -5,41 +5,46 @@ end
|
|
5
5
|
|
6
6
|
describe MonsterMash::Base do
|
7
7
|
describe "inheriting defaults from superclasses" do
|
8
|
-
|
9
|
-
|
10
|
-
|
8
|
+
before(:all) do
|
9
|
+
class A < MonsterMash::Base
|
10
|
+
defaults do
|
11
|
+
cache_timeout 9999
|
12
|
+
timeout 500
|
13
|
+
end
|
11
14
|
end
|
12
|
-
end
|
13
15
|
|
14
|
-
|
15
|
-
|
16
|
+
class B < A
|
17
|
+
end
|
16
18
|
|
17
|
-
|
18
|
-
|
19
|
-
|
19
|
+
class C < A
|
20
|
+
defaults do
|
21
|
+
cache_timeout 100
|
22
|
+
end
|
20
23
|
end
|
21
24
|
end
|
22
25
|
|
23
26
|
it "should propagate defaults to B" do
|
24
27
|
B.defaults.should == A.defaults
|
28
|
+
B.defaults.should have(1).thing
|
25
29
|
end
|
26
30
|
|
27
31
|
it "should allow override of defaults by C" do
|
28
32
|
C.defaults.should_not == A.defaults
|
33
|
+
C.defaults.should have(2).things
|
29
34
|
end
|
30
35
|
end
|
31
36
|
|
32
37
|
describe "#self.defaults" do
|
33
|
-
it "should default to
|
34
|
-
MockApi.defaults.should ==
|
38
|
+
it "should default to empty array" do
|
39
|
+
MockApi.defaults.should == []
|
35
40
|
end
|
36
41
|
|
37
42
|
it "should save a defaults proc in the class" do
|
38
43
|
defaults_block = lambda { nil }
|
39
44
|
MockApi.defaults(&defaults_block)
|
40
45
|
|
41
|
-
MockApi.defaults.should == defaults_block
|
42
|
-
MonsterMash::Base.defaults.should
|
46
|
+
MockApi.defaults.should == [defaults_block]
|
47
|
+
MonsterMash::Base.defaults.should be_empty
|
43
48
|
end
|
44
49
|
end
|
45
50
|
|
@@ -44,6 +44,31 @@ describe MonsterMash::Request do
|
|
44
44
|
end
|
45
45
|
end
|
46
46
|
|
47
|
+
describe "#apply_defaults" do
|
48
|
+
before(:all) do
|
49
|
+
class ApplyDefaultsA < MonsterMash::Base
|
50
|
+
defaults do
|
51
|
+
timeout 100
|
52
|
+
cache_timeout 9999
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
class ApplyDefaultsB < ApplyDefaultsA
|
57
|
+
defaults do
|
58
|
+
timeout 50
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
it "should apply the defaults in inheritance order" do
|
64
|
+
request = MonsterMash::Request.new(:get)
|
65
|
+
request.apply_defaults(ApplyDefaultsB.defaults)
|
66
|
+
|
67
|
+
request.options[:timeout].should == 50
|
68
|
+
request.options[:cache_timeout].should == 9999
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
47
72
|
describe "#handler" do
|
48
73
|
before(:each) do
|
49
74
|
@request = MonsterMash::Request.new(:get)
|
metadata
CHANGED
@@ -5,8 +5,8 @@ version: !ruby/object:Gem::Version
|
|
5
5
|
segments:
|
6
6
|
- 0
|
7
7
|
- 1
|
8
|
-
-
|
9
|
-
version: 0.1.
|
8
|
+
- 1
|
9
|
+
version: 0.1.1
|
10
10
|
platform: ruby
|
11
11
|
authors:
|
12
12
|
- David Balatero
|
@@ -14,7 +14,7 @@ autorequire:
|
|
14
14
|
bindir: bin
|
15
15
|
cert_chain: []
|
16
16
|
|
17
|
-
date: 2010-05-
|
17
|
+
date: 2010-05-15 00:00:00 -07:00
|
18
18
|
default_executable:
|
19
19
|
dependencies:
|
20
20
|
- !ruby/object:Gem::Dependency
|
@@ -27,8 +27,8 @@ dependencies:
|
|
27
27
|
segments:
|
28
28
|
- 0
|
29
29
|
- 1
|
30
|
-
-
|
31
|
-
version: 0.1.
|
30
|
+
- 25
|
31
|
+
version: 0.1.25
|
32
32
|
type: :runtime
|
33
33
|
version_requirements: *id001
|
34
34
|
- !ruby/object:Gem::Dependency
|
@@ -67,17 +67,17 @@ extensions: []
|
|
67
67
|
|
68
68
|
extra_rdoc_files:
|
69
69
|
- LICENSE
|
70
|
-
- README.
|
70
|
+
- README.markdown
|
71
|
+
- README.markdown.html
|
71
72
|
files:
|
72
73
|
- .document
|
73
74
|
- .gitignore
|
74
75
|
- LICENSE
|
75
|
-
- README.
|
76
|
+
- README.markdown
|
76
77
|
- Rakefile
|
77
78
|
- VERSION
|
78
79
|
- lib/monster_mash.rb
|
79
80
|
- lib/monster_mash/base.rb
|
80
|
-
- lib/monster_mash/inheritable_attributes.rb
|
81
81
|
- lib/monster_mash/instance_exec.rb
|
82
82
|
- lib/monster_mash/request.rb
|
83
83
|
- monster_mash.gemspec
|
@@ -87,6 +87,7 @@ files:
|
|
87
87
|
- spec/monster_mash/request_spec.rb
|
88
88
|
- spec/spec.opts
|
89
89
|
- spec/spec_helper.rb
|
90
|
+
- README.markdown.html
|
90
91
|
has_rdoc: true
|
91
92
|
homepage: http://github.com/dbalatero/monster_mash
|
92
93
|
licenses: []
|
data/README.rdoc
DELETED
@@ -1,19 +0,0 @@
|
|
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.
|
@@ -1,25 +0,0 @@
|
|
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
|