her 0.2.5 → 0.2.6
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/.rspec +2 -0
- data/README.md +83 -37
- data/Rakefile +0 -1
- data/UPGRADE.md +13 -13
- data/examples/twitter-oauth/app.rb +6 -5
- data/examples/twitter-search/app.rb +10 -8
- data/her.gemspec +13 -13
- data/lib/her.rb +7 -4
- data/lib/her/api.rb +20 -12
- data/lib/her/collection.rb +12 -0
- data/lib/her/middleware.rb +4 -3
- data/lib/her/middleware/accept_json.rb +15 -0
- data/lib/her/model.rb +8 -8
- data/lib/her/model/hooks.rb +24 -0
- data/lib/her/model/http.rb +19 -19
- data/lib/her/model/orm.rb +59 -46
- data/lib/her/model/relationships.rb +40 -27
- data/lib/her/version.rb +1 -1
- data/spec/api_spec.rb +41 -15
- data/spec/middleware/accept_json_spec.rb +10 -0
- data/spec/model/hooks_spec.rb +7 -7
- data/spec/model/http_spec.rb +44 -59
- data/spec/model/introspection_spec.rb +6 -5
- data/spec/model/orm_spec.rb +128 -23
- data/spec/model/paths_spec.rb +8 -10
- data/spec/model/relationships_spec.rb +54 -10
- data/spec/spec_helper.rb +0 -1
- metadata +59 -69
data/.rspec
ADDED
data/README.md
CHANGED
@@ -1,9 +1,7 @@
|
|
1
|
-
# Her
|
1
|
+
# Her [](http://travis-ci.org/remiprev/her) [](https://gemnasium.com/remiprev/her)
|
2
2
|
|
3
3
|
Her is an ORM (Object Relational Mapper) that maps REST resources to Ruby objects. It is designed to build applications that are powered by a RESTful API instead of a database.
|
4
4
|
|
5
|
-
[](http://travis-ci.org/remiprev/her)
|
6
|
-
|
7
5
|
## Installation
|
8
6
|
|
9
7
|
In your Gemfile, add:
|
@@ -24,10 +22,10 @@ First, you have to define which API your models will be bound to. For example, w
|
|
24
22
|
|
25
23
|
```ruby
|
26
24
|
# config/initializers/her.rb
|
27
|
-
Her::API.setup :
|
28
|
-
|
29
|
-
|
30
|
-
|
25
|
+
Her::API.setup :url => "https://api.example.com" do |connection|
|
26
|
+
connection.use Faraday::Request::UrlEncoded
|
27
|
+
connection.use Her::Middleware::DefaultParseJSON
|
28
|
+
connection.use Faraday::Adapter::NetHttp
|
31
29
|
end
|
32
30
|
```
|
33
31
|
|
@@ -62,13 +60,15 @@ User.find(1)
|
|
62
60
|
# PUT https://api.example.com/users/1 with the data and return+update the User object
|
63
61
|
```
|
64
62
|
|
63
|
+
You can look into the `examples` directory for sample applications using Her.
|
64
|
+
|
65
65
|
## Middleware
|
66
66
|
|
67
|
-
Since Her relies on [Faraday](https://github.com/technoweenie/faraday) to send HTTP requests, you can add additional middleware to handle requests and responses. Using the block in the `setup` call, you have access to Faraday’s `
|
67
|
+
Since Her relies on [Faraday](https://github.com/technoweenie/faraday) to send HTTP requests, you can add additional middleware to handle requests and responses. Using the block in the `setup` call, you have access to Faraday’s `connection` object and are able to customize the middleware stack used on each request and response.
|
68
68
|
|
69
69
|
### Authentication
|
70
70
|
|
71
|
-
Her doesn’t support any kind of authentication. However, it’s very easy to implement one with a request middleware. Using the
|
71
|
+
Her doesn’t support any kind of authentication. However, it’s very easy to implement one with a request middleware. Using the connection block, we add it to the default list of middleware.
|
72
72
|
|
73
73
|
```ruby
|
74
74
|
class MyAuthentication < Faraday::Middleware
|
@@ -82,13 +82,13 @@ class MyAuthentication < Faraday::Middleware
|
|
82
82
|
end
|
83
83
|
end
|
84
84
|
|
85
|
-
Her::API.setup :
|
85
|
+
Her::API.setup :url => "https://api.example.com" do |connection|
|
86
86
|
# This token could be stored in the client session
|
87
|
-
|
87
|
+
connection.use MyAuthentication, :token => "bb2b2dd75413d32c1ac421d39e95b978d1819ff611f68fc2fdd5c8b9c7331192"
|
88
88
|
|
89
|
-
|
90
|
-
|
91
|
-
|
89
|
+
connection.use Faraday::Request::UrlEncoded
|
90
|
+
connection.use Her::Middleware::DefaultParseJSON
|
91
|
+
connection.use Faraday::Adapter::NetHttp
|
92
92
|
end
|
93
93
|
```
|
94
94
|
|
@@ -106,7 +106,7 @@ By default, Her handles JSON data. It expects the resource/collection data to be
|
|
106
106
|
[{ "id" : 1, "name" : "Tobias Fünke" }]
|
107
107
|
```
|
108
108
|
|
109
|
-
However, you can define your own parsing method, using a response middleware. The middleware is expected to set `env[:body]` to a hash with three keys: `data`, `errors` and `metadata`. The following code enables parsing JSON data and treating the result as first-level properties. Using the
|
109
|
+
However, you can define your own parsing method, using a response middleware. The middleware is expected to set `env[:body]` to a hash with three keys: `data`, `errors` and `metadata`. The following code enables parsing JSON data and treating the result as first-level properties. Using the connection block, we then replace the default parser with our custom parser.
|
110
110
|
|
111
111
|
```ruby
|
112
112
|
class MyCustomParser < Faraday::Response::Middleware
|
@@ -120,10 +120,10 @@ class MyCustomParser < Faraday::Response::Middleware
|
|
120
120
|
end
|
121
121
|
end
|
122
122
|
|
123
|
-
Her::API.setup :
|
124
|
-
|
125
|
-
|
126
|
-
|
123
|
+
Her::API.setup :url => "https://api.example.com" do |connection|
|
124
|
+
connection.use Faraday::Request::UrlEncoded
|
125
|
+
connection.use MyCustomParser
|
126
|
+
connection.use Faraday::Adapter::NetHttp
|
127
127
|
end
|
128
128
|
# User.find(1) will now expect "https://api.example.com/users/1" to return something like '{ "result" => { "id": 1, "name": "Tobias Fünke" }, "errors" => [] }'
|
129
129
|
```
|
@@ -151,11 +151,11 @@ TWITTER_CREDENTIALS = {
|
|
151
151
|
:token_secret => ""
|
152
152
|
}
|
153
153
|
|
154
|
-
Her::API.setup :
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
154
|
+
Her::API.setup :url => "https://api.twitter.com/1/" do |connection|
|
155
|
+
connection.use FaradayMiddleware::OAuth, TWITTER_CREDENTIALS
|
156
|
+
connection.use Faraday::Request::UrlEncoded
|
157
|
+
connection.use Her::Middleware::DefaultParseJSON
|
158
|
+
connection.use Faraday::Adapter::NetHttp
|
159
159
|
end
|
160
160
|
|
161
161
|
class Tweet
|
@@ -199,11 +199,11 @@ end
|
|
199
199
|
# We should be probably using something like Memcached here, not a global object
|
200
200
|
$cache = MyCache.new
|
201
201
|
|
202
|
-
Her::API.setup :
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
|
202
|
+
Her::API.setup :url => "https://api.example.com" do |connection|
|
203
|
+
connection.use Faraday::Request::UrlEncoded
|
204
|
+
connection.use FaradayMiddleware::Caching, $cache
|
205
|
+
connection.use Her::Middleware::DefaultParseJSON
|
206
|
+
connection.use Faraday::Adapter::NetHttp
|
207
207
|
end
|
208
208
|
|
209
209
|
class User
|
@@ -403,17 +403,17 @@ It is possible to use different APIs for different models. Instead of calling `H
|
|
403
403
|
```ruby
|
404
404
|
# config/initializers/her.rb
|
405
405
|
$my_api = Her::API.new
|
406
|
-
$my_api.setup :
|
407
|
-
|
408
|
-
|
409
|
-
|
406
|
+
$my_api.setup :url => "https://my_api.example.com" do |connection|
|
407
|
+
connection.use Faraday::Request::UrlEncoded
|
408
|
+
connection.use Her::Middleware::DefaultParseJSON
|
409
|
+
connection.use Faraday::Adapter::NetHttp
|
410
410
|
end
|
411
411
|
|
412
412
|
$other_api = Her::API.new
|
413
|
-
$other_api.setup :
|
414
|
-
|
415
|
-
|
416
|
-
|
413
|
+
$other_api.setup :url => "https://other_api.example.com" do |connection|
|
414
|
+
connection.use Faraday::Request::UrlEncoded
|
415
|
+
connection.use Her::Middleware::DefaultParseJSON
|
416
|
+
connection.use Faraday::Adapter::NetHttp
|
417
417
|
end
|
418
418
|
```
|
419
419
|
|
@@ -437,6 +437,51 @@ Category.all
|
|
437
437
|
# GET https://other_api.example.com/categories
|
438
438
|
```
|
439
439
|
|
440
|
+
## SSL
|
441
|
+
|
442
|
+
When initializing `Her::API`, you can pass any parameter supported by `Faraday.new`. So [to use HTTPS](https://github.com/technoweenie/faraday/wiki/Setting-up-SSL-certificates), you can use Faraday’s `:ssl` option.
|
443
|
+
|
444
|
+
```ruby
|
445
|
+
ssl_options = { :ca_path => "/usr/lib/ssl/certs" }
|
446
|
+
Her::API.setup :url => "https://api.example.com", :ssl => ssl_options do |connection|
|
447
|
+
connection.use Faraday::Request::UrlEncoded
|
448
|
+
connection.use Her::Middleware::DefaultParseJSON
|
449
|
+
connection.use Faraday::Adapter::NetHttp
|
450
|
+
end
|
451
|
+
```
|
452
|
+
|
453
|
+
## Testing
|
454
|
+
|
455
|
+
Using Faraday stubbing feature, it’s very easy to write tests for our models. For example, using [RSpec](https://github.com/rspec/rspec-core):
|
456
|
+
|
457
|
+
```ruby
|
458
|
+
# app/models/post.rb
|
459
|
+
class Post
|
460
|
+
include Her::Model
|
461
|
+
custom_get :popular
|
462
|
+
end
|
463
|
+
|
464
|
+
# spec/models/post.rb
|
465
|
+
describe Post do
|
466
|
+
before do
|
467
|
+
Her::API.setup :url => "http://api.example.com" do |connection|
|
468
|
+
connection.use Her::Middleware::FirstLevelParseJSON
|
469
|
+
connection.use Faraday::Request::UrlEncoded
|
470
|
+
connection.adapter :test do |stub|
|
471
|
+
stub.get("/users/popular") { |env| [200, {}, [{ :id => 1, :name => "Tobias Fünke" }, { :id => 2, :name => "Lindsay Fünke" }].to_json] }
|
472
|
+
end
|
473
|
+
end
|
474
|
+
end
|
475
|
+
|
476
|
+
describe ".popular" do
|
477
|
+
it "should fetch all popular posts" do
|
478
|
+
@posts = Post.popular
|
479
|
+
@posts.length.should == 2
|
480
|
+
end
|
481
|
+
end
|
482
|
+
end
|
483
|
+
```
|
484
|
+
|
440
485
|
## Things to be done
|
441
486
|
|
442
487
|
* Better error handling
|
@@ -464,6 +509,7 @@ These fine folks helped with Her:
|
|
464
509
|
* [@rafaelss](https://github.com/rafaelss)
|
465
510
|
* [@tysontate](https://github.com/tysontate)
|
466
511
|
* [@nfo](https://github.com/nfo)
|
512
|
+
* [@simonprevost](https://github.com/simonprevost)
|
467
513
|
|
468
514
|
## License
|
469
515
|
|
data/Rakefile
CHANGED
data/UPGRADE.md
CHANGED
@@ -1,20 +1,20 @@
|
|
1
|
-
Here is a list of backward-incompatible changes that were introduced while Her is
|
1
|
+
Here is a list of backward-incompatible changes that were introduced while Her is pre-1.0. After reaching 1.0, it will follow the [Semantic Versioning](http://semver.org/) system.
|
2
2
|
|
3
3
|
## 0.2.4
|
4
4
|
|
5
5
|
* Her no longer includes default middleware when making HTTP requests. The user has now to define all the needed middleware. Before:
|
6
6
|
|
7
|
-
Her::API.setup :
|
8
|
-
|
7
|
+
Her::API.setup :url => "https://api.example.com" do |connection|
|
8
|
+
connection.insert(0, FaradayMiddle::OAuth)
|
9
9
|
end
|
10
10
|
|
11
11
|
Now:
|
12
|
-
|
13
|
-
Her::API.setup :
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
12
|
+
|
13
|
+
Her::API.setup :url => "https://api.example.com" do |connection|
|
14
|
+
connection.use FaradayMiddle::OAuth
|
15
|
+
connection.use Her::Middleware::FirstLevelParseJSON
|
16
|
+
connection.use Faraday::Request::UrlEncoded
|
17
|
+
connection.use Faraday::Adapter::NetHttp
|
18
18
|
end
|
19
19
|
|
20
20
|
## 0.2
|
@@ -22,9 +22,9 @@ Here is a list of backward-incompatible changes that were introduced while Her i
|
|
22
22
|
* The default parser middleware has been replaced to treat first-level JSON data as the resource or collection data. Before it expected this:
|
23
23
|
|
24
24
|
{ "data": { "id": 1, "name": "Foo" }, "errors": [] }
|
25
|
-
|
25
|
+
|
26
26
|
Now it expects this (the `errors` key is not treated as resource data):
|
27
|
-
|
27
|
+
|
28
28
|
{ "id": 1, "name": "Foo", "errors": [] }
|
29
|
-
|
30
|
-
If you still want to get the old behavior, you can use `Her::Middleware::SecondLevelParseJSON` instead of `Her::Middleware::FirstLevelParseJSON` in your middleware stack.
|
29
|
+
|
30
|
+
If you still want to get the old behavior, you can use `Her::Middleware::SecondLevelParseJSON` instead of `Her::Middleware::FirstLevelParseJSON` in your middleware stack.
|
@@ -1,7 +1,5 @@
|
|
1
1
|
# Create custom parser
|
2
2
|
class TwitterParser < Faraday::Response::Middleware
|
3
|
-
METADATA_KEYS = [:completed_in, :max_id, :max_id_str, :next_page, :page, :query, :refresh_url, :results_per_page, :since_id, :since_id_str]
|
4
|
-
|
5
3
|
def on_complete(env)
|
6
4
|
json = MultiJson.load(env[:body], :symbolize_keys => true)
|
7
5
|
errors = [json.delete(:error)]
|
@@ -13,6 +11,7 @@ class TwitterParser < Faraday::Response::Middleware
|
|
13
11
|
end
|
14
12
|
end
|
15
13
|
|
14
|
+
# See https://dev.twitter.com/apps
|
16
15
|
TWITTER_CREDENTIALS = {
|
17
16
|
:consumer_key => "",
|
18
17
|
:consumer_secret => "",
|
@@ -21,9 +20,11 @@ TWITTER_CREDENTIALS = {
|
|
21
20
|
}
|
22
21
|
|
23
22
|
# Initialize API
|
24
|
-
Her::API.setup :
|
25
|
-
builder.
|
26
|
-
builder.
|
23
|
+
Her::API.setup :url => "https://api.twitter.com/1/" do |builder|
|
24
|
+
builder.use FaradayMiddleware::OAuth, TWITTER_CREDENTIALS
|
25
|
+
builder.use Faraday::Request::UrlEncoded
|
26
|
+
builder.use TwitterParser
|
27
|
+
builder.use Faraday::Adapter::NetHttp
|
27
28
|
end
|
28
29
|
|
29
30
|
# Define classes
|
@@ -4,10 +4,12 @@ class TwitterSearchParser < Faraday::Response::Middleware
|
|
4
4
|
|
5
5
|
def on_complete(env)
|
6
6
|
json = MultiJson.load(env[:body], :symbolize_keys => true)
|
7
|
+
data = json.delete(:results)
|
8
|
+
errors = [json.delete(:error)].compact
|
7
9
|
env[:body] = {
|
8
|
-
:data =>
|
9
|
-
:errors =>
|
10
|
-
:metadata => json
|
10
|
+
:data => data,
|
11
|
+
:errors => errors,
|
12
|
+
:metadata => json
|
11
13
|
}
|
12
14
|
end
|
13
15
|
end
|
@@ -31,11 +33,11 @@ end
|
|
31
33
|
$cache = MyCache.new
|
32
34
|
|
33
35
|
# Initialize API
|
34
|
-
Her::API.setup :
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
36
|
+
Her::API.setup :url => "http://search.twitter.com" do |connection|
|
37
|
+
connection.use Faraday::Request::UrlEncoded
|
38
|
+
connection.use FaradayMiddleware::Caching, $cache
|
39
|
+
connection.use TwitterSearchParser
|
40
|
+
connection.use Faraday::Adapter::NetHttp
|
39
41
|
end
|
40
42
|
|
41
43
|
# Define classes
|
data/her.gemspec
CHANGED
@@ -8,6 +8,7 @@ Gem::Specification.new do |s|
|
|
8
8
|
s.authors = ["Rémi Prévost"]
|
9
9
|
s.email = ["remi@exomel.com"]
|
10
10
|
s.homepage = "http://remiprev.github.com/her"
|
11
|
+
s.license = "MIT"
|
11
12
|
s.summary = "A simple Representational State Transfer-based Hypertext Transfer Protocol-powered Object Relational Mapper. Her?"
|
12
13
|
s.description = "Her is an ORM that maps REST resources and collections to Ruby objects"
|
13
14
|
|
@@ -16,18 +17,17 @@ Gem::Specification.new do |s|
|
|
16
17
|
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
17
18
|
s.require_paths = ["lib"]
|
18
19
|
|
19
|
-
s.add_development_dependency "rake", "0.9.2
|
20
|
-
s.add_development_dependency "rspec", "2.
|
21
|
-
s.add_development_dependency "yard", "0.
|
22
|
-
s.add_development_dependency "redcarpet", "1
|
23
|
-
s.add_development_dependency "mocha", "0.11
|
24
|
-
s.add_development_dependency "
|
25
|
-
s.add_development_dependency "guard", "
|
26
|
-
s.add_development_dependency "
|
27
|
-
s.add_development_dependency "
|
28
|
-
s.add_development_dependency "growl", "1.0.3"
|
20
|
+
s.add_development_dependency "rake", "~> 0.9.2"
|
21
|
+
s.add_development_dependency "rspec", "~> 2.10"
|
22
|
+
s.add_development_dependency "yard", "~> 0.8"
|
23
|
+
s.add_development_dependency "redcarpet", "~> 2.1"
|
24
|
+
s.add_development_dependency "mocha", "~> 0.11"
|
25
|
+
s.add_development_dependency "guard", "~> 1.0"
|
26
|
+
s.add_development_dependency "guard-rspec", "~> 0.7"
|
27
|
+
s.add_development_dependency "rb-fsevent", "~> 0.9"
|
28
|
+
s.add_development_dependency "growl", "~> 1.0"
|
29
29
|
|
30
|
-
s.add_runtime_dependency "activesupport", "3.2
|
31
|
-
s.add_runtime_dependency "faraday", "0.8
|
32
|
-
s.add_runtime_dependency "multi_json", "1.3
|
30
|
+
s.add_runtime_dependency "activesupport", "~> 3.2"
|
31
|
+
s.add_runtime_dependency "faraday", "~> 0.8"
|
32
|
+
s.add_runtime_dependency "multi_json", "~> 1.3"
|
33
33
|
end
|
data/lib/her.rb
CHANGED
@@ -1,12 +1,15 @@
|
|
1
1
|
require "her/version"
|
2
|
+
|
2
3
|
require "multi_json"
|
3
4
|
require "faraday"
|
4
5
|
require "active_support"
|
5
6
|
require "active_support/inflector"
|
6
7
|
|
8
|
+
require "her/model"
|
9
|
+
require "her/api"
|
10
|
+
require "her/middleware"
|
11
|
+
require "her/errors"
|
12
|
+
require "her/collection"
|
13
|
+
|
7
14
|
module Her
|
8
|
-
autoload :Model, "her/model"
|
9
|
-
autoload :API, "her/api"
|
10
|
-
autoload :Middleware, "her/middleware"
|
11
|
-
autoload :Errors, "her/errors"
|
12
15
|
end
|
data/lib/her/api.rb
CHANGED
@@ -3,7 +3,7 @@ module Her
|
|
3
3
|
# so it knows where to make those requests. In Rails, this is usually done in `config/initializers/her.rb`:
|
4
4
|
class API
|
5
5
|
# @private
|
6
|
-
attr_reader :base_uri, :connection
|
6
|
+
attr_reader :base_uri, :connection, :options
|
7
7
|
|
8
8
|
# Setup a default API connection. Accepted arguments and options are the same as {API#setup}.
|
9
9
|
def self.setup(attrs={}, &block) # {{{
|
@@ -13,13 +13,14 @@ module Her
|
|
13
13
|
|
14
14
|
# Setup the API connection.
|
15
15
|
#
|
16
|
-
# @param [Hash] attrs the options
|
17
|
-
# @option attrs [String] :
|
16
|
+
# @param [Hash] attrs the Faraday options
|
17
|
+
# @option attrs [String] :url The main HTTP API root (eg. `https://api.example.com`)
|
18
|
+
# @option attrs [String] :ssl A hash containing [SSL options](https://github.com/technoweenie/faraday/wiki/Setting-up-SSL-certificates)
|
18
19
|
#
|
19
20
|
# @return Faraday::Connection
|
20
21
|
#
|
21
22
|
# @example Setting up the default API connection
|
22
|
-
# Her::API.setup :
|
23
|
+
# Her::API.setup :url => "https://api.example"
|
23
24
|
#
|
24
25
|
# @example A custom middleware added to the default list
|
25
26
|
# class MyAuthentication < Faraday::Middleware
|
@@ -28,8 +29,10 @@ module Her
|
|
28
29
|
# @all.call(env)
|
29
30
|
# end
|
30
31
|
# end
|
31
|
-
# Her::API.setup :
|
32
|
-
#
|
32
|
+
# Her::API.setup :url => "https://api.example.com" do |connection|
|
33
|
+
# connection.use Faraday::Request::UrlEncoded
|
34
|
+
# connection.use Her::Middleware::DefaultParseJSON
|
35
|
+
# connection.use Faraday::Adapter::NetHttp
|
33
36
|
# end
|
34
37
|
#
|
35
38
|
# @example A custom parse middleware
|
@@ -41,14 +44,17 @@ module Her
|
|
41
44
|
# env[:body] = { :data => json, :errors => errors, :metadata => metadata }
|
42
45
|
# end
|
43
46
|
# end
|
44
|
-
# Her::API.setup :
|
45
|
-
#
|
46
|
-
#
|
47
|
+
# Her::API.setup :url => "https://api.example.com" do |connection|
|
48
|
+
# connection.use Faraday::Request::UrlEncoded
|
49
|
+
# connection.use MyCustomParser
|
50
|
+
# connection.use Faraday::Adapter::NetHttp
|
47
51
|
# end
|
48
52
|
def setup(attrs={}) # {{{
|
49
|
-
|
50
|
-
@
|
51
|
-
|
53
|
+
attrs[:url] = attrs.delete(:base_uri) if attrs.include?(:base_uri) # Support legacy :base_uri option
|
54
|
+
@base_uri = attrs[:url]
|
55
|
+
@options = attrs
|
56
|
+
@connection = Faraday.new(attrs) do |connection|
|
57
|
+
yield connection if block_given?
|
52
58
|
end
|
53
59
|
end # }}}
|
54
60
|
|
@@ -60,8 +66,10 @@ module Her
|
|
60
66
|
def request(attrs={}) # {{{
|
61
67
|
method = attrs.delete(:_method)
|
62
68
|
path = attrs.delete(:_path)
|
69
|
+
headers = attrs.delete(:_headers)
|
63
70
|
attrs.delete_if { |key, value| key.to_s =~ /^_/ } # Remove all internal parameters
|
64
71
|
response = @connection.send method do |request|
|
72
|
+
request.headers.merge!(headers) if headers
|
65
73
|
if method == :get
|
66
74
|
# For GET requests, treat additional parameters as querystring data
|
67
75
|
request.url path, attrs
|