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 CHANGED
@@ -19,3 +19,4 @@ rdoc
19
19
  pkg
20
20
 
21
21
  ## PROJECT::SPECIFIC
22
+ README.markdown.html
@@ -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.23"
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.0
1
+ 0.1.1
@@ -1,6 +1,5 @@
1
1
  require 'typhoeus'
2
2
 
3
- require File.dirname(__FILE__) + '/monster_mash/inheritable_attributes'
4
3
  files = Dir.glob(File.dirname(__FILE__) + '/**/*.rb')
5
4
  files.each { |f| require f }
6
5
 
@@ -4,9 +4,10 @@ module MonsterMash
4
4
  end
5
5
 
6
6
  class Base
7
- include ClassLevelInheritableAttributes
8
- inheritable_attributes :defaults
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
- @defaults = block
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, &defaults)
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)
@@ -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
@@ -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.0"
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-04}
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.rdoc"
17
+ "README.markdown",
18
+ "README.markdown.html"
18
19
  ]
19
20
  s.files = [
20
21
  ".document",
21
22
  ".gitignore",
22
23
  "LICENSE",
23
- "README.rdoc",
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.23"])
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.23"])
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.23"])
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
- class A < MonsterMash::Base
9
- defaults do
10
- cache_timeout 9999
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
- class B < A
15
- end
16
+ class B < A
17
+ end
16
18
 
17
- class C < A
18
- defaults do
19
- cache_timeout 100
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 nil" do
34
- MockApi.defaults.should == nil
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 == nil
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
- - 0
9
- version: 0.1.0
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-04 00:00:00 -07:00
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
- - 23
31
- version: 0.1.23
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.rdoc
70
+ - README.markdown
71
+ - README.markdown.html
71
72
  files:
72
73
  - .document
73
74
  - .gitignore
74
75
  - LICENSE
75
- - README.rdoc
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: []
@@ -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