her 0.3.7 → 0.3.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/README.md +565 -10
- data/Rakefile +0 -16
- data/{CONTRIBUTING.md → docs/CONTRIBUTING.md} +0 -0
- data/{UPGRADE.md → docs/UPGRADE.md} +2 -0
- data/her.gemspec +3 -9
- data/lib/her/api.rb +1 -1
- data/lib/her/model/hooks.rb +8 -1
- data/lib/her/model/introspection.rb +1 -1
- data/lib/her/model/orm.rb +9 -2
- data/lib/her/version.rb +1 -1
- data/spec/api_spec.rb +6 -0
- data/spec/model/hooks_spec.rb +131 -0
- data/spec/model/introspection_spec.rb +10 -2
- data/spec/spec_helper.rb +1 -1
- metadata +12 -113
- data/FEATURES.md +0 -296
- data/Guardfile +0 -7
- data/MIDDLEWARE.md +0 -183
- data/TESTING.md +0 -88
data/spec/spec_helper.rb
CHANGED
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.3.
|
4
|
+
version: 0.3.8
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date:
|
12
|
+
date: 2013-01-14 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: rake
|
@@ -34,7 +34,7 @@ dependencies:
|
|
34
34
|
requirements:
|
35
35
|
- - ~>
|
36
36
|
- !ruby/object:Gem::Version
|
37
|
-
version: '2.
|
37
|
+
version: '2.12'
|
38
38
|
type: :development
|
39
39
|
prerelease: false
|
40
40
|
version_requirements: !ruby/object:Gem::Requirement
|
@@ -42,39 +42,7 @@ dependencies:
|
|
42
42
|
requirements:
|
43
43
|
- - ~>
|
44
44
|
- !ruby/object:Gem::Version
|
45
|
-
version: '2.
|
46
|
-
- !ruby/object:Gem::Dependency
|
47
|
-
name: yard
|
48
|
-
requirement: !ruby/object:Gem::Requirement
|
49
|
-
none: false
|
50
|
-
requirements:
|
51
|
-
- - ~>
|
52
|
-
- !ruby/object:Gem::Version
|
53
|
-
version: '0.8'
|
54
|
-
type: :development
|
55
|
-
prerelease: false
|
56
|
-
version_requirements: !ruby/object:Gem::Requirement
|
57
|
-
none: false
|
58
|
-
requirements:
|
59
|
-
- - ~>
|
60
|
-
- !ruby/object:Gem::Version
|
61
|
-
version: '0.8'
|
62
|
-
- !ruby/object:Gem::Dependency
|
63
|
-
name: redcarpet
|
64
|
-
requirement: !ruby/object:Gem::Requirement
|
65
|
-
none: false
|
66
|
-
requirements:
|
67
|
-
- - ~>
|
68
|
-
- !ruby/object:Gem::Version
|
69
|
-
version: '2.1'
|
70
|
-
type: :development
|
71
|
-
prerelease: false
|
72
|
-
version_requirements: !ruby/object:Gem::Requirement
|
73
|
-
none: false
|
74
|
-
requirements:
|
75
|
-
- - ~>
|
76
|
-
- !ruby/object:Gem::Version
|
77
|
-
version: '2.1'
|
45
|
+
version: '2.12'
|
78
46
|
- !ruby/object:Gem::Dependency
|
79
47
|
name: mocha
|
80
48
|
requirement: !ruby/object:Gem::Requirement
|
@@ -82,71 +50,7 @@ dependencies:
|
|
82
50
|
requirements:
|
83
51
|
- - ~>
|
84
52
|
- !ruby/object:Gem::Version
|
85
|
-
version: '0.
|
86
|
-
type: :development
|
87
|
-
prerelease: false
|
88
|
-
version_requirements: !ruby/object:Gem::Requirement
|
89
|
-
none: false
|
90
|
-
requirements:
|
91
|
-
- - ~>
|
92
|
-
- !ruby/object:Gem::Version
|
93
|
-
version: '0.12'
|
94
|
-
- !ruby/object:Gem::Dependency
|
95
|
-
name: guard
|
96
|
-
requirement: !ruby/object:Gem::Requirement
|
97
|
-
none: false
|
98
|
-
requirements:
|
99
|
-
- - ~>
|
100
|
-
- !ruby/object:Gem::Version
|
101
|
-
version: '1.2'
|
102
|
-
type: :development
|
103
|
-
prerelease: false
|
104
|
-
version_requirements: !ruby/object:Gem::Requirement
|
105
|
-
none: false
|
106
|
-
requirements:
|
107
|
-
- - ~>
|
108
|
-
- !ruby/object:Gem::Version
|
109
|
-
version: '1.2'
|
110
|
-
- !ruby/object:Gem::Dependency
|
111
|
-
name: guard-rspec
|
112
|
-
requirement: !ruby/object:Gem::Requirement
|
113
|
-
none: false
|
114
|
-
requirements:
|
115
|
-
- - ~>
|
116
|
-
- !ruby/object:Gem::Version
|
117
|
-
version: '2.3'
|
118
|
-
type: :development
|
119
|
-
prerelease: false
|
120
|
-
version_requirements: !ruby/object:Gem::Requirement
|
121
|
-
none: false
|
122
|
-
requirements:
|
123
|
-
- - ~>
|
124
|
-
- !ruby/object:Gem::Version
|
125
|
-
version: '2.3'
|
126
|
-
- !ruby/object:Gem::Dependency
|
127
|
-
name: rb-fsevent
|
128
|
-
requirement: !ruby/object:Gem::Requirement
|
129
|
-
none: false
|
130
|
-
requirements:
|
131
|
-
- - ~>
|
132
|
-
- !ruby/object:Gem::Version
|
133
|
-
version: '0.9'
|
134
|
-
type: :development
|
135
|
-
prerelease: false
|
136
|
-
version_requirements: !ruby/object:Gem::Requirement
|
137
|
-
none: false
|
138
|
-
requirements:
|
139
|
-
- - ~>
|
140
|
-
- !ruby/object:Gem::Version
|
141
|
-
version: '0.9'
|
142
|
-
- !ruby/object:Gem::Dependency
|
143
|
-
name: growl
|
144
|
-
requirement: !ruby/object:Gem::Requirement
|
145
|
-
none: false
|
146
|
-
requirements:
|
147
|
-
- - ~>
|
148
|
-
- !ruby/object:Gem::Version
|
149
|
-
version: '1.0'
|
53
|
+
version: '0.13'
|
150
54
|
type: :development
|
151
55
|
prerelease: false
|
152
56
|
version_requirements: !ruby/object:Gem::Requirement
|
@@ -154,7 +58,7 @@ dependencies:
|
|
154
58
|
requirements:
|
155
59
|
- - ~>
|
156
60
|
- !ruby/object:Gem::Version
|
157
|
-
version: '
|
61
|
+
version: '0.13'
|
158
62
|
- !ruby/object:Gem::Dependency
|
159
63
|
name: activesupport
|
160
64
|
requirement: !ruby/object:Gem::Requirement
|
@@ -194,7 +98,7 @@ dependencies:
|
|
194
98
|
requirements:
|
195
99
|
- - ~>
|
196
100
|
- !ruby/object:Gem::Version
|
197
|
-
version: '1.
|
101
|
+
version: '1.5'
|
198
102
|
type: :runtime
|
199
103
|
prerelease: false
|
200
104
|
version_requirements: !ruby/object:Gem::Requirement
|
@@ -202,7 +106,7 @@ dependencies:
|
|
202
106
|
requirements:
|
203
107
|
- - ~>
|
204
108
|
- !ruby/object:Gem::Version
|
205
|
-
version: '1.
|
109
|
+
version: '1.5'
|
206
110
|
description: Her is an ORM that maps REST resources and collections to Ruby objects
|
207
111
|
email:
|
208
112
|
- remi@exomel.com
|
@@ -213,16 +117,12 @@ files:
|
|
213
117
|
- .gitignore
|
214
118
|
- .rspec
|
215
119
|
- .travis.yml
|
216
|
-
- CONTRIBUTING.md
|
217
|
-
- FEATURES.md
|
218
120
|
- Gemfile
|
219
|
-
- Guardfile
|
220
121
|
- LICENSE
|
221
|
-
- MIDDLEWARE.md
|
222
122
|
- README.md
|
223
123
|
- Rakefile
|
224
|
-
-
|
225
|
-
- UPGRADE.md
|
124
|
+
- docs/CONTRIBUTING.md
|
125
|
+
- docs/UPGRADE.md
|
226
126
|
- examples/twitter-oauth/Gemfile
|
227
127
|
- examples/twitter-oauth/app.rb
|
228
128
|
- examples/twitter-oauth/config.ru
|
@@ -277,7 +177,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
277
177
|
version: '0'
|
278
178
|
segments:
|
279
179
|
- 0
|
280
|
-
hash: -
|
180
|
+
hash: -2988245247515927159
|
281
181
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
282
182
|
none: false
|
283
183
|
requirements:
|
@@ -286,7 +186,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
286
186
|
version: '0'
|
287
187
|
segments:
|
288
188
|
- 0
|
289
|
-
hash: -
|
189
|
+
hash: -2988245247515927159
|
290
190
|
requirements: []
|
291
191
|
rubyforge_project:
|
292
192
|
rubygems_version: 1.8.24
|
@@ -308,4 +208,3 @@ test_files:
|
|
308
208
|
- spec/model/relationships_spec.rb
|
309
209
|
- spec/model_spec.rb
|
310
210
|
- spec/spec_helper.rb
|
311
|
-
has_rdoc:
|
data/FEATURES.md
DELETED
@@ -1,296 +0,0 @@
|
|
1
|
-
# Features
|
2
|
-
|
3
|
-
## Methods
|
4
|
-
|
5
|
-
```ruby
|
6
|
-
class User
|
7
|
-
include Her::Model
|
8
|
-
end
|
9
|
-
|
10
|
-
# Update a fetched resource
|
11
|
-
user = User.find(1)
|
12
|
-
user.fullname = "Lindsay Fünke"
|
13
|
-
# OR user.assign_attributes :fullname => "Lindsay Fünke"
|
14
|
-
user.save
|
15
|
-
|
16
|
-
# Update a resource without fetching it
|
17
|
-
User.save_existing(1, :fullname => "Lindsay Fünke")
|
18
|
-
|
19
|
-
# Destroy a fetched resource
|
20
|
-
user = User.find(1)
|
21
|
-
user.destroy
|
22
|
-
|
23
|
-
# Destroy a resource without fetching it
|
24
|
-
User.destroy_existing(1)
|
25
|
-
|
26
|
-
# Fetching a collection of resources
|
27
|
-
User.all
|
28
|
-
|
29
|
-
# Create a new resource
|
30
|
-
User.create(:fullname => "Maeby Fünke")
|
31
|
-
|
32
|
-
# Save a new resource
|
33
|
-
user = User.new(:fullname => "Maeby Fünke")
|
34
|
-
user.save
|
35
|
-
```
|
36
|
-
|
37
|
-
## Relationships
|
38
|
-
|
39
|
-
You can define `has_many`, `has_one` and `belongs_to` relationships in your models. The relationship data is handled in two different ways.
|
40
|
-
|
41
|
-
1. If Her finds relationship data when parsing a resource, that data will be used to create the associated model objects on the resource.
|
42
|
-
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).
|
43
|
-
|
44
|
-
For example:
|
45
|
-
|
46
|
-
```ruby
|
47
|
-
class User
|
48
|
-
include Her::Model
|
49
|
-
has_many :comments
|
50
|
-
has_one :role
|
51
|
-
belongs_to :organization
|
52
|
-
end
|
53
|
-
|
54
|
-
class Comment
|
55
|
-
include Her::Model
|
56
|
-
end
|
57
|
-
|
58
|
-
class Role
|
59
|
-
include Her::Model
|
60
|
-
end
|
61
|
-
|
62
|
-
class Organization
|
63
|
-
include Her::Model
|
64
|
-
end
|
65
|
-
```
|
66
|
-
|
67
|
-
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:
|
68
|
-
|
69
|
-
```ruby
|
70
|
-
@user = User.find(1)
|
71
|
-
# {
|
72
|
-
# :data => {
|
73
|
-
# :id => 1,
|
74
|
-
# :name => "George Michael Bluth",
|
75
|
-
# :comments => [
|
76
|
-
# { :id => 1, :text => "Foo" },
|
77
|
-
# { :id => 2, :text => "Bar" }
|
78
|
-
# ],
|
79
|
-
# :role => { :id => 1, :name => "Admin" },
|
80
|
-
# :organization => { :id => 2, :name => "Bluth Company" }
|
81
|
-
# }
|
82
|
-
# }
|
83
|
-
@user.comments
|
84
|
-
# [#<Comment id=1 text="Foo">, #<Comment id=2 text="Bar">]
|
85
|
-
@user.role
|
86
|
-
# #<Role id=1 name="Admin">
|
87
|
-
@user.organization
|
88
|
-
# #<Organization id=2 name="Bluth Company">
|
89
|
-
```
|
90
|
-
|
91
|
-
If there’s no relationship data in the resource, Her makes a HTTP request to retrieve the data.
|
92
|
-
|
93
|
-
```ruby
|
94
|
-
@user = User.find(1)
|
95
|
-
# { :data => { :id => 1, :name => "George Michael Bluth", :organization_id => 2 }}
|
96
|
-
|
97
|
-
# has_many relationship:
|
98
|
-
@user.comments
|
99
|
-
# GET /users/1/comments
|
100
|
-
# [#<Comment id=1>, #<Comment id=2>]
|
101
|
-
|
102
|
-
# has_one relationship:
|
103
|
-
@user.role
|
104
|
-
# GET /users/1/role
|
105
|
-
# #<Role id=1>
|
106
|
-
|
107
|
-
# belongs_to relationship:
|
108
|
-
@user.organization
|
109
|
-
# (the organization id comes from :organization_id, by default)
|
110
|
-
# GET /organizations/2
|
111
|
-
# #<Organization id=2>
|
112
|
-
```
|
113
|
-
|
114
|
-
Subsequent calls to `#comments`, `#role` and `#organization` will not trigger extra HTTP requests and will return the cached objects.
|
115
|
-
|
116
|
-
## Hooks
|
117
|
-
|
118
|
-
You can add *before* and *after* hooks to your models that are triggered on specific actions (`save`, `update`, `create`, `destroy`):
|
119
|
-
|
120
|
-
```ruby
|
121
|
-
class User
|
122
|
-
include Her::Model
|
123
|
-
before_save :set_internal_id
|
124
|
-
|
125
|
-
def set_internal_id
|
126
|
-
self.internal_id = 42 # Will be passed in the HTTP request
|
127
|
-
end
|
128
|
-
end
|
129
|
-
|
130
|
-
@user = User.create(:fullname => "Tobias Fünke")
|
131
|
-
# POST /users&fullname=Tobias+Fünke&internal_id=42
|
132
|
-
```
|
133
|
-
|
134
|
-
## Custom requests
|
135
|
-
|
136
|
-
You can easily define custom requests for your models using `custom_get`, `custom_post`, etc.
|
137
|
-
|
138
|
-
```ruby
|
139
|
-
class User
|
140
|
-
include Her::Model
|
141
|
-
custom_get :popular, :unpopular
|
142
|
-
custom_post :from_default
|
143
|
-
end
|
144
|
-
|
145
|
-
User.popular
|
146
|
-
# GET /users/popular
|
147
|
-
# [#<User id=1>, #<User id=2>]
|
148
|
-
|
149
|
-
User.unpopular
|
150
|
-
# GET /users/unpopular
|
151
|
-
# [#<User id=3>, #<User id=4>]
|
152
|
-
|
153
|
-
User.from_default(:name => "Maeby Fünke")
|
154
|
-
# POST /users/from_default?name=Maeby+Fünke
|
155
|
-
# #<User id=5 name="Maeby Fünke">
|
156
|
-
```
|
157
|
-
|
158
|
-
You can also use `get`, `post`, `put` or `delete` (which maps the returned data to either a collection or a resource).
|
159
|
-
|
160
|
-
```ruby
|
161
|
-
class User
|
162
|
-
include Her::Model
|
163
|
-
end
|
164
|
-
|
165
|
-
User.get(:popular)
|
166
|
-
# GET /users/popular
|
167
|
-
# [#<User id=1>, #<User id=2>]
|
168
|
-
|
169
|
-
User.get(:single_best)
|
170
|
-
# GET /users/single_best
|
171
|
-
# #<User id=1>
|
172
|
-
```
|
173
|
-
|
174
|
-
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.).
|
175
|
-
|
176
|
-
```ruby
|
177
|
-
class User
|
178
|
-
include Her::Model
|
179
|
-
|
180
|
-
def self.popular
|
181
|
-
get_collection(:popular)
|
182
|
-
end
|
183
|
-
|
184
|
-
def self.total
|
185
|
-
get_raw(:stats) do |parsed_data|
|
186
|
-
parsed_data[:data][:total_users]
|
187
|
-
end
|
188
|
-
end
|
189
|
-
end
|
190
|
-
|
191
|
-
User.popular
|
192
|
-
# GET /users/popular
|
193
|
-
# [#<User id=1>, #<User id=2>]
|
194
|
-
User.total
|
195
|
-
# GET /users/stats
|
196
|
-
# => 42
|
197
|
-
```
|
198
|
-
|
199
|
-
You can also use full request paths (with strings instead of symbols).
|
200
|
-
|
201
|
-
```ruby
|
202
|
-
class User
|
203
|
-
include Her::Model
|
204
|
-
end
|
205
|
-
|
206
|
-
User.get("/users/popular")
|
207
|
-
# GET /users/popular
|
208
|
-
# [#<User id=1>, #<User id=2>]
|
209
|
-
```
|
210
|
-
|
211
|
-
## Custom paths
|
212
|
-
|
213
|
-
You can define custom HTTP paths for your models:
|
214
|
-
|
215
|
-
```ruby
|
216
|
-
class User
|
217
|
-
include Her::Model
|
218
|
-
collection_path "/hello_users/:id"
|
219
|
-
end
|
220
|
-
|
221
|
-
@user = User.find(1)
|
222
|
-
# GET /hello_users/1
|
223
|
-
```
|
224
|
-
|
225
|
-
You can also include custom variables in your paths:
|
226
|
-
|
227
|
-
```ruby
|
228
|
-
class User
|
229
|
-
include Her::Model
|
230
|
-
collection_path "/organizations/:organization_id/users"
|
231
|
-
end
|
232
|
-
|
233
|
-
@user = User.find(1, :_organization_id => 2)
|
234
|
-
# GET /organizations/2/users/1
|
235
|
-
|
236
|
-
@user = User.all(:_organization_id => 2)
|
237
|
-
# GET /organizations/2/users
|
238
|
-
|
239
|
-
@user = User.new(:fullname => "Tobias Fünke", :organization_id => 2)
|
240
|
-
@user.save
|
241
|
-
# POST /organizations/2/users
|
242
|
-
```
|
243
|
-
|
244
|
-
## Multiple APIs
|
245
|
-
|
246
|
-
It is possible to use different APIs for different models. Instead of calling `Her::API.setup`, you can create instances of `Her::API`:
|
247
|
-
|
248
|
-
```ruby
|
249
|
-
# config/initializers/her.rb
|
250
|
-
$my_api = Her::API.new
|
251
|
-
$my_api.setup :url => "https://my_api.example.com" do |connection|
|
252
|
-
connection.use Faraday::Request::UrlEncoded
|
253
|
-
connection.use Her::Middleware::DefaultParseJSON
|
254
|
-
connection.use Faraday::Adapter::NetHttp
|
255
|
-
end
|
256
|
-
|
257
|
-
$other_api = Her::API.new
|
258
|
-
$other_api.setup :url => "https://other_api.example.com" do |connection|
|
259
|
-
connection.use Faraday::Request::UrlEncoded
|
260
|
-
connection.use Her::Middleware::DefaultParseJSON
|
261
|
-
connection.use Faraday::Adapter::NetHttp
|
262
|
-
end
|
263
|
-
```
|
264
|
-
|
265
|
-
You can then define which API a model will use:
|
266
|
-
|
267
|
-
```ruby
|
268
|
-
class User
|
269
|
-
include Her::Model
|
270
|
-
uses_api $my_api
|
271
|
-
end
|
272
|
-
|
273
|
-
class Category
|
274
|
-
include Her::Model
|
275
|
-
uses_api $other_api
|
276
|
-
end
|
277
|
-
|
278
|
-
User.all
|
279
|
-
# GET https://my_api.example.com/users
|
280
|
-
|
281
|
-
Category.all
|
282
|
-
# GET https://other_api.example.com/categories
|
283
|
-
```
|
284
|
-
|
285
|
-
## SSL
|
286
|
-
|
287
|
-
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.
|
288
|
-
|
289
|
-
```ruby
|
290
|
-
ssl_options = { :ca_path => "/usr/lib/ssl/certs" }
|
291
|
-
Her::API.setup :url => "https://api.example.com", :ssl => ssl_options do |connection|
|
292
|
-
connection.use Faraday::Request::UrlEncoded
|
293
|
-
connection.use Her::Middleware::DefaultParseJSON
|
294
|
-
connection.use Faraday::Adapter::NetHttp
|
295
|
-
end
|
296
|
-
```
|