Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Newer
Older
100644 556 lines (421 sloc) 14.389 kB
aab3042 @remiprev Update README with travis and gemnasium
authored
1 # Her [![Build Status](https://secure.travis-ci.org/remiprev/her.png)](http://travis-ci.org/remiprev/her) [![Gem dependency status](https://gemnasium.com/remiprev/her.png?travis)](https://gemnasium.com/remiprev/her)
871ef96 @remiprev Add README
authored
2
6bd587d @remiprev Improve README, yay!
authored
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.
871ef96 @remiprev Add README
authored
4
5 ## Installation
6
7 In your Gemfile, add:
8
60f209e @remiprev Update README
authored
9 ```ruby
10 gem "her"
11 ```
871ef96 @remiprev Add README
authored
12
6878101 @remiprev Update documentation with new API code
authored
13 That’s it!
14
d907ddd @remiprev Bump version to 0.2.4, add note about UPGRADE.md
authored
15 ## Upgrade
16
17 Please see the [UPGRADE.md](https://github.com/remiprev/her/blob/master/UPGRADE.md) file for backward compability issues.
18
871ef96 @remiprev Add README
authored
19 ## Usage
20
53744d4 @remiprev Do not set any default middleware
authored
21 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:
871ef96 @remiprev Add README
authored
22
23 ```ruby
cdeb59f @remiprev Add Multiple APIs section in README
authored
24 # config/initializers/her.rb
1afdd82 @remiprev Replace “builder” with “connection” in docs and code
authored
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
53744d4 @remiprev Do not set any default middleware
authored
29 end
871ef96 @remiprev Add README
authored
30 ```
31
6878101 @remiprev Update documentation with new API code
authored
32 And then to add the ORM behavior to a class, you just have to include `Her::Model` in it:
871ef96 @remiprev Add README
authored
33
34 ```ruby
35 class User
36 include Her::Model
37 end
38 ```
39
40 After that, using Her is very similar to many ActiveModel-like ORMs:
41
42 ```ruby
a6e9967 @remiprev Update README with more examples
authored
43 User.all
cdeb59f @remiprev Add Multiple APIs section in README
authored
44 # GET https://api.example.com/users and return an array of User objects
a6e9967 @remiprev Update README with more examples
authored
45
46 User.find(1)
cdeb59f @remiprev Add Multiple APIs section in README
authored
47 # GET https://api.example.com/users/1 and return a User object
a6e9967 @remiprev Update README with more examples
authored
48
49 @user = User.create(:fullname => "Tobias Fünke")
bc5779a @remiprev Fix typo
authored
50 # POST "https://api.example.com/users" with the data and return a User object
a6e9967 @remiprev Update README with more examples
authored
51
52 @user = User.new(:fullname => "Tobias Fünke")
53 @user.occupation = "actor"
54 @user.save
cdeb59f @remiprev Add Multiple APIs section in README
authored
55 # POST https://api.example.com/users with the data and return a User object
a6e9967 @remiprev Update README with more examples
authored
56
57 @user = User.find(1)
58 @user.fullname = "Lindsay Fünke"
59 @user.save
cdeb59f @remiprev Add Multiple APIs section in README
authored
60 # PUT https://api.example.com/users/1 with the data and return+update the User object
871ef96 @remiprev Add README
authored
61 ```
60f209e @remiprev Update README
authored
62
ca1a516 @remiprev Update example applications
authored
63 You can look into the `examples` directory for sample applications using Her.
64
fd7dbca @remiprev Fix typo in README
authored
65 ## Middleware
3b3c7ac @remiprev Improve middleware handling on API#setup
authored
66
1bc8ca4 @tysontate Readme fixes for readability / clarity.
tysontate authored
67 Since Her relies on [Faraday](https://github.com/technoweenie/faraday) to send HTTP requests, you can choose the middleware used 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.
3b3c7ac @remiprev Improve middleware handling on API#setup
authored
68
69 ### Authentication
70
1bc8ca4 @tysontate Readme fixes for readability / clarity.
tysontate authored
71 Her doesn’t support authentication by default. However, it’s easy to implement one with request middleware. Using the `builder` block, we can add it to the middleware stack.
72
73 For example, to add a API token header to your requests, you would do something like this:
3b3c7ac @remiprev Improve middleware handling on API#setup
authored
74
75 ```ruby
1bc8ca4 @tysontate Readme fixes for readability / clarity.
tysontate authored
76 class TokenAuthentication < Faraday::Middleware
6bd587d @remiprev Improve README, yay!
authored
77 def initialize(app, options={})
78 @options = options
79 end
80
3b3c7ac @remiprev Improve middleware handling on API#setup
authored
81 def call(env)
6bd587d @remiprev Improve README, yay!
authored
82 env[:request_headers]["X-API-Token"] = @options[:token] if @options.include?(:token)
388826c @remiprev Add OAuth example in documentation
authored
83 @app.call(env)
3b3c7ac @remiprev Improve middleware handling on API#setup
authored
84 end
85 end
86
1afdd82 @remiprev Replace “builder” with “connection” in docs and code
authored
87 Her::API.setup :url => "https://api.example.com" do |connection|
6bd587d @remiprev Improve README, yay!
authored
88 # This token could be stored in the client session
1bc8ca4 @tysontate Readme fixes for readability / clarity.
tysontate authored
89 connection.use TokenAuthentication, :token => "bb2b2dd75413d32c1ac421d39e95b978d1819ff611f68fc2fdd5c8b9c7331192"
53744d4 @remiprev Do not set any default middleware
authored
90
1afdd82 @remiprev Replace “builder” with “connection” in docs and code
authored
91 connection.use Faraday::Request::UrlEncoded
92 connection.use Her::Middleware::DefaultParseJSON
93 connection.use Faraday::Adapter::NetHttp
b73abec @remiprev Improve the way we handle middleware; expose Faraday’s connection bui…
authored
94 end
3b3c7ac @remiprev Improve middleware handling on API#setup
authored
95 ```
96
97 Now, each HTTP request made by Her will have the `X-API-Token` header.
98
1154d56 @remiprev Expect first-level data to be returned by APIs
authored
99 ### Parsing JSON data
ab31348 @remiprev Add Parsing data section in README
authored
100
1154d56 @remiprev Expect first-level data to be returned by APIs
authored
101 By default, Her handles JSON data. It expects the resource/collection data to be returned at the first level.
102
8f55b37 @remiprev Fix typo in README
authored
103 ```javascript
ab31348 @remiprev Add Parsing data section in README
authored
104 // The response of GET /users/1
1154d56 @remiprev Expect first-level data to be returned by APIs
authored
105 { "id" : 1, "name" : "Tobias Fünke" }
ab31348 @remiprev Add Parsing data section in README
authored
106
107 // The response of GET /users
1154d56 @remiprev Expect first-level data to be returned by APIs
authored
108 [{ "id" : 1, "name" : "Tobias Fünke" }]
ab31348 @remiprev Add Parsing data section in README
authored
109 ```
110
1bc8ca4 @tysontate Readme fixes for readability / clarity.
tysontate authored
111 However, you can define your own parsing method using a response middleware. The middleware should set `env[:body]` to a hash with three keys: `data`, `errors` and `metadata`. The following code uses a custom middleware to parse the JSON data:
ab31348 @remiprev Add Parsing data section in README
authored
112
113 ```ruby
1bc8ca4 @tysontate Readme fixes for readability / clarity.
tysontate authored
114 # Expects responses like:
115 #
116 # {
117 # "result": {
118 # "id": 1,
119 # "name": "Tobias Fünke"
120 # },
121 # "errors" => []
122 # }
123 #
3d1da8d @remiprev Add support for custom Faraday middleware
authored
124 class MyCustomParser < Faraday::Response::Middleware
125 def on_complete(env)
490c313 @remiprev Fix typo in README
authored
126 json = MultiJson.load(env[:body], :symbolize_keys => true)
1154d56 @remiprev Expect first-level data to be returned by APIs
authored
127 env[:body] = {
6bd587d @remiprev Improve README, yay!
authored
128 :data => json[:result],
1154d56 @remiprev Expect first-level data to be returned by APIs
authored
129 :errors => json[:errors],
130 :metadata => json[:metadata]
131 }
3d1da8d @remiprev Add support for custom Faraday middleware
authored
132 end
133 end
8a5bee6 @remiprev Fix a few typos
authored
134
1afdd82 @remiprev Replace “builder” with “connection” in docs and code
authored
135 Her::API.setup :url => "https://api.example.com" do |connection|
136 connection.use Faraday::Request::UrlEncoded
137 connection.use MyCustomParser
138 connection.use Faraday::Adapter::NetHttp
b73abec @remiprev Improve the way we handle middleware; expose Faraday’s connection bui…
authored
139 end
ab31348 @remiprev Add Parsing data section in README
authored
140 ```
141
388826c @remiprev Add OAuth example in documentation
authored
142 ### OAuth
143
144 Using the `faraday_middleware` and `simple_oauth` gems, it’s fairly easy to use OAuth authentication with Her.
145
146 In your Gemfile:
147
148 ```ruby
c01ceda @remiprev Update OAuth example in README
authored
149 gem "her"
150 gem "faraday_middleware"
151 gem "simple_oauth"
388826c @remiprev Add OAuth example in documentation
authored
152 ```
153
154 In your Ruby code:
155
156 ```ruby
c01ceda @remiprev Update OAuth example in README
authored
157 # Create an application on `https://dev.twitter.com/apps` to set these values
388826c @remiprev Add OAuth example in documentation
authored
158 TWITTER_CREDENTIALS = {
159 :consumer_key => "",
160 :consumer_secret => "",
161 :token => "",
162 :token_secret => ""
163 }
164
1afdd82 @remiprev Replace “builder” with “connection” in docs and code
authored
165 Her::API.setup :url => "https://api.twitter.com/1/" do |connection|
166 connection.use FaradayMiddleware::OAuth, TWITTER_CREDENTIALS
167 connection.use Faraday::Request::UrlEncoded
168 connection.use Her::Middleware::DefaultParseJSON
169 connection.use Faraday::Adapter::NetHttp
b73abec @remiprev Improve the way we handle middleware; expose Faraday’s connection bui…
authored
170 end
388826c @remiprev Add OAuth example in documentation
authored
171
172 class Tweet
173 include Her::Model
174 end
175
176 @tweets = Tweet.get("/statuses/home_timeline.json")
177 ```
178
b73abec @remiprev Improve the way we handle middleware; expose Faraday’s connection bui…
authored
179 ### Caching
180
181 Again, using the `faraday_middleware` makes it very easy to cache requests and responses:
182
183 In your Gemfile:
184
185 ```ruby
186 gem "her"
187 gem "faraday_middleware"
188 ```
189
190 In your Ruby code:
191
192 ```ruby
721b7f4 @remiprev Update caching example in README
authored
193 class MyCache < Hash
194 def read(key)
195 if cached = self[key]
196 Marshal.load(cached)
197 end
4b824f9 @remiprev Update caching example in README
authored
198 end
199
721b7f4 @remiprev Update caching example in README
authored
200 def write(key, data)
201 self[key] = Marshal.dump(data)
4b824f9 @remiprev Update caching example in README
authored
202 end
203
721b7f4 @remiprev Update caching example in README
authored
204 def fetch(key)
205 read(key) || yield.tap { |data| write(key, data) }
4b824f9 @remiprev Update caching example in README
authored
206 end
b73abec @remiprev Improve the way we handle middleware; expose Faraday’s connection bui…
authored
207 end
208
27a9a78 @remiprev Fix typo in README
authored
209 # A cache system must respond to `#write`, `#read` and `#fetch`.
210 # We should be probably using something like Memcached here, not a global object
b73abec @remiprev Improve the way we handle middleware; expose Faraday’s connection bui…
authored
211 $cache = MyCache.new
212
1afdd82 @remiprev Replace “builder” with “connection” in docs and code
authored
213 Her::API.setup :url => "https://api.example.com" do |connection|
214 connection.use Faraday::Request::UrlEncoded
215 connection.use FaradayMiddleware::Caching, $cache
216 connection.use Her::Middleware::DefaultParseJSON
217 connection.use Faraday::Adapter::NetHttp
b73abec @remiprev Improve the way we handle middleware; expose Faraday’s connection bui…
authored
218 end
219
220 class User
221 include Her::Model
222 end
223
224 @user = User.find(1)
6bd587d @remiprev Improve README, yay!
authored
225 # GET /users/1
226
227 @user = User.find(1)
228 # This request will be fetched from the cache
b73abec @remiprev Improve the way we handle middleware; expose Faraday’s connection bui…
authored
229 ```
230
6878101 @remiprev Update documentation with new API code
authored
231 ## Relationships
232
1bc8ca4 @tysontate Readme fixes for readability / clarity.
tysontate authored
233 You can define `has_many`, `has_one` and `belongs_to` relationships in your models. The relationship data is handled in two different ways.
313c487 @remiprev Add better documentation for relationships
authored
234
1bc8ca4 @tysontate Readme fixes for readability / clarity.
tysontate authored
235 1. If Her finds relationship data when parsing a resource, that data will be used to create the associated model objects on the resource.
236 2. If no relationship data was included when parsing a resource, calling a method with the same name as the relationship will fetch the data (providing there’s an HTTP request available for it in the API).
313c487 @remiprev Add better documentation for relationships
authored
237
1bc8ca4 @tysontate Readme fixes for readability / clarity.
tysontate authored
238 For example:
313c487 @remiprev Add better documentation for relationships
authored
239
6878101 @remiprev Update documentation with new API code
authored
240 ```ruby
241 class User
242 include Her::Model
243 has_many :comments
d997547 Updated readme for has_one relationship
jfcixmedia authored
244 has_one :role
875f744 @remiprev Update README for belongs_to
authored
245 belongs_to :organization
6878101 @remiprev Update documentation with new API code
authored
246 end
247
248 class Comment
249 include Her::Model
250 end
d997547 Updated readme for has_one relationship
jfcixmedia authored
251
252 class Role
253 include Her::Model
254 end
875f744 @remiprev Update README for belongs_to
authored
255
256 class Organization
257 include Her::Model
258 end
313c487 @remiprev Add better documentation for relationships
authored
259 ```
260
6bd587d @remiprev Improve README, yay!
authored
261 If there’s relationship data in the resource, no extra HTTP request is made when calling the `#comments` method and an array of resources is returned:
6878101 @remiprev Update documentation with new API code
authored
262
313c487 @remiprev Add better documentation for relationships
authored
263 ```ruby
1bc8ca4 @tysontate Readme fixes for readability / clarity.
tysontate authored
264 @user = User.find(1)
265 # {
266 # :data => {
267 # :id => 1,
268 # :name => "George Michael Bluth",
269 # :comments => [
270 # { :id => 1, :text => "Foo" },
271 # { :id => 2, :text => "Bar" }
272 # ],
273 # :role => { :id => 1, :name => "Admin" },
274 # :organization => { :id => 2, :name => "Bluth Company" }
275 # }
276 # }
277 @user.comments
278 # [#<Comment id=1 text="Foo">, #<Comment id=2 text="Bar">]
279 @user.role
280 # #<Role id=1 name="Admin">
281 @user.organization
282 # #<Organization id=2 name="Bluth Company">
313c487 @remiprev Add better documentation for relationships
authored
283 ```
284
1bc8ca4 @tysontate Readme fixes for readability / clarity.
tysontate authored
285 If there’s no relationship data in the resource, Her makes a HTTP request to retrieve the data.
d997547 Updated readme for has_one relationship
jfcixmedia authored
286
287 ```ruby
1bc8ca4 @tysontate Readme fixes for readability / clarity.
tysontate authored
288 @user = User.find(1)
289 # { :data => { :id => 1, :name => "George Michael Bluth", :organization_id => 2 }}
290
291 # has_many relationship:
292 @user.comments
293 # GET /users/1/comments
294 # [#<Comment id=1>, #<Comment id=2>]
295
296 # has_one relationship:
297 @user.role
298 # GET /users/1/role
299 # #<Role id=1>
300
301 # belongs_to relationship:
302 @user.organization
303 # (the organization id comes from :organization_id, by default)
304 # GET /organizations/2
305 # #<Organization id=2>
875f744 @remiprev Update README for belongs_to
authored
306 ```
307
1bc8ca4 @tysontate Readme fixes for readability / clarity.
tysontate authored
308 Subsequent calls to `#comments`, `#role` and `#organization` will not trigger extra HTTP requests and will return the cached objects.
313c487 @remiprev Add better documentation for relationships
authored
309
3bb8232 @remiprev Add documentation for hooks
authored
310 ## Hooks
311
312 You can add *before* and *after* hooks to your models that are triggered on specific actions (`save`, `update`, `create`, `destroy`):
313
314 ```ruby
315 class User
316 include Her::Model
317 before_save :set_internal_id
318
319 def set_internal_id
320 self.internal_id = 42 # Will be passed in the HTTP request
321 end
322 end
ee90237 @remiprev Add example for hooks
authored
323
324 @user = User.create(:fullname => "Tobias Fünke")
325 # POST /users&fullname=Tobias+Fünke&internal_id=42
3bb8232 @remiprev Add documentation for hooks
authored
326 ```
327
6878101 @remiprev Update documentation with new API code
authored
328 ## Custom requests
329
2c0c171 @remiprev Add support for custom_<method> methods
authored
330 You can easily define custom requests for your models using `custom_get`, `custom_post`, etc.
331
332 ```ruby
333 class User
334 include Her::Model
335 custom_get :popular, :unpopular
336 custom_post :from_default
337 end
338
1bc8ca4 @tysontate Readme fixes for readability / clarity.
tysontate authored
339 User.popular
2c0c171 @remiprev Add support for custom_<method> methods
authored
340 # GET /users/popular
1bc8ca4 @tysontate Readme fixes for readability / clarity.
tysontate authored
341 # [#<User id=1>, #<User id=2>]
2c0c171 @remiprev Add support for custom_<method> methods
authored
342
1bc8ca4 @tysontate Readme fixes for readability / clarity.
tysontate authored
343 User.unpopular
2c0c171 @remiprev Add support for custom_<method> methods
authored
344 # GET /users/unpopular
1bc8ca4 @tysontate Readme fixes for readability / clarity.
tysontate authored
345 # [#<User id=3>, #<User id=4>]
2c0c171 @remiprev Add support for custom_<method> methods
authored
346
1bc8ca4 @tysontate Readme fixes for readability / clarity.
tysontate authored
347 User.from_default(:name => "Maeby Fünke")
2c0c171 @remiprev Add support for custom_<method> methods
authored
348 # POST /users/from_default?name=Maeby+Fünke
1bc8ca4 @tysontate Readme fixes for readability / clarity.
tysontate authored
349 # #<User id=5 name="Maeby Fünke">
2c0c171 @remiprev Add support for custom_<method> methods
authored
350 ```
351
352 You can also use `get`, `post`, `put` or `delete` (which maps the returned data to either a collection or a resource).
6878101 @remiprev Update documentation with new API code
authored
353
17d968c @remiprev Improve support for custom methods
authored
354 ```ruby
355 class User
356 include Her::Model
a7ae25f @remiprev Add support for symbols in custom requests
authored
357 end
358
1bc8ca4 @tysontate Readme fixes for readability / clarity.
tysontate authored
359 User.get(:popular)
a7ae25f @remiprev Add support for symbols in custom requests
authored
360 # GET /users/popular
1bc8ca4 @tysontate Readme fixes for readability / clarity.
tysontate authored
361 # [#<User id=1>, #<User id=2>]
37aef13 @remiprev Add support for `get`, `post`, etc. wrapper methods
authored
362
1bc8ca4 @tysontate Readme fixes for readability / clarity.
tysontate authored
363 User.get(:single_best)
37aef13 @remiprev Add support for `get`, `post`, etc. wrapper methods
authored
364 # GET /users/single_best
1bc8ca4 @tysontate Readme fixes for readability / clarity.
tysontate authored
365 # #<User id=1>
a7ae25f @remiprev Add support for symbols in custom requests
authored
366 ```
367
37aef13 @remiprev Add support for `get`, `post`, etc. wrapper methods
authored
368 Also, `get_collection` (which maps the returned data to a collection of resources), `get_resource` (which maps the returned data to a single resource) or `get_raw` (which yields the parsed data return from the HTTP request) can also be used. Other HTTP methods are supported (`post_raw`, `put_resource`, etc.).
a7ae25f @remiprev Add support for symbols in custom requests
authored
369
370 ```ruby
371 class User
372 include Her::Model
17d968c @remiprev Improve support for custom methods
authored
373
374 def self.popular
37aef13 @remiprev Add support for `get`, `post`, etc. wrapper methods
authored
375 get_collection(:popular)
17d968c @remiprev Improve support for custom methods
authored
376 end
6878101 @remiprev Update documentation with new API code
authored
377
17d968c @remiprev Improve support for custom methods
authored
378 def self.total
37aef13 @remiprev Add support for `get`, `post`, etc. wrapper methods
authored
379 get_raw(:stats) do |parsed_data|
17d968c @remiprev Improve support for custom methods
authored
380 parsed_data[:data][:total_users]
381 end
382 end
383 end
384
1bc8ca4 @tysontate Readme fixes for readability / clarity.
tysontate authored
385 User.popular
386 # GET /users/popular
387 # [#<User id=1>, #<User id=2>]
388 User.total
389 # GET /users/stats
390 # => 42
17d968c @remiprev Improve support for custom methods
authored
391 ```
7f7392f @remiprev Improve README and add LICENSE
authored
392
37aef13 @remiprev Add support for `get`, `post`, etc. wrapper methods
authored
393 You can also use full request paths (with strings instead of symbols).
394
395 ```ruby
396 class User
397 include Her::Model
398 end
399
1bc8ca4 @tysontate Readme fixes for readability / clarity.
tysontate authored
400 User.get("/users/popular")
37aef13 @remiprev Add support for `get`, `post`, etc. wrapper methods
authored
401 # GET /users/popular
1bc8ca4 @tysontate Readme fixes for readability / clarity.
tysontate authored
402 # [#<User id=1>, #<User id=2>]
37aef13 @remiprev Add support for `get`, `post`, etc. wrapper methods
authored
403 ```
404
fca11ad @remiprev Use internal parameter to build custom paths
authored
405 ## Custom paths
406
407 You can define custom HTTP paths for your models:
408
409 ```ruby
410 class User
411 include Her::Model
412 collection_path "/hello_users/:id"
413 end
414
415 @user = User.find(1)
416 # GET /hello_users/1
417 ```
418
6bd587d @remiprev Improve README, yay!
authored
419 You can also include custom variables in your paths:
fca11ad @remiprev Use internal parameter to build custom paths
authored
420
421 ```ruby
422 class User
423 include Her::Model
6bd587d @remiprev Improve README, yay!
authored
424 collection_path "/organizations/:organization_id/users"
fca11ad @remiprev Use internal parameter to build custom paths
authored
425 end
426
427 @user = User.find(1, :_organization_id => 2)
428 # GET /organizations/2/users/1
429
430 @user = User.all(:_organization_id => 2)
431 # GET /organizations/2/users
6bd587d @remiprev Improve README, yay!
authored
432
433 @user = User.new(:fullname => "Tobias Fünke", :organization_id => 2)
434 @user.save
435 # POST /organizations/2/users
fca11ad @remiprev Use internal parameter to build custom paths
authored
436 ```
437
cdeb59f @remiprev Add Multiple APIs section in README
authored
438 ## Multiple APIs
439
440 It is possible to use different APIs for different models. Instead of calling `Her::API.setup`, you can create instances of `Her::API`:
441
442 ```ruby
443 # config/initializers/her.rb
444 $my_api = Her::API.new
1afdd82 @remiprev Replace “builder” with “connection” in docs and code
authored
445 $my_api.setup :url => "https://my_api.example.com" do |connection|
446 connection.use Faraday::Request::UrlEncoded
447 connection.use Her::Middleware::DefaultParseJSON
448 connection.use Faraday::Adapter::NetHttp
53744d4 @remiprev Do not set any default middleware
authored
449 end
cdeb59f @remiprev Add Multiple APIs section in README
authored
450
451 $other_api = Her::API.new
1afdd82 @remiprev Replace “builder” with “connection” in docs and code
authored
452 $other_api.setup :url => "https://other_api.example.com" do |connection|
453 connection.use Faraday::Request::UrlEncoded
454 connection.use Her::Middleware::DefaultParseJSON
455 connection.use Faraday::Adapter::NetHttp
53744d4 @remiprev Do not set any default middleware
authored
456 end
cdeb59f @remiprev Add Multiple APIs section in README
authored
457 ```
458
459 You can then define which API a model will use:
460
461 ```ruby
462 class User
463 include Her::Model
464 uses_api $my_api
465 end
466
467 class Category
468 include Her::Model
469 uses_api $other_api
470 end
471
472 User.all
473 # GET https://my_api.example.com/users
474
475 Category.all
476 # GET https://other_api.example.com/categories
477 ```
478
3805014 @remiprev Add SSL section
authored
479 ## SSL
480
481 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.
482
483 ```ruby
484 ssl_options = { :ca_path => "/usr/lib/ssl/certs" }
1afdd82 @remiprev Replace “builder” with “connection” in docs and code
authored
485 Her::API.setup :url => "https://api.example.com", :ssl => ssl_options do |connection|
486 connection.use Faraday::Request::UrlEncoded
487 connection.use Her::Middleware::DefaultParseJSON
488 connection.use Faraday::Adapter::NetHttp
3805014 @remiprev Add SSL section
authored
489 end
490 ```
491
c4108fa @remiprev Add README section for testing models
authored
492 ## Testing
493
494 Using Faraday stubbing feature, it’s very easy to write tests for our models. For example, using [RSpec](https://github.com/rspec/rspec-core):
495
496 ```ruby
497 # app/models/post.rb
498 class Post
499 include Her::Model
500 custom_get :popular
501 end
502
503 # spec/models/post.rb
504 describe Post do
505 before do
1afdd82 @remiprev Replace “builder” with “connection” in docs and code
authored
506 Her::API.setup :url => "http://api.example.com" do |connection|
507 connection.use Her::Middleware::FirstLevelParseJSON
508 connection.use Faraday::Request::UrlEncoded
509 connection.adapter :test do |stub|
c4108fa @remiprev Add README section for testing models
authored
510 stub.get("/users/popular") { |env| [200, {}, [{ :id => 1, :name => "Tobias Fünke" }, { :id => 2, :name => "Lindsay Fünke" }].to_json] }
511 end
512 end
513 end
514
515 describe ".popular" do
516 it "should fetch all popular posts" do
517 @posts = Post.popular
518 @posts.length.should == 2
519 end
520 end
521 end
522 ```
523
7f7392f @remiprev Improve README and add LICENSE
authored
524 ## Things to be done
525
a6e9967 @remiprev Update README with more examples
authored
526 * Better error handling
6bd587d @remiprev Improve README, yay!
authored
527 * Better API documentation (using YARD)
7f7392f @remiprev Improve README and add LICENSE
authored
528
676a56f @remiprev Improve Contribute section in README
authored
529 ## Contribute
7f7392f @remiprev Improve README and add LICENSE
authored
530
676a56f @remiprev Improve Contribute section in README
authored
531 Yes please! Feel free to contribute and submit issues/pull requests [on GitHub](https://github.com/remiprev/her/issues).
532
533 ### How to contribute
534
535 * Fork the repository
536 * Implement your feature or fix
537 * Add examples that describe it (in the `spec` directory)
538 * Make sure `bundle exec rake spec` passes after your modifications
539 * Commit (bonus points for doing it in a `feature-*` branch)
540 * Send a pull request!
541
542 ### Contributors
543
544 These fine folks helped with Her:
7f9f399 @remiprev Add contributors, woohoo!
authored
545
546 * [@jfcixmedia](https://github.com/jfcixmedia)
547 * [@EtienneLem](https://github.com/EtienneLem)
a366819 @remiprev Add @rafaelss to contributors
authored
548 * [@rafaelss](https://github.com/rafaelss)
855b897 @remiprev Update contributors with @tysontate
authored
549 * [@tysontate](https://github.com/tysontate)
2163cf5 @remiprev Add Nicolas Fouché to contributors list
authored
550 * [@nfo](https://github.com/nfo)
f18374a @remiprev Add @simonprevost to contributors
authored
551 * [@simonprevost](https://github.com/simonprevost)
7f7392f @remiprev Improve README and add LICENSE
authored
552
553 ## License
554
fd5bb21 @fbernier Show the correct license name in README
fbernier authored
555 Her is © 2012 [Rémi Prévost](http://exomel.com) and may be freely distributed under the [MIT license](https://github.com/remiprev/her/blob/master/LICENSE). See the `LICENSE` file.
Something went wrong with that request. Please try again.