Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Newer
Older
100644 215 lines (157 sloc) 6.125 kB
871ef96 @remiprev Add README
authored
1 # Her
2
3 [![Build Status](https://secure.travis-ci.org/remiprev/her.png)](http://travis-ci.org/remiprev/her)
4
a6e9967 @remiprev Update README with more examples
authored
5 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 and no database.
871ef96 @remiprev Add README
authored
6
7 ## Installation
8
9 In your Gemfile, add:
10
60f209e @remiprev Update README
authored
11 ```ruby
12 gem "her"
13 ```
871ef96 @remiprev Add README
authored
14
6878101 @remiprev Update documentation with new API code
authored
15 That’s it!
16
871ef96 @remiprev Add README
authored
17 ## Usage
18
6878101 @remiprev Update documentation with new API code
authored
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:
871ef96 @remiprev Add README
authored
20
21 ```ruby
cdeb59f @remiprev Add Multiple APIs section in README
authored
22 # config/initializers/her.rb
6878101 @remiprev Update documentation with new API code
authored
23 Her::API.setup :base_uri => "https://api.example.com"
871ef96 @remiprev Add README
authored
24 ```
25
6878101 @remiprev Update documentation with new API code
authored
26 And then to add the ORM behavior to a class, you just have to include `Her::Model` in it:
871ef96 @remiprev Add README
authored
27
28 ```ruby
29 class User
30 include Her::Model
31 end
32 ```
33
34 After that, using Her is very similar to many ActiveModel-like ORMs:
35
36 ```ruby
a6e9967 @remiprev Update README with more examples
authored
37 User.all
cdeb59f @remiprev Add Multiple APIs section in README
authored
38 # GET https://api.example.com/users and return an array of User objects
a6e9967 @remiprev Update README with more examples
authored
39
40 User.find(1)
cdeb59f @remiprev Add Multiple APIs section in README
authored
41 # GET https://api.example.com/users/1 and return a User object
a6e9967 @remiprev Update README with more examples
authored
42
43 @user = User.create(:fullname => "Tobias Fünke")
bc5779a @remiprev Fix typo
authored
44 # POST "https://api.example.com/users" with the data and return a User object
a6e9967 @remiprev Update README with more examples
authored
45
46 @user = User.new(:fullname => "Tobias Fünke")
47 @user.occupation = "actor"
48 @user.save
cdeb59f @remiprev Add Multiple APIs section in README
authored
49 # POST https://api.example.com/users with the data and return a User object
a6e9967 @remiprev Update README with more examples
authored
50
51 @user = User.find(1)
52 @user.fullname = "Lindsay Fünke"
53 @user.save
cdeb59f @remiprev Add Multiple APIs section in README
authored
54 # PUT https://api.example.com/users/1 with the data and return+update the User object
871ef96 @remiprev Add README
authored
55 ```
60f209e @remiprev Update README
authored
56
ab31348 @remiprev Add Parsing data section in README
authored
57 ## Parsing data
58
59 By default, Her handles JSON data. It expects the data to be formatted in a certain structure. The default is this:
60
61 ```json
62 // The response of GET /users/1
63 {
64 "data" : {
65 "id" : 1,
66 "name" : "Tobias Fünke"
67 }
68 }
69
70 // The response of GET /users
71 {
72 "data" : [
73 {
74 "id" : 1,
75 "name" : "Tobias Fünke"
76 },
77 {
78 "id" : 2,
79 "name" : "Lindsay Fünke"
80 }
81 ]
82 "metadata" : {
83 "page" : 1,
84 "per_page" : 10
85 }
86 }
87 ```
88
89 However, you can define your own parsing method, with `Her::API.parse_with`. The `parse_with` method takes a block which will be executed each time data from an HTTP response needs to be parsed. The block is expected to return a hash with three keys: `data`, `errors` and `metadata`. The following code enables parsing JSON data and treating this data as first-level properties.
90
91 ```ruby
92 Her::API.setup :base_uri => "https://api.example.com"
93 Her::API.parse_with |response|
94 json = JSON.parse(response.body, :symbolize_names => true)
95 errors = json.delete(:errors)
96 {
97 :data => json,
98 :errors => errors || [],
99 :metadata => {}
100 }
101 end
102 ```
103
104 This feature is not stable and might change in the future, probably by using a middleware throught [Faraday](https://github.com/technoweenie/faraday).
105
6878101 @remiprev Update documentation with new API code
authored
106 ## Relationships
107
313c487 @remiprev Add better documentation for relationships
authored
108 You can define `has_many` relationships in your models. The relationship data is handled in two different ways. When parsing a resource from JSON data, if there’s a relationship data included, it will be used to create new Ruby objects.
109
110 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).
111
112 For example, with this setup:
113
6878101 @remiprev Update documentation with new API code
authored
114 ```ruby
115 class User
116 include Her::Model
117 has_many :comments
118 end
119
120 class Comment
121 include Her::Model
122 end
313c487 @remiprev Add better documentation for relationships
authored
123 ```
124
dc37005 @remiprev Better english in README
authored
125 If there’s relationship data in the resource, no extra HTTP request is made when calling the `#comments` method and an array of resources are returned:
6878101 @remiprev Update documentation with new API code
authored
126
313c487 @remiprev Add better documentation for relationships
authored
127 ```ruby
a6e9967 @remiprev Update README with more examples
authored
128 @user = User.find(1) # { :data => { :id => 1, :name => "George Michael Bluth", :comments => [{ :id => 1, :text => "Foo" }, { :id => 2, :text => "Bar" }] }}
313c487 @remiprev Add better documentation for relationships
authored
129 @user.comments # => [#<Comment id=1>, #<Comment id=2>] fetched directly from @user
6878101 @remiprev Update documentation with new API code
authored
130 ```
131
313c487 @remiprev Add better documentation for relationships
authored
132 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:
133
134 ```ruby
a6e9967 @remiprev Update README with more examples
authored
135 @user = User.find(1) # { :data => { :id => 1, :name => "George Michael Bluth" }}
313c487 @remiprev Add better documentation for relationships
authored
136 @user.comments # => [#<Comment id=1>, #<Comment id=2>] fetched from /users/1/comments
137 ```
138
139 However, subsequent calls to `#comments` will not trigger the extra HTTP request.
140
6878101 @remiprev Update documentation with new API code
authored
141 ## Custom requests
142
a6e9967 @remiprev Update README with more examples
authored
143 You can easily add custom methods for your models. You can either use `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). Other HTTP methods are supported (`post_raw`, `put_resource`, etc.)
6878101 @remiprev Update documentation with new API code
authored
144
17d968c @remiprev Improve support for custom methods
authored
145 ```ruby
146 class User
147 include Her::Model
148
149 def self.popular
150 get_collection("/users/popular")
151 end
6878101 @remiprev Update documentation with new API code
authored
152
17d968c @remiprev Improve support for custom methods
authored
153 def self.total
154 get_raw("/users/stats") do |parsed_data|
155 parsed_data[:data][:total_users]
156 end
157 end
158 end
159
160 User.popular # => [#<User id=1>, #<User id=2>]
161 User.total # => 42
162 ```
7f7392f @remiprev Improve README and add LICENSE
authored
163
cdeb59f @remiprev Add Multiple APIs section in README
authored
164 ## Multiple APIs
165
166 It is possible to use different APIs for different models. Instead of calling `Her::API.setup`, you can create instances of `Her::API`:
167
168 ```ruby
169 # config/initializers/her.rb
170 $my_api = Her::API.new
171 $my_api.setup :base_uri => "https://my_api.example.com"
172
173 $other_api = Her::API.new
174 $other_api.setup :base_uri => "https://other_api.example.com"
175 ```
176
177 You can then define which API a model will use:
178
179 ```ruby
180 class User
181 include Her::Model
182 uses_api $my_api
183 end
184
185 class Category
186 include Her::Model
187 uses_api $other_api
188 end
189
190 User.all
191 # GET https://my_api.example.com/users
192
193 Category.all
194 # GET https://other_api.example.com/categories
195 ```
196
7f7392f @remiprev Improve README and add LICENSE
authored
197 ## Things to be done
198
199 * Deleting resources
200 * Support for Faraday middleware
201 * Hooks before save, update, create, destroy, etc.
a6e9967 @remiprev Update README with more examples
authored
202 * Better error handling
7f7392f @remiprev Improve README and add LICENSE
authored
203 * Better introspection for debug
204 * Better documentation
205
206 ## Contributors
207
208 Feel free to contribute and submit issues/pull requests [on GitHub](https://github.com/remiprev/her/issues).
209
210 Take a look at the `spec` folder before you do, and make sure `bundle exec rake spec` passes after your modifications :)
211
212 ## License
213
e0f75c8 @remiprev Fix typo in README, d’uh.
authored
214 Her is © 2012 [Rémi Prévost](http://exomel.com) and may be freely distributed under the [LITL license](https://github.com/remiprev/her/blob/master/LICENSE). See the `LICENSE` file.
Something went wrong with that request. Please try again.