monster_mash 0.1.0 → 0.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|