her 0.2.3 → 0.2.4

Sign up to get free protection for your applications and to get access to all the features.
data/README.md CHANGED
@@ -14,13 +14,21 @@ gem "her"
14
14
 
15
15
  That’s it!
16
16
 
17
+ ## Upgrade
18
+
19
+ Please see the [UPGRADE.md](https://github.com/remiprev/her/blob/master/UPGRADE.md) file for backward compability issues.
20
+
17
21
  ## Usage
18
22
 
19
- First, you have to define which API your models will be bound to. For example, with Rails, you would create a new `config/initializers/her.rb` file with this line:
23
+ First, you have to define which API your models will be bound to. For example, with Rails, you would create a new `config/initializers/her.rb` file with these lines:
20
24
 
21
25
  ```ruby
22
26
  # config/initializers/her.rb
23
- Her::API.setup :base_uri => "https://api.example.com"
27
+ Her::API.setup :base_uri => "https://api.example.com" do |builder|
28
+ builder.use Faraday::Request::UrlEncoded
29
+ builder.use Her::Middleware::DefaultParseJSON
30
+ builder.use Faraday::Adapter::NetHttp
31
+ end
24
32
  ```
25
33
 
26
34
  And then to add the ORM behavior to a class, you just have to include `Her::Model` in it:
@@ -56,7 +64,7 @@ User.find(1)
56
64
 
57
65
  ## Middleware
58
66
 
59
- 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 a block in the `setup` call, you have access to Faraday’s `builder` object and are able to customize the middleware stack used on each request and response.
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 `builder` object and are able to customize the middleware stack used on each request and response.
60
68
 
61
69
  ### Authentication
62
70
 
@@ -77,6 +85,10 @@ end
77
85
  Her::API.setup :base_uri => "https://api.example.com" do |builder|
78
86
  # This token could be stored in the client session
79
87
  builder.use MyAuthentication, :token => "bb2b2dd75413d32c1ac421d39e95b978d1819ff611f68fc2fdd5c8b9c7331192"
88
+
89
+ builder.use Faraday::Request::UrlEncoded
90
+ builder.use Her::Middleware::DefaultParseJSON
91
+ builder.use Faraday::Adapter::NetHttp
80
92
  end
81
93
  ```
82
94
 
@@ -86,8 +98,6 @@ Now, each HTTP request made by Her will have the `X-API-Token` header.
86
98
 
87
99
  By default, Her handles JSON data. It expects the resource/collection data to be returned at the first level.
88
100
 
89
- **Note**: *Before 0.2, Her expected the resource/collection data to be returned in a `data` key within the JSON object. If you want the old behavior, you can use the `Her::Middleware::SecondLevelParseJSON` middleware.*
90
-
91
101
  ```javascript
92
102
  // The response of GET /users/1
93
103
  { "id" : 1, "name" : "Tobias Fünke" }
@@ -111,8 +121,9 @@ class MyCustomParser < Faraday::Response::Middleware
111
121
  end
112
122
 
113
123
  Her::API.setup :base_uri => "https://api.example.com" do |builder|
114
- # We use the `swap` method to replace Her’s default parser middleware
115
- builder.swap Her::Middleware::DefaultParseJSON, MyCustomParser
124
+ builder.use Faraday::Request::UrlEncoded
125
+ builder.use MyCustomParser
126
+ builder.use Faraday::Adapter::NetHttp
116
127
  end
117
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" => [] }'
118
129
  ```
@@ -141,8 +152,10 @@ TWITTER_CREDENTIALS = {
141
152
  }
142
153
 
143
154
  Her::API.setup :base_uri => "https://api.twitter.com/1/" do |builder|
144
- # We need to insert the middleware at the beginning of the stack (hence the `insert 0`)
145
- builder.insert 0, FaradayMiddleware::OAuth, TWITTER_CREDENTIALS
155
+ builder.use FaradayMiddleware::OAuth, TWITTER_CREDENTIALS
156
+ builder.use Faraday::Request::UrlEncoded
157
+ builder.use Her::Middleware::DefaultParseJSON
158
+ builder.use Faraday::Adapter::NetHttp
146
159
  end
147
160
 
148
161
  class Tweet
@@ -190,7 +203,10 @@ end
190
203
  $cache = MyCache.new
191
204
 
192
205
  Her::API.setup :base_uri => "https://api.example.com" do |builder|
206
+ builder.use Faraday::Request::UrlEncoded
193
207
  builder.use FaradayMiddleware::Caching, $cache
208
+ builder.use Her::Middleware::DefaultParseJSON
209
+ builder.use Faraday::Adapter::NetHttp
194
210
  end
195
211
 
196
212
  class User
@@ -390,10 +406,18 @@ It is possible to use different APIs for different models. Instead of calling `H
390
406
  ```ruby
391
407
  # config/initializers/her.rb
392
408
  $my_api = Her::API.new
393
- $my_api.setup :base_uri => "https://my_api.example.com"
409
+ $my_api.setup :base_uri => "https://my_api.example.com" do |builder|
410
+ builder.use Faraday::Request::UrlEncoded
411
+ builder.use Her::Middleware::DefaultParseJSON
412
+ builder.use Faraday::Adapter::NetHttp
413
+ end
394
414
 
395
415
  $other_api = Her::API.new
396
- $other_api.setup :base_uri => "https://other_api.example.com"
416
+ $other_api.setup :base_uri => "https://other_api.example.com" do |builder|
417
+ builder.use Faraday::Request::UrlEncoded
418
+ builder.use Her::Middleware::DefaultParseJSON
419
+ builder.use Faraday::Adapter::NetHttp
420
+ end
397
421
  ```
398
422
 
399
423
  You can then define which API a model will use:
@@ -429,6 +453,7 @@ Feel free to contribute and submit issues/pull requests [on GitHub](https://gith
429
453
  * [@EtienneLem](https://github.com/EtienneLem)
430
454
  * [@rafaelss](https://github.com/rafaelss)
431
455
  * [@tysontate](https://github.com/tysontate)
456
+ * [@nfo](https://github.com/nfo)
432
457
 
433
458
  Take a look at the `spec` folder before you do, and make sure `bundle exec rake spec` passes after your modifications :)
434
459
 
@@ -0,0 +1,30 @@
1
+ Here is a list of backward-incompatible changes that were introduced while Her is still \<1.0. After reaching 1.0, it will follow the [Semantic Versioning](http://semver.org/) system.
2
+
3
+ ## 0.2.4
4
+
5
+ * Her no longer includes default middleware when making HTTP requests. The user has now to define all the needed middleware. Before:
6
+
7
+ Her::API.setup :base_uri => "https://api.example.com" do |builder|
8
+ builder.insert(0, FaradayMiddle::OAuth)
9
+ end
10
+
11
+ Now:
12
+
13
+ Her::API.setup :base_uri => "https://api.example.com" do |builder|
14
+ builder.use FaradayMiddle::OAuth
15
+ builder.use Her::Middleware::FirstLevelParseJSON
16
+ builder.use Faraday::Request::UrlEncoded
17
+ builder.use Faraday::Adapter::NetHttp
18
+ end
19
+
20
+ ## 0.2
21
+
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
+
24
+ { "data": { "id": 1, "name": "Foo" }, "errors": [] }
25
+
26
+ Now it expects this (the `errors` key is not treated as resource data):
27
+
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.
@@ -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, :middleware, :connection
6
+ attr_reader :base_uri, :connection
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) # {{{
@@ -15,9 +15,6 @@ module Her
15
15
  #
16
16
  # @param [Hash] attrs the options to create a message with
17
17
  # @option attrs [String] :base_uri The main HTTP API root (eg. `https://api.example.com`)
18
- # @option attrs [Array, Class] :middleware **Deprecated** A list of the only middleware Her will use
19
- # @option attrs [Array, Class] :add_middleware **Deprecated** A list of middleware to add to Her’s default middleware
20
- # @option attrs [Class] :parse_middleware **Deprecated** A middleware that will replace {Her::Middleware::FirstLevelParseJSON} to parse the received JSON
21
18
  #
22
19
  # @return Faraday::Connection
23
20
  #
@@ -50,18 +47,7 @@ module Her
50
47
  # end
51
48
  def setup(attrs={}) # {{{
52
49
  @base_uri = attrs[:base_uri]
53
- @middleware = Her::API.default_middleware
54
-
55
- @middleware = [attrs[:middleware]] if attrs[:middleware]
56
- @middleware = [attrs[:add_middleware]] + @middleware if attrs[:add_middleware]
57
- @middleware = [attrs[:parse_middleware]] + @middleware.reject { |item| item == Her::Middleware::FirstLevelParseJSON } if attrs[:parse_middleware]
58
-
59
- @middleware.flatten!
60
- middleware = @middleware
61
50
  @connection = Faraday.new(:url => @base_uri) do |connection|
62
- middleware.each do |klass|
63
- connection.use klass
64
- end
65
51
  yield connection.builder if block_given?
66
52
  end
67
53
  end # }}}
@@ -93,10 +79,5 @@ module Her
93
79
  def self.default_api(attrs={}) # {{{
94
80
  defined?(@@default_api) ? @@default_api : nil
95
81
  end # }}}
96
-
97
- # @private
98
- def self.default_middleware # {{{
99
- [Her::Middleware::FirstLevelParseJSON, Faraday::Request::UrlEncoded, Faraday::Adapter::NetHttp]
100
- end # }}}
101
82
  end
102
83
  end
@@ -35,7 +35,7 @@ module Her
35
35
  extend Her::Model::Paths
36
36
 
37
37
  # Define default settings
38
- base_path = self.name.split("::").last.downcase.pluralize
38
+ base_path = self.name.split("::").last.underscore.pluralize
39
39
  collection_path "/#{base_path}"
40
40
  resource_path "/#{base_path}/:id"
41
41
  uses_api Her::API.default_api
@@ -42,7 +42,7 @@ module Her
42
42
  # @param [Hash] parsed_data The raw `parsed_data` parsed from the HTTP response
43
43
  def new_collection(parsed_data) # {{{
44
44
  collection_data = parsed_data[:data]
45
- Her::Model::ORM.initialize_collection(self.to_s.downcase.to_sym, collection_data)
45
+ Her::Model::ORM.initialize_collection(self.to_s.underscore, collection_data)
46
46
  end # }}}
47
47
 
48
48
  # Return `true` if a resource was not saved yet
@@ -1,3 +1,3 @@
1
1
  module Her
2
- VERSION = "0.2.3"
2
+ VERSION = "0.2.4"
3
3
  end
@@ -26,27 +26,7 @@ describe Her::API do
26
26
  builder.use Foo
27
27
  builder.use Bar
28
28
  end
29
- @api.connection.builder.handlers.should == [Her::Middleware::FirstLevelParseJSON, Faraday::Request::UrlEncoded, Faraday::Adapter::NetHttp, Foo, Bar]
30
- end # }}}
31
-
32
- it "sets custom middleware with #insert" do # {{{
33
- class Foo; end;
34
- class Bar; end;
35
-
36
- @api = Her::API.new
37
- @api.setup :base_uri => "https://api.example.com" do |builder|
38
- builder.use Foo
39
- builder.insert 0, Bar
40
- end
41
- @api.connection.builder.handlers.should == [Bar, Her::Middleware::FirstLevelParseJSON, Faraday::Request::UrlEncoded, Faraday::Adapter::NetHttp, Foo]
42
- end # }}}
43
-
44
- it "delete some default middleware" do # {{{
45
- @api = Her::API.new
46
- @api.setup :base_uri => "https://api.example.com" do |builder|
47
- builder.delete Faraday::Request::UrlEncoded
48
- end
49
- @api.connection.builder.handlers.should == [Her::Middleware::FirstLevelParseJSON, Faraday::Adapter::NetHttp]
29
+ @api.connection.builder.handlers.should == [Foo, Bar]
50
30
  end # }}}
51
31
  end
52
32
 
@@ -61,7 +41,12 @@ describe Her::API do
61
41
  end
62
42
 
63
43
  @api = Her::API.new
64
- @api.setup :base_uri => "https://api.example.com", :parse_middleware => SimpleParser
44
+ @api.setup :base_uri => "https://api.example.com" do |builder|
45
+ builder.use SimpleParser
46
+ builder.use Faraday::Request::UrlEncoded
47
+ builder.use Faraday::Adapter::NetHttp
48
+ end
49
+
65
50
  parsed_data = @api.request(:_method => :get, :_path => "/foo")
66
51
  parsed_data[:data] == "Foo, it is."
67
52
  end # }}}
@@ -70,7 +55,11 @@ describe Her::API do
70
55
  FakeWeb.register_uri(:get, "https://api.example.com/users/1", :body => MultiJson.dump({ :id => 1, :name => "George Michael Bluth", :errors => ["This is a single error"], :metadata => { :page => 1, :per_page => 10 } }))
71
56
 
72
57
  @api = Her::API.new
73
- @api.setup :base_uri => "https://api.example.com"
58
+ @api.setup :base_uri => "https://api.example.com" do |builder|
59
+ builder.use Her::Middleware::FirstLevelParseJSON
60
+ builder.use Faraday::Request::UrlEncoded
61
+ builder.use Faraday::Adapter::NetHttp
62
+ end
74
63
  parsed_data = @api.request(:_method => :get, :_path => "users/1")
75
64
  parsed_data[:data].should == { :id => 1, :name => "George Michael Bluth" }
76
65
  parsed_data[:errors].should == ["This is a single error"]
@@ -94,8 +83,10 @@ describe Her::API do
94
83
  end
95
84
 
96
85
  @api = Her::API.new
97
- @api.setup :base_uri => "https://api.example.com" do |connection|
98
- connection.swap Her::Middleware::DefaultParseJSON, CustomParser
86
+ @api.setup :base_uri => "https://api.example.com" do |builder|
87
+ builder.use CustomParser
88
+ builder.use Faraday::Request::UrlEncoded
89
+ builder.use Faraday::Adapter::NetHttp
99
90
  end
100
91
  parsed_data = @api.request(:_method => :get, :_path => "users/1")
101
92
  parsed_data[:data].should == { :id => 1, :name => "George Michael Bluth" }
@@ -110,7 +110,12 @@ describe Her::Model::Hooks do
110
110
 
111
111
  context "perform hooks on a model" do
112
112
  before do # {{{
113
- Her::API.setup :base_uri => "https://api.example.com"
113
+ Her::API.setup :base_uri => "https://api.example.com" do |builder|
114
+ builder.use Her::Middleware::FirstLevelParseJSON
115
+ builder.use Faraday::Request::UrlEncoded
116
+ builder.use Faraday::Adapter::NetHttp
117
+ end
118
+
114
119
  FakeWeb.register_uri(:post, "https://api.example.com/users", :body => { :id => 1, :name => "Tobias Fünke" }.to_json)
115
120
  FakeWeb.register_uri(:get, "https://api.example.com/users/1", :body => { :id => 1, :name => "Tobias Fünke" }.to_json)
116
121
  FakeWeb.register_uri(:put, "https://api.example.com/users/1", :body => { :id => 1, :name => "Tobias Fünke" }.to_json)
@@ -29,7 +29,11 @@ describe Her::Model::HTTP do
29
29
 
30
30
  it "binds two models to two different instances of Her::API" do # {{{
31
31
  @api1 = Her::API.new
32
- @api1.setup :base_uri => "https://api1.example.com"
32
+ @api1.setup :base_uri => "https://api1.example.com" do |builder|
33
+ builder.use Her::Middleware::FirstLevelParseJSON
34
+ builder.use Faraday::Request::UrlEncoded
35
+ builder.use Faraday::Adapter::NetHttp
36
+ end
33
37
 
34
38
  spawn_model :User
35
39
  User.uses_api @api1
@@ -39,7 +43,11 @@ describe Her::Model::HTTP do
39
43
  end
40
44
 
41
45
  @api2 = Her::API.new
42
- @api2.setup :base_uri => "https://api2.example.com"
46
+ @api2.setup :base_uri => "https://api2.example.com" do |builder|
47
+ builder.use Her::Middleware::FirstLevelParseJSON
48
+ builder.use Faraday::Request::UrlEncoded
49
+ builder.use Faraday::Adapter::NetHttp
50
+ end
43
51
 
44
52
  spawn_model :Comment
45
53
  Comment.uses_api @api2
@@ -50,7 +58,12 @@ describe Her::Model::HTTP do
50
58
  end # }}}
51
59
 
52
60
  it "binds one model to Her::API and another one to an instance of Her::API" do # {{{
53
- Her::API.setup :base_uri => "https://api1.example.com"
61
+ Her::API.setup :base_uri => "https://api1.example.com" do |builder|
62
+ builder.use Her::Middleware::FirstLevelParseJSON
63
+ builder.use Faraday::Request::UrlEncoded
64
+ builder.use Faraday::Adapter::NetHttp
65
+ end
66
+
54
67
  spawn_model :User
55
68
 
56
69
  User.class_eval do
@@ -58,7 +71,11 @@ describe Her::Model::HTTP do
58
71
  end
59
72
 
60
73
  @api = Her::API.new
61
- @api.setup :base_uri => "https://api2.example.com"
74
+ @api.setup :base_uri => "https://api2.example.com" do |builder|
75
+ builder.use Her::Middleware::FirstLevelParseJSON
76
+ builder.use Faraday::Request::UrlEncoded
77
+ builder.use Faraday::Adapter::NetHttp
78
+ end
62
79
 
63
80
  spawn_model :Comment
64
81
  Comment.uses_api @api
@@ -72,7 +89,12 @@ describe Her::Model::HTTP do
72
89
  context "making HTTP requests" do
73
90
  before do # {{{
74
91
  @api = Her::API.new
75
- @api.setup :base_uri => "https://api.example.com"
92
+ @api.setup :base_uri => "https://api.example.com" do |builder|
93
+ builder.use Her::Middleware::FirstLevelParseJSON
94
+ builder.use Faraday::Request::UrlEncoded
95
+ builder.use Faraday::Adapter::NetHttp
96
+ end
97
+
76
98
  FakeWeb.register_uri(:get, "https://api.example.com/users", :body => [{ :id => 1 }].to_json)
77
99
  FakeWeb.register_uri(:get, "https://api.example.com/users?page=2", :body => [{ :id => 2 }].to_json)
78
100
  FakeWeb.register_uri(:get, "https://api.example.com/users/popular", :body => [{ :id => 1 }, { :id => 2 }].to_json)
@@ -163,7 +185,12 @@ describe Her::Model::HTTP do
163
185
  context "setting custom requests" do
164
186
  before do # {{{
165
187
  @api = Her::API.new
166
- @api.setup :base_uri => "https://api.example.com"
188
+ @api.setup :base_uri => "https://api.example.com" do |builder|
189
+ builder.use Her::Middleware::FirstLevelParseJSON
190
+ builder.use Faraday::Request::UrlEncoded
191
+ builder.use Faraday::Adapter::NetHttp
192
+ end
193
+
167
194
  FakeWeb.register_uri(:get, "https://api.example.com/users/popular", :body => [{ :id => 1 }, { :id => 2 }].to_json)
168
195
  FakeWeb.register_uri(:post, "https://api.example.com/users/from_default", :body => { :id => 4 }.to_json)
169
196
 
@@ -4,7 +4,12 @@ require File.join(File.dirname(__FILE__), "../spec_helper.rb")
4
4
  describe Her::Model::Introspection do
5
5
  context "introspecting a resource" do
6
6
  before do # {{{
7
- Her::API.setup :base_uri => "https://api.example.com"
7
+ Her::API.setup :base_uri => "https://api.example.com" do |builder|
8
+ builder.use Her::Middleware::FirstLevelParseJSON
9
+ builder.use Faraday::Request::UrlEncoded
10
+ builder.use Faraday::Adapter::NetHttp
11
+ end
12
+
8
13
  FakeWeb.register_uri(:get, "https://api.example.com/users/1", :body => { :id => 1, :name => "Tobias Funke" }.to_json)
9
14
  spawn_model :User
10
15
  end # }}}
@@ -5,13 +5,23 @@ describe Her::Model::ORM do
5
5
  context "mapping data to Ruby objects" do
6
6
  before do # {{{
7
7
  api = Her::API.new
8
- api.setup :base_uri => "https://api.example.com"
8
+ api.setup :base_uri => "https://api.example.com" do |builder|
9
+ builder.use Her::Middleware::FirstLevelParseJSON
10
+ builder.use Faraday::Request::UrlEncoded
11
+ builder.use Faraday::Adapter::NetHttp
12
+ end
13
+
9
14
  FakeWeb.register_uri(:get, "https://api.example.com/users/1", :body => { :id => 1, :name => "Tobias Fünke" }.to_json)
10
15
  FakeWeb.register_uri(:get, "https://api.example.com/users", :body => [{ :id => 1, :name => "Tobias Fünke" }, { :id => 2, :name => "Lindsay Fünke" }].to_json)
16
+ FakeWeb.register_uri(:get, "https://api.example.com/admin_users", :body => [{ :id => 1, :name => "Tobias Fünke" }, { :id => 2, :name => "Lindsay Fünke" }].to_json)
11
17
 
12
18
  spawn_model :User do
13
19
  uses_api api
14
20
  end
21
+
22
+ spawn_model :AdminUser do
23
+ uses_api api
24
+ end
15
25
  end # }}}
16
26
 
17
27
  it "maps a single resource to a Ruby object" do # {{{
@@ -24,6 +34,10 @@ describe Her::Model::ORM do
24
34
  @users = User.all
25
35
  @users.length.should == 2
26
36
  @users.first.name.should == "Tobias Fünke"
37
+
38
+ @users = AdminUser.all
39
+ @users.length.should == 2
40
+ @users.first.name.should == "Tobias Fünke"
27
41
  end # }}}
28
42
 
29
43
  it "handles new resource" do # {{{
@@ -37,7 +51,12 @@ describe Her::Model::ORM do
37
51
 
38
52
  context "creating resources" do
39
53
  before do # {{{
40
- Her::API.setup :base_uri => "https://api.example.com"
54
+ Her::API.setup :base_uri => "https://api.example.com" do |builder|
55
+ builder.use Her::Middleware::FirstLevelParseJSON
56
+ builder.use Faraday::Request::UrlEncoded
57
+ builder.use Faraday::Adapter::NetHttp
58
+ end
59
+
41
60
  FakeWeb.register_uri(:post, "https://api.example.com/users", :body => { :id => 1, :fullname => "Tobias Fünke" }.to_json)
42
61
 
43
62
  spawn_model :User
@@ -59,7 +78,12 @@ describe Her::Model::ORM do
59
78
  context "updating resources" do
60
79
  before do # {{{
61
80
  @api = Her::API.new
62
- @api.setup :base_uri => "https://api.example.com"
81
+ @api.setup :base_uri => "https://api.example.com" do |builder|
82
+ builder.use Her::Middleware::FirstLevelParseJSON
83
+ builder.use Faraday::Request::UrlEncoded
84
+ builder.use Faraday::Adapter::NetHttp
85
+ end
86
+
63
87
  FakeWeb.register_uri(:get, "https://api.example.com/users/1", :body => { :id => 1, :fullname => "Tobias Fünke" }.to_json)
64
88
  FakeWeb.register_uri(:put, "https://api.example.com/users/1", :body => { :id => 1, :fullname => "Lindsay Fünke" }.to_json)
65
89
 
@@ -89,7 +113,12 @@ describe Her::Model::ORM do
89
113
  context "deleting resources" do
90
114
  before do # {{{
91
115
  @api = Her::API.new
92
- @api.setup :base_uri => "https://api.example.com"
116
+ @api.setup :base_uri => "https://api.example.com" do |builder|
117
+ builder.use Her::Middleware::FirstLevelParseJSON
118
+ builder.use Faraday::Request::UrlEncoded
119
+ builder.use Faraday::Adapter::NetHttp
120
+ end
121
+
93
122
  FakeWeb.register_uri(:get, "https://api.example.com/users/1", :body => { :id => 1, :fullname => "Tobias Fünke", :active => true }.to_json)
94
123
  FakeWeb.register_uri(:delete, "https://api.example.com/users/1", :body => { :id => 1, :fullname => "Lindsay Fünke", :active => false }.to_json)
95
124
 
@@ -39,6 +39,42 @@ describe Her::Model::Paths do
39
39
  end
40
40
  end
41
41
 
42
+ context "simple model with multiple words" do
43
+ before do # {{{
44
+ spawn_model :AdminUser
45
+ end # }}}
46
+
47
+ describe "#build_request_path" do
48
+ it "builds paths with defaults" do # {{{
49
+ AdminUser.build_request_path(:id => "foo").should == "/admin_users/foo"
50
+ AdminUser.build_request_path.should == "/admin_users"
51
+ end # }}}
52
+
53
+ it "builds paths with custom collection path" do # {{{
54
+ AdminUser.collection_path "/users"
55
+ AdminUser.build_request_path(:id => "foo").should == "/users/foo"
56
+ AdminUser.build_request_path.should == "/users"
57
+ end # }}}
58
+
59
+ it "builds paths with custom collection path with multiple variables" do # {{{
60
+ AdminUser.collection_path "/organizations/:organization_id/users"
61
+ AdminUser.build_request_path(:id => "foo", :_organization_id => "acme").should == "/organizations/acme/users/foo"
62
+ AdminUser.build_request_path(:_organization_id => "acme").should == "/organizations/acme/users"
63
+ end # }}}
64
+
65
+ it "builds paths with custom item path" do # {{{
66
+ AdminUser.resource_path "/users/:id"
67
+ AdminUser.build_request_path(:id => "foo").should == "/users/foo"
68
+ AdminUser.build_request_path.should == "/admin_users"
69
+ end # }}}
70
+
71
+ it "raises exceptions when building a path without required custom variables" do # {{{
72
+ AdminUser.collection_path "/organizations/:organization_id/users"
73
+ expect { AdminUser.build_request_path(:id => "foo") }.should raise_error(Her::Errors::PathError)
74
+ end # }}}
75
+ end
76
+ end
77
+
42
78
  context "nested model" do
43
79
  before do # {{{
44
80
  spawn_submodel :Base, :User
@@ -56,7 +92,12 @@ describe Her::Model::Paths do
56
92
  context "making HTTP requests" do
57
93
  before do # {{{
58
94
  api = Her::API.new
59
- api.setup :base_uri => "https://api.example.com"
95
+ api.setup :base_uri => "https://api.example.com" do |builder|
96
+ builder.use Her::Middleware::FirstLevelParseJSON
97
+ builder.use Faraday::Request::UrlEncoded
98
+ builder.use Faraday::Adapter::NetHttp
99
+ end
100
+
60
101
  FakeWeb.register_uri(:get, "https://api.example.com/organizations/2/users", :body => [{ :id => 1, :fullname => "Tobias Fünke", :organization_id => 2 }, { :id => 2, :fullname => "Lindsay Fünke", :organization_id => 2 }].to_json)
61
102
  FakeWeb.register_uri(:post, "https://api.example.com/organizations/2/users", :body => { :id => 1, :fullname => "Tobias Fünke", :organization_id => 2 }.to_json)
62
103
  FakeWeb.register_uri(:put, "https://api.example.com/organizations/2/users/1", :body => { :id => 1, :fullname => "Lindsay Fünke", :organization_id => 2 }.to_json)
@@ -43,7 +43,12 @@ describe Her::Model::Relationships do
43
43
 
44
44
  context "handling relationships" do
45
45
  before do # {{{
46
- Her::API.setup :base_uri => "https://api.example.com"
46
+ Her::API.setup :base_uri => "https://api.example.com" do |builder|
47
+ builder.use Her::Middleware::FirstLevelParseJSON
48
+ builder.use Faraday::Request::UrlEncoded
49
+ builder.use Faraday::Adapter::NetHttp
50
+ end
51
+
47
52
  FakeWeb.register_uri(:get, "https://api.example.com/users/1", :body => { :id => 1, :name => "Tobias Fünke", :comments => [{ :id => 2, :body => "Tobias, you blow hard!" }, { :id => 3, :body => "I wouldn't mind kissing that man between the cheeks, so to speak" }], :role => { :id => 1, :body => "Admin" }, :organization => { :id => 1, :name => "Bluth Company" }, :organization_id => 1 }.to_json)
48
53
  FakeWeb.register_uri(:get, "https://api.example.com/users/2", :body => { :id => 2, :name => "Lindsay Fünke", :organization_id => 1 }.to_json)
49
54
  FakeWeb.register_uri(:get, "https://api.example.com/users/2/comments", :body => [{ :id => 4, :body => "They're having a FIRESALE?" }, { :id => 5, :body => "Is this the tiny town from Footloose?" }].to_json)
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: her
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.3
4
+ version: 0.2.4
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,151 +9,216 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-05-01 00:00:00.000000000 Z
12
+ date: 2012-05-03 00:00:00.000000000Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: rake
16
- requirement: &70289715223620 !ruby/object:Gem::Requirement
16
+ requirement: !ruby/object:Gem::Requirement
17
17
  none: false
18
18
  requirements:
19
- - - =
19
+ - - '='
20
20
  - !ruby/object:Gem::Version
21
21
  version: 0.9.2.2
22
22
  type: :development
23
23
  prerelease: false
24
- version_requirements: *70289715223620
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - '='
28
+ - !ruby/object:Gem::Version
29
+ version: 0.9.2.2
25
30
  - !ruby/object:Gem::Dependency
26
31
  name: rspec
27
- requirement: &70289715222660 !ruby/object:Gem::Requirement
32
+ requirement: !ruby/object:Gem::Requirement
28
33
  none: false
29
34
  requirements:
30
- - - =
35
+ - - '='
31
36
  - !ruby/object:Gem::Version
32
37
  version: 2.9.0
33
38
  type: :development
34
39
  prerelease: false
35
- version_requirements: *70289715222660
40
+ version_requirements: !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - '='
44
+ - !ruby/object:Gem::Version
45
+ version: 2.9.0
36
46
  - !ruby/object:Gem::Dependency
37
47
  name: yard
38
- requirement: &70289715221300 !ruby/object:Gem::Requirement
48
+ requirement: !ruby/object:Gem::Requirement
39
49
  none: false
40
50
  requirements:
41
- - - =
51
+ - - '='
42
52
  - !ruby/object:Gem::Version
43
53
  version: 0.7.5
44
54
  type: :development
45
55
  prerelease: false
46
- version_requirements: *70289715221300
56
+ version_requirements: !ruby/object:Gem::Requirement
57
+ none: false
58
+ requirements:
59
+ - - '='
60
+ - !ruby/object:Gem::Version
61
+ version: 0.7.5
47
62
  - !ruby/object:Gem::Dependency
48
63
  name: redcarpet
49
- requirement: &70289715220480 !ruby/object:Gem::Requirement
64
+ requirement: !ruby/object:Gem::Requirement
50
65
  none: false
51
66
  requirements:
52
- - - =
67
+ - - '='
53
68
  - !ruby/object:Gem::Version
54
69
  version: 1.17.2
55
70
  type: :development
56
71
  prerelease: false
57
- version_requirements: *70289715220480
72
+ version_requirements: !ruby/object:Gem::Requirement
73
+ none: false
74
+ requirements:
75
+ - - '='
76
+ - !ruby/object:Gem::Version
77
+ version: 1.17.2
58
78
  - !ruby/object:Gem::Dependency
59
79
  name: mocha
60
- requirement: &70289715219620 !ruby/object:Gem::Requirement
80
+ requirement: !ruby/object:Gem::Requirement
61
81
  none: false
62
82
  requirements:
63
- - - =
83
+ - - '='
64
84
  - !ruby/object:Gem::Version
65
85
  version: 0.11.3
66
86
  type: :development
67
87
  prerelease: false
68
- version_requirements: *70289715219620
88
+ version_requirements: !ruby/object:Gem::Requirement
89
+ none: false
90
+ requirements:
91
+ - - '='
92
+ - !ruby/object:Gem::Version
93
+ version: 0.11.3
69
94
  - !ruby/object:Gem::Dependency
70
95
  name: fakeweb
71
- requirement: &70289715218820 !ruby/object:Gem::Requirement
96
+ requirement: !ruby/object:Gem::Requirement
72
97
  none: false
73
98
  requirements:
74
- - - =
99
+ - - '='
75
100
  - !ruby/object:Gem::Version
76
101
  version: 1.3.0
77
102
  type: :development
78
103
  prerelease: false
79
- version_requirements: *70289715218820
104
+ version_requirements: !ruby/object:Gem::Requirement
105
+ none: false
106
+ requirements:
107
+ - - '='
108
+ - !ruby/object:Gem::Version
109
+ version: 1.3.0
80
110
  - !ruby/object:Gem::Dependency
81
111
  name: guard
82
- requirement: &70289715217880 !ruby/object:Gem::Requirement
112
+ requirement: !ruby/object:Gem::Requirement
83
113
  none: false
84
114
  requirements:
85
- - - =
115
+ - - '='
86
116
  - !ruby/object:Gem::Version
87
117
  version: 1.0.1
88
118
  type: :development
89
119
  prerelease: false
90
- version_requirements: *70289715217880
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ none: false
122
+ requirements:
123
+ - - '='
124
+ - !ruby/object:Gem::Version
125
+ version: 1.0.1
91
126
  - !ruby/object:Gem::Dependency
92
127
  name: guard-rspec
93
- requirement: &70289715233320 !ruby/object:Gem::Requirement
128
+ requirement: !ruby/object:Gem::Requirement
94
129
  none: false
95
130
  requirements:
96
- - - =
131
+ - - '='
97
132
  - !ruby/object:Gem::Version
98
133
  version: 0.7.0
99
134
  type: :development
100
135
  prerelease: false
101
- version_requirements: *70289715233320
136
+ version_requirements: !ruby/object:Gem::Requirement
137
+ none: false
138
+ requirements:
139
+ - - '='
140
+ - !ruby/object:Gem::Version
141
+ version: 0.7.0
102
142
  - !ruby/object:Gem::Dependency
103
143
  name: rb-fsevent
104
- requirement: &70289715232440 !ruby/object:Gem::Requirement
144
+ requirement: !ruby/object:Gem::Requirement
105
145
  none: false
106
146
  requirements:
107
- - - =
147
+ - - '='
108
148
  - !ruby/object:Gem::Version
109
149
  version: 0.9.1
110
150
  type: :development
111
151
  prerelease: false
112
- version_requirements: *70289715232440
152
+ version_requirements: !ruby/object:Gem::Requirement
153
+ none: false
154
+ requirements:
155
+ - - '='
156
+ - !ruby/object:Gem::Version
157
+ version: 0.9.1
113
158
  - !ruby/object:Gem::Dependency
114
159
  name: growl
115
- requirement: &70289715231640 !ruby/object:Gem::Requirement
160
+ requirement: !ruby/object:Gem::Requirement
116
161
  none: false
117
162
  requirements:
118
- - - =
163
+ - - '='
119
164
  - !ruby/object:Gem::Version
120
165
  version: 1.0.3
121
166
  type: :development
122
167
  prerelease: false
123
- version_requirements: *70289715231640
168
+ version_requirements: !ruby/object:Gem::Requirement
169
+ none: false
170
+ requirements:
171
+ - - '='
172
+ - !ruby/object:Gem::Version
173
+ version: 1.0.3
124
174
  - !ruby/object:Gem::Dependency
125
175
  name: activesupport
126
- requirement: &70289715230600 !ruby/object:Gem::Requirement
176
+ requirement: !ruby/object:Gem::Requirement
127
177
  none: false
128
178
  requirements:
129
- - - =
179
+ - - '='
130
180
  - !ruby/object:Gem::Version
131
181
  version: 3.2.3
132
182
  type: :runtime
133
183
  prerelease: false
134
- version_requirements: *70289715230600
184
+ version_requirements: !ruby/object:Gem::Requirement
185
+ none: false
186
+ requirements:
187
+ - - '='
188
+ - !ruby/object:Gem::Version
189
+ version: 3.2.3
135
190
  - !ruby/object:Gem::Dependency
136
191
  name: faraday
137
- requirement: &70289715229920 !ruby/object:Gem::Requirement
192
+ requirement: !ruby/object:Gem::Requirement
138
193
  none: false
139
194
  requirements:
140
- - - =
195
+ - - '='
141
196
  - !ruby/object:Gem::Version
142
197
  version: 0.8.0
143
198
  type: :runtime
144
199
  prerelease: false
145
- version_requirements: *70289715229920
200
+ version_requirements: !ruby/object:Gem::Requirement
201
+ none: false
202
+ requirements:
203
+ - - '='
204
+ - !ruby/object:Gem::Version
205
+ version: 0.8.0
146
206
  - !ruby/object:Gem::Dependency
147
207
  name: multi_json
148
- requirement: &70289715229140 !ruby/object:Gem::Requirement
208
+ requirement: !ruby/object:Gem::Requirement
149
209
  none: false
150
210
  requirements:
151
- - - =
211
+ - - '='
152
212
  - !ruby/object:Gem::Version
153
213
  version: 1.3.4
154
214
  type: :runtime
155
215
  prerelease: false
156
- version_requirements: *70289715229140
216
+ version_requirements: !ruby/object:Gem::Requirement
217
+ none: false
218
+ requirements:
219
+ - - '='
220
+ - !ruby/object:Gem::Version
221
+ version: 1.3.4
157
222
  description: Her is an ORM that maps REST resources and collections to Ruby objects
158
223
  email:
159
224
  - remi@exomel.com
@@ -168,6 +233,7 @@ files:
168
233
  - LICENSE
169
234
  - README.md
170
235
  - Rakefile
236
+ - UPGRADE.md
171
237
  - examples/twitter-oauth/Gemfile
172
238
  - examples/twitter-oauth/app.rb
173
239
  - examples/twitter-oauth/config.ru
@@ -216,7 +282,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
216
282
  version: '0'
217
283
  segments:
218
284
  - 0
219
- hash: 3378238073562667343
285
+ hash: -3092731316656290620
220
286
  required_rubygems_version: !ruby/object:Gem::Requirement
221
287
  none: false
222
288
  requirements:
@@ -225,10 +291,10 @@ required_rubygems_version: !ruby/object:Gem::Requirement
225
291
  version: '0'
226
292
  segments:
227
293
  - 0
228
- hash: 3378238073562667343
294
+ hash: -3092731316656290620
229
295
  requirements: []
230
296
  rubyforge_project:
231
- rubygems_version: 1.8.10
297
+ rubygems_version: 1.8.18
232
298
  signing_key:
233
299
  specification_version: 3
234
300
  summary: A simple Representational State Transfer-based Hypertext Transfer Protocol-powered