Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Newer
Older
100644 517 lines (382 sloc) 14.606 kb
aab3042 Rémi Prévost 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 Rémi Prévost Add README
authored
2
6bd587d Rémi Prévost 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 Rémi Prévost Add README
authored
4
5 ## Installation
6
7 In your Gemfile, add:
8
60f209e Rémi Prévost Update README
authored
9 ```ruby
10 gem "her"
11 ```
871ef96 Rémi Prévost Add README
authored
12
6878101 Rémi Prévost Update documentation with new API code
authored
13 That’s it!
14
d907ddd Rémi Prévost 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 Rémi Prévost Add README
authored
19 ## Usage
20
53744d4 Rémi Prévost 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 Rémi Prévost Add README
authored
22
23 ```ruby
cdeb59f Rémi Prévost Add Multiple APIs section in README
authored
24 # config/initializers/her.rb
ec9699c Rémi Prévost Add support for Faraday connection options in Her::API#setup
authored
25 Her::API.setup :url => "https://api.example.com" do |builder|
53744d4 Rémi Prévost Do not set any default middleware
authored
26 builder.use Faraday::Request::UrlEncoded
27 builder.use Her::Middleware::DefaultParseJSON
28 builder.use Faraday::Adapter::NetHttp
29 end
871ef96 Rémi Prévost Add README
authored
30 ```
31
6878101 Rémi Prévost 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 Rémi Prévost 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 Rémi Prévost Update README with more examples
authored
43 User.all
cdeb59f Rémi Prévost Add Multiple APIs section in README
authored
44 # GET https://api.example.com/users and return an array of User objects
a6e9967 Rémi Prévost Update README with more examples
authored
45
46 User.find(1)
cdeb59f Rémi Prévost Add Multiple APIs section in README
authored
47 # GET https://api.example.com/users/1 and return a User object
a6e9967 Rémi Prévost Update README with more examples
authored
48
49 @user = User.create(:fullname => "Tobias Fünke")
bc5779a Rémi Prévost Fix typo
authored
50 # POST "https://api.example.com/users" with the data and return a User object
a6e9967 Rémi Prévost Update README with more examples
authored
51
52 @user = User.new(:fullname => "Tobias Fünke")
53 @user.occupation = "actor"
54 @user.save
cdeb59f Rémi Prévost Add Multiple APIs section in README
authored
55 # POST https://api.example.com/users with the data and return a User object
a6e9967 Rémi Prévost Update README with more examples
authored
56
57 @user = User.find(1)
58 @user.fullname = "Lindsay Fünke"
59 @user.save
cdeb59f Rémi Prévost 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 Rémi Prévost Add README
authored
61 ```
60f209e Rémi Prévost Update README
authored
62
ca1a516 Rémi Prévost Update example applications
authored
63 You can look into the `examples` directory for sample applications using Her.
64
fd7dbca Rémi Prévost Fix typo in README
authored
65 ## Middleware
3b3c7ac Rémi Prévost Improve middleware handling on API#setup
authored
66
53744d4 Rémi Prévost Do not set any default middleware
authored
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.
3b3c7ac Rémi Prévost Improve middleware handling on API#setup
authored
68
69 ### Authentication
70
b73abec Rémi Prévost Improve the way we handle middleware; expose Faraday’s connection builde...
authored
71 Her doesn’t support any kind of authentication. However, it’s very easy to implement one with a request middleware. Using the builder block, we add it to the default list of middleware.
3b3c7ac Rémi Prévost Improve middleware handling on API#setup
authored
72
73 ```ruby
74 class MyAuthentication < Faraday::Middleware
6bd587d Rémi Prévost Improve README, yay!
authored
75 def initialize(app, options={})
76 @options = options
77 end
78
3b3c7ac Rémi Prévost Improve middleware handling on API#setup
authored
79 def call(env)
6bd587d Rémi Prévost Improve README, yay!
authored
80 env[:request_headers]["X-API-Token"] = @options[:token] if @options.include?(:token)
388826c Rémi Prévost Add OAuth example in documentation
authored
81 @app.call(env)
3b3c7ac Rémi Prévost Improve middleware handling on API#setup
authored
82 end
83 end
84
ec9699c Rémi Prévost Add support for Faraday connection options in Her::API#setup
authored
85 Her::API.setup :url => "https://api.example.com" do |builder|
6bd587d Rémi Prévost Improve README, yay!
authored
86 # This token could be stored in the client session
53744d4 Rémi Prévost Do not set any default middleware
authored
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
b73abec Rémi Prévost Improve the way we handle middleware; expose Faraday’s connection builde...
authored
92 end
3b3c7ac Rémi Prévost Improve middleware handling on API#setup
authored
93 ```
94
95 Now, each HTTP request made by Her will have the `X-API-Token` header.
96
1154d56 Rémi Prévost Expect first-level data to be returned by APIs
authored
97 ### Parsing JSON data
ab31348 Rémi Prévost Add Parsing data section in README
authored
98
1154d56 Rémi Prévost Expect first-level data to be returned by APIs
authored
99 By default, Her handles JSON data. It expects the resource/collection data to be returned at the first level.
100
8f55b37 Rémi Prévost Fix typo in README
authored
101 ```javascript
ab31348 Rémi Prévost Add Parsing data section in README
authored
102 // The response of GET /users/1
1154d56 Rémi Prévost Expect first-level data to be returned by APIs
authored
103 { "id" : 1, "name" : "Tobias Fünke" }
ab31348 Rémi Prévost Add Parsing data section in README
authored
104
105 // The response of GET /users
1154d56 Rémi Prévost Expect first-level data to be returned by APIs
authored
106 [{ "id" : 1, "name" : "Tobias Fünke" }]
ab31348 Rémi Prévost Add Parsing data section in README
authored
107 ```
108
d0bfc9e Rémi Prévost Use swap instead of delete/use!
authored
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 builder block, we then replace the default parser with our custom parser.
ab31348 Rémi Prévost Add Parsing data section in README
authored
110
111 ```ruby
3d1da8d Rémi Prévost Add support for custom Faraday middleware
authored
112 class MyCustomParser < Faraday::Response::Middleware
113 def on_complete(env)
490c313 Rémi Prévost Fix typo in README
authored
114 json = MultiJson.load(env[:body], :symbolize_keys => true)
1154d56 Rémi Prévost Expect first-level data to be returned by APIs
authored
115 env[:body] = {
6bd587d Rémi Prévost Improve README, yay!
authored
116 :data => json[:result],
1154d56 Rémi Prévost Expect first-level data to be returned by APIs
authored
117 :errors => json[:errors],
118 :metadata => json[:metadata]
119 }
3d1da8d Rémi Prévost Add support for custom Faraday middleware
authored
120 end
121 end
8a5bee6 Rémi Prévost Fix a few typos
authored
122
ec9699c Rémi Prévost Add support for Faraday connection options in Her::API#setup
authored
123 Her::API.setup :url => "https://api.example.com" do |builder|
53744d4 Rémi Prévost Do not set any default middleware
authored
124 builder.use Faraday::Request::UrlEncoded
125 builder.use MyCustomParser
126 builder.use Faraday::Adapter::NetHttp
b73abec Rémi Prévost Improve the way we handle middleware; expose Faraday’s connection builde...
authored
127 end
6bd587d Rémi Prévost Improve README, yay!
authored
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" => [] }'
ab31348 Rémi Prévost Add Parsing data section in README
authored
129 ```
130
388826c Rémi Prévost Add OAuth example in documentation
authored
131 ### OAuth
132
133 Using the `faraday_middleware` and `simple_oauth` gems, it’s fairly easy to use OAuth authentication with Her.
134
135 In your Gemfile:
136
137 ```ruby
c01ceda Rémi Prévost Update OAuth example in README
authored
138 gem "her"
139 gem "faraday_middleware"
140 gem "simple_oauth"
388826c Rémi Prévost Add OAuth example in documentation
authored
141 ```
142
143 In your Ruby code:
144
145 ```ruby
c01ceda Rémi Prévost Update OAuth example in README
authored
146 # Create an application on `https://dev.twitter.com/apps` to set these values
388826c Rémi Prévost Add OAuth example in documentation
authored
147 TWITTER_CREDENTIALS = {
148 :consumer_key => "",
149 :consumer_secret => "",
150 :token => "",
151 :token_secret => ""
152 }
153
ec9699c Rémi Prévost Add support for Faraday connection options in Her::API#setup
authored
154 Her::API.setup :url => "https://api.twitter.com/1/" do |builder|
53744d4 Rémi Prévost Do not set any default middleware
authored
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
b73abec Rémi Prévost Improve the way we handle middleware; expose Faraday’s connection builde...
authored
159 end
388826c Rémi Prévost Add OAuth example in documentation
authored
160
161 class Tweet
162 include Her::Model
163 end
164
165 @tweets = Tweet.get("/statuses/home_timeline.json")
166 ```
167
b73abec Rémi Prévost Improve the way we handle middleware; expose Faraday’s connection builde...
authored
168 ### Caching
169
170 Again, using the `faraday_middleware` makes it very easy to cache requests and responses:
171
172 In your Gemfile:
173
174 ```ruby
175 gem "her"
176 gem "faraday_middleware"
177 ```
178
179 In your Ruby code:
180
181 ```ruby
721b7f4 Rémi Prévost Update caching example in README
authored
182 class MyCache < Hash
183 def read(key)
184 if cached = self[key]
185 Marshal.load(cached)
186 end
4b824f9 Rémi Prévost Update caching example in README
authored
187 end
188
721b7f4 Rémi Prévost Update caching example in README
authored
189 def write(key, data)
190 self[key] = Marshal.dump(data)
4b824f9 Rémi Prévost Update caching example in README
authored
191 end
192
721b7f4 Rémi Prévost Update caching example in README
authored
193 def fetch(key)
194 read(key) || yield.tap { |data| write(key, data) }
4b824f9 Rémi Prévost Update caching example in README
authored
195 end
b73abec Rémi Prévost Improve the way we handle middleware; expose Faraday’s connection builde...
authored
196 end
197
27a9a78 Rémi Prévost Fix typo in README
authored
198 # A cache system must respond to `#write`, `#read` and `#fetch`.
199 # We should be probably using something like Memcached here, not a global object
b73abec Rémi Prévost Improve the way we handle middleware; expose Faraday’s connection builde...
authored
200 $cache = MyCache.new
201
ec9699c Rémi Prévost Add support for Faraday connection options in Her::API#setup
authored
202 Her::API.setup :url => "https://api.example.com" do |builder|
53744d4 Rémi Prévost Do not set any default middleware
authored
203 builder.use Faraday::Request::UrlEncoded
b73abec Rémi Prévost Improve the way we handle middleware; expose Faraday’s connection builde...
authored
204 builder.use FaradayMiddleware::Caching, $cache
53744d4 Rémi Prévost Do not set any default middleware
authored
205 builder.use Her::Middleware::DefaultParseJSON
206 builder.use Faraday::Adapter::NetHttp
b73abec Rémi Prévost Improve the way we handle middleware; expose Faraday’s connection builde...
authored
207 end
208
209 class User
210 include Her::Model
211 end
212
213 @user = User.find(1)
6bd587d Rémi Prévost Improve README, yay!
authored
214 # GET /users/1
215
216 @user = User.find(1)
217 # This request will be fetched from the cache
b73abec Rémi Prévost Improve the way we handle middleware; expose Faraday’s connection builde...
authored
218 ```
219
6878101 Rémi Prévost Update documentation with new API code
authored
220 ## Relationships
221
6bd587d Rémi Prévost Improve README, yay!
authored
222 You can define `has_many`, `has_one` and `belongs_to` relationships in your models. The relationship data is handled in two different ways. If there’s relationship data when parsing a resource, it will be used to create new Ruby objects.
313c487 Rémi Prévost Add better documentation for relationships
authored
223
875f744 Rémi Prévost Update README for belongs_to
authored
224 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 Rémi Prévost Add better documentation for relationships
authored
225
226 For example, with this setup:
227
6878101 Rémi Prévost Update documentation with new API code
authored
228 ```ruby
229 class User
230 include Her::Model
231 has_many :comments
d997547 Updated readme for has_one relationship
jfcixmedia authored
232 has_one :role
875f744 Rémi Prévost Update README for belongs_to
authored
233 belongs_to :organization
6878101 Rémi Prévost Update documentation with new API code
authored
234 end
235
236 class Comment
237 include Her::Model
238 end
d997547 Updated readme for has_one relationship
jfcixmedia authored
239
240 class Role
241 include Her::Model
242 end
875f744 Rémi Prévost Update README for belongs_to
authored
243
244 class Organization
245 include Her::Model
246 end
313c487 Rémi Prévost Add better documentation for relationships
authored
247 ```
248
6bd587d Rémi Prévost Improve README, yay!
authored
249 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 Rémi Prévost Update documentation with new API code
authored
250
313c487 Rémi Prévost Add better documentation for relationships
authored
251 ```ruby
875f744 Rémi Prévost Update README for belongs_to
authored
252 @user = User.find(1) # { :data => { :id => 1, :name => "George Michael Bluth", :comments => [{ :id => 1, :text => "Foo" }, { :id => 2, :text => "Bar" }], :role => { :id => 1, :name => "Admin" }, :organization => { :id => 2, :name => "Bluth Company" } }}
313c487 Rémi Prévost Add better documentation for relationships
authored
253 @user.comments # => [#<Comment id=1>, #<Comment id=2>] fetched directly from @user
d997547 Updated readme for has_one relationship
jfcixmedia authored
254 @user.role # => #<Role id=1> fetched directly from @user
875f744 Rémi Prévost Update README for belongs_to
authored
255 @user.organization # => #<Organization id=2> fetched directly from @user
6878101 Rémi Prévost Update documentation with new API code
authored
256 ```
257
313c487 Rémi Prévost Add better documentation for relationships
authored
258 If there’s no relationship data in the resource, an extra HTTP request (to `GET /users/1/comments`) is made when calling the `#comments` method:
259
260 ```ruby
a6e9967 Rémi Prévost Update README with more examples
authored
261 @user = User.find(1) # { :data => { :id => 1, :name => "George Michael Bluth" }}
313c487 Rémi Prévost Add better documentation for relationships
authored
262 @user.comments # => [#<Comment id=1>, #<Comment id=2>] fetched from /users/1/comments
263 ```
264
6bd587d Rémi Prévost Improve README, yay!
authored
265 For `has_one` relationships, an extra HTTP request (to `GET /users/1/role`) is made when calling the `#role` method:
d997547 Updated readme for has_one relationship
jfcixmedia authored
266
267 ```ruby
268 @user = User.find(1) # { :data => { :id => 1, :name => "George Michael Bluth" }}
269 @user.role # => #<Role id=1> fetched from /users/1/role
270 ```
271
6bd587d Rémi Prévost Improve README, yay!
authored
272 For `belongs_to` relationships, an extra HTTP request (to `GET /organizations/2`) is made when calling the `#organization` method:
875f744 Rémi Prévost Update README for belongs_to
authored
273
274 ```ruby
275 @user = User.find(1) # { :data => { :id => 1, :name => "George Michael Bluth", :organization_id => 2 }}
276 @user.organization # => #<Organization id=2> fetched from /organizations/2
277 ```
278
6bd587d Rémi Prévost Improve README, yay!
authored
279 However, subsequent calls to `#comments`, `#role` and `#organization` will not trigger extra HTTP requests as the data has already been fetched.
313c487 Rémi Prévost Add better documentation for relationships
authored
280
3bb8232 Rémi Prévost Add documentation for hooks
authored
281 ## Hooks
282
283 You can add *before* and *after* hooks to your models that are triggered on specific actions (`save`, `update`, `create`, `destroy`):
284
285 ```ruby
286 class User
287 include Her::Model
288 before_save :set_internal_id
289
290 def set_internal_id
291 self.internal_id = 42 # Will be passed in the HTTP request
292 end
293 end
ee90237 Rémi Prévost Add example for hooks
authored
294
295 @user = User.create(:fullname => "Tobias Fünke")
296 # POST /users&fullname=Tobias+Fünke&internal_id=42
3bb8232 Rémi Prévost Add documentation for hooks
authored
297 ```
298
6878101 Rémi Prévost Update documentation with new API code
authored
299 ## Custom requests
300
2c0c171 Rémi Prévost Add support for custom_<method> methods
authored
301 You can easily define custom requests for your models using `custom_get`, `custom_post`, etc.
302
303 ```ruby
304 class User
305 include Her::Model
306 custom_get :popular, :unpopular
307 custom_post :from_default
308 end
309
310 User.popular # => [#<User id=1>, #<User id=2>]
311 # GET /users/popular
312
313 User.unpopular # => [#<User id=3>, #<User id=4>]
314 # GET /users/unpopular
315
316 User.from_default(:name => "Maeby Fünke") # => #<User id=5>
317 # POST /users/from_default?name=Maeby+Fünke
318 ```
319
320 You can also use `get`, `post`, `put` or `delete` (which maps the returned data to either a collection or a resource).
6878101 Rémi Prévost Update documentation with new API code
authored
321
17d968c Rémi Prévost Improve support for custom methods
authored
322 ```ruby
323 class User
324 include Her::Model
a7ae25f Rémi Prévost Add support for symbols in custom requests
authored
325 end
326
37aef13 Rémi Prévost Add support for `get`, `post`, etc. wrapper methods
authored
327 User.get(:popular) # => [#<User id=1>, #<User id=2>]
a7ae25f Rémi Prévost Add support for symbols in custom requests
authored
328 # GET /users/popular
37aef13 Rémi Prévost Add support for `get`, `post`, etc. wrapper methods
authored
329
330 User.get(:single_best) # => #<User id=1>
331 # GET /users/single_best
a7ae25f Rémi Prévost Add support for symbols in custom requests
authored
332 ```
333
37aef13 Rémi Prévost Add support for `get`, `post`, etc. wrapper methods
authored
334 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 Rémi Prévost Add support for symbols in custom requests
authored
335
336 ```ruby
337 class User
338 include Her::Model
17d968c Rémi Prévost Improve support for custom methods
authored
339
340 def self.popular
37aef13 Rémi Prévost Add support for `get`, `post`, etc. wrapper methods
authored
341 get_collection(:popular)
17d968c Rémi Prévost Improve support for custom methods
authored
342 end
6878101 Rémi Prévost Update documentation with new API code
authored
343
17d968c Rémi Prévost Improve support for custom methods
authored
344 def self.total
37aef13 Rémi Prévost Add support for `get`, `post`, etc. wrapper methods
authored
345 get_raw(:stats) do |parsed_data|
17d968c Rémi Prévost Improve support for custom methods
authored
346 parsed_data[:data][:total_users]
347 end
348 end
349 end
350
a7ae25f Rémi Prévost Add support for symbols in custom requests
authored
351 User.popular # => [#<User id=1>, #<User id=2>]
352 User.total # => 42
17d968c Rémi Prévost Improve support for custom methods
authored
353 ```
7f7392f Rémi Prévost Improve README and add LICENSE
authored
354
37aef13 Rémi Prévost Add support for `get`, `post`, etc. wrapper methods
authored
355 You can also use full request paths (with strings instead of symbols).
356
357 ```ruby
358 class User
359 include Her::Model
360 end
361
362 User.get("/users/popular") # => [#<User id=1>, #<User id=2>]
363 # GET /users/popular
364 ```
365
fca11ad Rémi Prévost Use internal parameter to build custom paths
authored
366 ## Custom paths
367
368 You can define custom HTTP paths for your models:
369
370 ```ruby
371 class User
372 include Her::Model
373 collection_path "/hello_users/:id"
374 end
375
376 @user = User.find(1)
377 # GET /hello_users/1
378 ```
379
6bd587d Rémi Prévost Improve README, yay!
authored
380 You can also include custom variables in your paths:
fca11ad Rémi Prévost Use internal parameter to build custom paths
authored
381
382 ```ruby
383 class User
384 include Her::Model
6bd587d Rémi Prévost Improve README, yay!
authored
385 collection_path "/organizations/:organization_id/users"
fca11ad Rémi Prévost Use internal parameter to build custom paths
authored
386 end
387
388 @user = User.find(1, :_organization_id => 2)
389 # GET /organizations/2/users/1
390
391 @user = User.all(:_organization_id => 2)
392 # GET /organizations/2/users
6bd587d Rémi Prévost Improve README, yay!
authored
393
394 @user = User.new(:fullname => "Tobias Fünke", :organization_id => 2)
395 @user.save
396 # POST /organizations/2/users
fca11ad Rémi Prévost Use internal parameter to build custom paths
authored
397 ```
398
cdeb59f Rémi Prévost Add Multiple APIs section in README
authored
399 ## Multiple APIs
400
401 It is possible to use different APIs for different models. Instead of calling `Her::API.setup`, you can create instances of `Her::API`:
402
403 ```ruby
404 # config/initializers/her.rb
405 $my_api = Her::API.new
ec9699c Rémi Prévost Add support for Faraday connection options in Her::API#setup
authored
406 $my_api.setup :url => "https://my_api.example.com" do |builder|
53744d4 Rémi Prévost Do not set any default middleware
authored
407 builder.use Faraday::Request::UrlEncoded
408 builder.use Her::Middleware::DefaultParseJSON
409 builder.use Faraday::Adapter::NetHttp
410 end
cdeb59f Rémi Prévost Add Multiple APIs section in README
authored
411
412 $other_api = Her::API.new
ec9699c Rémi Prévost Add support for Faraday connection options in Her::API#setup
authored
413 $other_api.setup :url => "https://other_api.example.com" do |builder|
53744d4 Rémi Prévost Do not set any default middleware
authored
414 builder.use Faraday::Request::UrlEncoded
415 builder.use Her::Middleware::DefaultParseJSON
416 builder.use Faraday::Adapter::NetHttp
417 end
cdeb59f Rémi Prévost Add Multiple APIs section in README
authored
418 ```
419
420 You can then define which API a model will use:
421
422 ```ruby
423 class User
424 include Her::Model
425 uses_api $my_api
426 end
427
428 class Category
429 include Her::Model
430 uses_api $other_api
431 end
432
433 User.all
434 # GET https://my_api.example.com/users
435
436 Category.all
437 # GET https://other_api.example.com/categories
438 ```
439
3805014 Rémi Prévost Add SSL section
authored
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 |builder|
447 builder.use Faraday::Request::UrlEncoded
448 builder.use Her::Middleware::DefaultParseJSON
449 builder.use Faraday::Adapter::NetHttp
450 end
451 ```
452
c4108fa Rémi Prévost Add README section for testing models
authored
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 |builder|
468 builder.use Her::Middleware::FirstLevelParseJSON
469 builder.use Faraday::Request::UrlEncoded
470 builder.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
7f7392f Rémi Prévost Improve README and add LICENSE
authored
485 ## Things to be done
486
a6e9967 Rémi Prévost Update README with more examples
authored
487 * Better error handling
6bd587d Rémi Prévost Improve README, yay!
authored
488 * Better API documentation (using YARD)
7f7392f Rémi Prévost Improve README and add LICENSE
authored
489
676a56f Rémi Prévost Improve Contribute section in README
authored
490 ## Contribute
7f7392f Rémi Prévost Improve README and add LICENSE
authored
491
676a56f Rémi Prévost Improve Contribute section in README
authored
492 Yes please! Feel free to contribute and submit issues/pull requests [on GitHub](https://github.com/remiprev/her/issues).
493
494 ### How to contribute
495
496 * Fork the repository
497 * Implement your feature or fix
498 * Add examples that describe it (in the `spec` directory)
499 * Make sure `bundle exec rake spec` passes after your modifications
500 * Commit (bonus points for doing it in a `feature-*` branch)
501 * Send a pull request!
502
503 ### Contributors
504
505 These fine folks helped with Her:
7f9f399 Rémi Prévost Add contributors, woohoo!
authored
506
507 * [@jfcixmedia](https://github.com/jfcixmedia)
508 * [@EtienneLem](https://github.com/EtienneLem)
a366819 Rémi Prévost Add @rafaelss to contributors
authored
509 * [@rafaelss](https://github.com/rafaelss)
855b897 Rémi Prévost Update contributors with @tysontate
authored
510 * [@tysontate](https://github.com/tysontate)
2163cf5 Rémi Prévost Add Nicolas Fouché to contributors list
authored
511 * [@nfo](https://github.com/nfo)
f18374a Rémi Prévost Add @simonprevost to contributors
authored
512 * [@simonprevost](https://github.com/simonprevost)
7f7392f Rémi Prévost Improve README and add LICENSE
authored
513
514 ## License
515
fd5bb21 François Bernier Show the correct license name in README
fbernier authored
516 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.