her 0.1.7 → 0.1.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/LICENSE +7 -3
- data/README.md +82 -40
- data/Rakefile +1 -1
- data/her.gemspec +2 -2
- data/lib/her.rb +1 -1
- data/lib/her/api.rb +48 -32
- data/lib/her/middleware/default_parse_json.rb +18 -8
- data/lib/her/model.rb +3 -1
- data/lib/her/model/hooks.rb +52 -12
- data/lib/her/model/http.rb +142 -0
- data/lib/her/model/introspection.rb +32 -0
- data/lib/her/model/orm.rb +46 -20
- data/lib/her/model/relationships.rb +51 -16
- data/lib/her/version.rb +1 -1
- data/spec/api_spec.rb +25 -4
- data/spec/middleware/default_parse_json_spec.rb +24 -0
- data/spec/model/hooks_spec.rb +80 -80
- data/spec/model/http_spec.rb +58 -0
- data/spec/model/introspection_spec.rb +27 -0
- data/spec/model/orm_spec.rb +8 -0
- metadata +15 -10
data/lib/her/model/http.rb
CHANGED
@@ -37,13 +37,35 @@ module Her
|
|
37
37
|
yield @her_api.request(attrs)
|
38
38
|
end # }}}
|
39
39
|
|
40
|
+
# Make a GET request and return either a collection or a resource
|
41
|
+
#
|
42
|
+
# @example
|
43
|
+
# class User
|
44
|
+
# include Her::Model
|
45
|
+
# end
|
46
|
+
#
|
47
|
+
# @popular_users = User.get(:popular)
|
48
|
+
# # Fetched via GET "/users/popular"
|
49
|
+
def get(path, attrs={}) # {{{
|
50
|
+
path = "#{@her_collection_path}/#{path}" if path.is_a?(Symbol)
|
51
|
+
get_raw(path, attrs) do |parsed_data|
|
52
|
+
if parsed_data[:data].is_a?(Array)
|
53
|
+
new_collection(parsed_data)
|
54
|
+
else
|
55
|
+
new(parsed_data[:data])
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end # }}}
|
59
|
+
|
40
60
|
# Make a GET request and return the parsed JSON response (not mapped to objects)
|
41
61
|
def get_raw(path, attrs={}, &block) # {{{
|
62
|
+
path = "#{@her_collection_path}/#{path}" if path.is_a?(Symbol)
|
42
63
|
request(attrs.merge(:_method => :get, :_path => path), &block)
|
43
64
|
end # }}}
|
44
65
|
|
45
66
|
# Make a GET request and return a collection of resources
|
46
67
|
def get_collection(path, attrs={}) # {{{
|
68
|
+
path = "#{@her_collection_path}/#{path}" if path.is_a?(Symbol)
|
47
69
|
get_raw(path, attrs) do |parsed_data|
|
48
70
|
new_collection(parsed_data)
|
49
71
|
end
|
@@ -51,18 +73,33 @@ module Her
|
|
51
73
|
|
52
74
|
# Make a GET request and return a collection of resources
|
53
75
|
def get_resource(path, attrs={}) # {{{
|
76
|
+
path = "#{@her_collection_path}/#{path}" if path.is_a?(Symbol)
|
54
77
|
get_raw(path, attrs) do |parsed_data|
|
55
78
|
new(parsed_data[:data])
|
56
79
|
end
|
57
80
|
end # }}}
|
58
81
|
|
82
|
+
# Make a POST request and return either a collection or a resource
|
83
|
+
def post(path, attrs={}) # {{{
|
84
|
+
path = "#{@her_collection_path}/#{path}" if path.is_a?(Symbol)
|
85
|
+
post_raw(path, attrs) do |parsed_data|
|
86
|
+
if parsed_data[:data].is_a?(Array)
|
87
|
+
new_collection(parsed_data)
|
88
|
+
else
|
89
|
+
new(parsed_data[:data])
|
90
|
+
end
|
91
|
+
end
|
92
|
+
end # }}}
|
93
|
+
|
59
94
|
# Make a POST request and return the parsed JSON response (not mapped to objects)
|
60
95
|
def post_raw(path, attrs={}, &block) # {{{
|
96
|
+
path = "#{@her_collection_path}/#{path}" if path.is_a?(Symbol)
|
61
97
|
request(attrs.merge(:_method => :post, :_path => path), &block)
|
62
98
|
end # }}}
|
63
99
|
|
64
100
|
# Make a POST request and return a collection of resources
|
65
101
|
def post_collection(path, attrs={}) # {{{
|
102
|
+
path = "#{@her_collection_path}/#{path}" if path.is_a?(Symbol)
|
66
103
|
post_raw(path, attrs) do |parsed_data|
|
67
104
|
new_collection(parsed_data)
|
68
105
|
end
|
@@ -70,18 +107,33 @@ module Her
|
|
70
107
|
|
71
108
|
# Make a POST request and return a collection of resources
|
72
109
|
def post_resource(path, attrs={}) # {{{
|
110
|
+
path = "#{@her_collection_path}/#{path}" if path.is_a?(Symbol)
|
73
111
|
post_raw(path, attrs) do |parsed_data|
|
74
112
|
new(parsed_data[:data])
|
75
113
|
end
|
76
114
|
end # }}}
|
77
115
|
|
116
|
+
# Make a PUT request and return either a collection or a resource
|
117
|
+
def put(path, attrs={}) # {{{
|
118
|
+
path = "#{@her_collection_path}/#{path}" if path.is_a?(Symbol)
|
119
|
+
put_raw(path, attrs) do |parsed_data|
|
120
|
+
if parsed_data[:data].is_a?(Array)
|
121
|
+
new_collection(parsed_data)
|
122
|
+
else
|
123
|
+
new(parsed_data[:data])
|
124
|
+
end
|
125
|
+
end
|
126
|
+
end # }}}
|
127
|
+
|
78
128
|
# Make a PUT request and return the parsed JSON response (not mapped to objects)
|
79
129
|
def put_raw(path, attrs={}, &block) # {{{
|
130
|
+
path = "#{@her_collection_path}/#{path}" if path.is_a?(Symbol)
|
80
131
|
request(attrs.merge(:_method => :put, :_path => path), &block)
|
81
132
|
end # }}}
|
82
133
|
|
83
134
|
# Make a PUT request and return a collection of resources
|
84
135
|
def put_collection(path, attrs={}) # {{{
|
136
|
+
path = "#{@her_collection_path}/#{path}" if path.is_a?(Symbol)
|
85
137
|
put_raw(path, attrs) do |parsed_data|
|
86
138
|
new_collection(parsed_data)
|
87
139
|
end
|
@@ -89,18 +141,33 @@ module Her
|
|
89
141
|
|
90
142
|
# Make a PUT request and return a collection of resources
|
91
143
|
def put_resource(path, attrs={}) # {{{
|
144
|
+
path = "#{@her_collection_path}/#{path}" if path.is_a?(Symbol)
|
92
145
|
put_raw(path, attrs) do |parsed_data|
|
93
146
|
new(parsed_data[:data])
|
94
147
|
end
|
95
148
|
end # }}}
|
96
149
|
|
150
|
+
# Make a PATCH request and return either a collection or a resource
|
151
|
+
def patch(path, attrs={}) # {{{
|
152
|
+
path = "#{@her_collection_path}/#{path}" if path.is_a?(Symbol)
|
153
|
+
patch_raw(path, attrs) do |parsed_data|
|
154
|
+
if parsed_data[:data].is_a?(Array)
|
155
|
+
new_collection(parsed_data)
|
156
|
+
else
|
157
|
+
new(parsed_data[:data])
|
158
|
+
end
|
159
|
+
end
|
160
|
+
end # }}}
|
161
|
+
|
97
162
|
# Make a PATCH request and return the parsed JSON response (not mapped to objects)
|
98
163
|
def patch_raw(path, attrs={}, &block) # {{{
|
164
|
+
path = "#{@her_collection_path}/#{path}" if path.is_a?(Symbol)
|
99
165
|
request(attrs.merge(:_method => :patch, :_path => path), &block)
|
100
166
|
end # }}}
|
101
167
|
|
102
168
|
# Make a PATCH request and return a collection of resources
|
103
169
|
def patch_collection(path, attrs={}) # {{{
|
170
|
+
path = "#{@her_collection_path}/#{path}" if path.is_a?(Symbol)
|
104
171
|
patch_raw(path, attrs) do |parsed_data|
|
105
172
|
new_collection(parsed_data)
|
106
173
|
end
|
@@ -108,18 +175,33 @@ module Her
|
|
108
175
|
|
109
176
|
# Make a PATCH request and return a collection of resources
|
110
177
|
def patch_resource(path, attrs={}) # {{{
|
178
|
+
path = "#{@her_collection_path}/#{path}" if path.is_a?(Symbol)
|
111
179
|
patch_raw(path, attrs) do |parsed_data|
|
112
180
|
new(parsed_data[:data])
|
113
181
|
end
|
114
182
|
end # }}}
|
115
183
|
|
184
|
+
# Make a DELETE request and return either a collection or a resource
|
185
|
+
def delete(path, attrs={}) # {{{
|
186
|
+
path = "#{@her_collection_path}/#{path}" if path.is_a?(Symbol)
|
187
|
+
delete_raw(path, attrs) do |parsed_data|
|
188
|
+
if parsed_data[:data].is_a?(Array)
|
189
|
+
new_collection(parsed_data)
|
190
|
+
else
|
191
|
+
new(parsed_data[:data])
|
192
|
+
end
|
193
|
+
end
|
194
|
+
end # }}}
|
195
|
+
|
116
196
|
# Make a DELETE request and return the parsed JSON response (not mapped to objects)
|
117
197
|
def delete_raw(path, attrs={}, &block) # {{{
|
198
|
+
path = "#{@her_collection_path}/#{path}" if path.is_a?(Symbol)
|
118
199
|
request(attrs.merge(:_method => :delete, :_path => path), &block)
|
119
200
|
end # }}}
|
120
201
|
|
121
202
|
# Make a DELETE request and return a collection of resources
|
122
203
|
def delete_collection(path, attrs={}) # {{{
|
204
|
+
path = "#{@her_collection_path}/#{path}" if path.is_a?(Symbol)
|
123
205
|
delete_raw(path, attrs) do |parsed_data|
|
124
206
|
new_collection(parsed_data)
|
125
207
|
end
|
@@ -127,10 +209,70 @@ module Her
|
|
127
209
|
|
128
210
|
# Make a DELETE request and return a collection of resources
|
129
211
|
def delete_resource(path, attrs={}) # {{{
|
212
|
+
path = "#{@her_collection_path}/#{path}" if path.is_a?(Symbol)
|
130
213
|
delete_raw(path, attrs) do |parsed_data|
|
131
214
|
new(parsed_data[:data])
|
132
215
|
end
|
133
216
|
end # }}}
|
217
|
+
|
218
|
+
# Define custom GET requests
|
219
|
+
#
|
220
|
+
# @example
|
221
|
+
# class User
|
222
|
+
# include Her::Model
|
223
|
+
# custom_get :popular
|
224
|
+
# end
|
225
|
+
#
|
226
|
+
# User.popular
|
227
|
+
# # Fetched from GET "/users/popular"
|
228
|
+
def custom_get(*paths) # {{{
|
229
|
+
metaclass = (class << self; self; end)
|
230
|
+
paths.each do |path|
|
231
|
+
metaclass.send(:define_method, path.to_sym) do |*attrs|
|
232
|
+
get(path, attrs.first || Hash.new)
|
233
|
+
end
|
234
|
+
end
|
235
|
+
end # }}}
|
236
|
+
|
237
|
+
# Define custom POST requests
|
238
|
+
def custom_post(*paths) # {{{
|
239
|
+
metaclass = (class << self; self; end)
|
240
|
+
paths.each do |path|
|
241
|
+
metaclass.send(:define_method, path.to_sym) do |*attrs|
|
242
|
+
post(path, attrs.first || Hash.new)
|
243
|
+
end
|
244
|
+
end
|
245
|
+
end # }}}
|
246
|
+
|
247
|
+
# Define custom PUT requests
|
248
|
+
def custom_put(*paths) # {{{
|
249
|
+
metaclass = (class << self; self; end)
|
250
|
+
paths.each do |path|
|
251
|
+
metaclass.send(:define_method, path.to_sym) do |*attrs|
|
252
|
+
put(path, attrs.first || Hash.new)
|
253
|
+
end
|
254
|
+
end
|
255
|
+
end # }}}
|
256
|
+
|
257
|
+
# Define custom PATCH requests
|
258
|
+
def custom_patch(*paths) # {{{
|
259
|
+
metaclass = (class << self; self; end)
|
260
|
+
paths.each do |path|
|
261
|
+
metaclass.send(:define_method, path.to_sym) do |*attrs|
|
262
|
+
patch(path, attrs.first || Hash.new)
|
263
|
+
end
|
264
|
+
end
|
265
|
+
end # }}}
|
266
|
+
|
267
|
+
# Define custom DELETE requests
|
268
|
+
def custom_delete(*paths) # {{{
|
269
|
+
metaclass = (class << self; self; end)
|
270
|
+
paths.each do |path|
|
271
|
+
metaclass.send(:define_method, path.to_sym) do |*attrs|
|
272
|
+
delete(path, attrs.first || Hash.new)
|
273
|
+
end
|
274
|
+
end
|
275
|
+
end # }}}
|
134
276
|
end
|
135
277
|
end
|
136
278
|
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
module Her
|
2
|
+
module Model
|
3
|
+
module Introspection
|
4
|
+
# Inspect an element, returns it for introspection.
|
5
|
+
#
|
6
|
+
# @example
|
7
|
+
# class User
|
8
|
+
# include Her::Model
|
9
|
+
# end
|
10
|
+
#
|
11
|
+
# @user = User.find(1)
|
12
|
+
# p @user # => #<User(/users/1) id=1 name="Tobias Fünke">
|
13
|
+
def inspect # {{{
|
14
|
+
resource_path = self.class.collection_path
|
15
|
+
resource_path << "/#{id}" if @data.include?(:id)
|
16
|
+
"#<#{self.class}(#{resource_path}) #{@data.inject([]) { |memo, item| key, value = item; memo << "#{key}=#{attribute_for_inspect(value)}"}.join(" ")}>"
|
17
|
+
end # }}}
|
18
|
+
|
19
|
+
private
|
20
|
+
# @private
|
21
|
+
def attribute_for_inspect(value) # {{{
|
22
|
+
if value.is_a?(String) && value.length > 50
|
23
|
+
"#{value[0..50]}...".inspect
|
24
|
+
elsif value.is_a?(Date) || value.is_a?(Time)
|
25
|
+
%("#{value}")
|
26
|
+
else
|
27
|
+
value.inspect
|
28
|
+
end
|
29
|
+
end # }}}
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
data/lib/her/model/orm.rb
CHANGED
@@ -32,15 +32,23 @@ module Her
|
|
32
32
|
end # }}}
|
33
33
|
|
34
34
|
# Initialize a collection of resources with raw data from an HTTP request
|
35
|
+
#
|
36
|
+
# @param [Hash] parsed_data The raw `parsed_data` parsed from the HTTP response
|
35
37
|
def new_collection(parsed_data) # {{{
|
36
38
|
collection_data = parsed_data[:data]
|
37
39
|
Her::Model::ORM.initialize_collection(self.to_s.downcase.to_sym, collection_data)
|
38
40
|
end # }}}
|
39
41
|
|
42
|
+
# Return `true` if a resource was not saved yet
|
43
|
+
def new? # {{{
|
44
|
+
!@data.include?(:id)
|
45
|
+
end # }}}
|
46
|
+
|
40
47
|
# Fetch a specific resource based on an ID
|
41
48
|
#
|
42
49
|
# @example
|
43
|
-
# @user = User.find(1)
|
50
|
+
# @user = User.find(1)
|
51
|
+
# # Fetched via GET "/users/1"
|
44
52
|
def find(id, params={}) # {{{
|
45
53
|
request(params.merge(:_method => :get, :_path => "#{@her_collection_path}/#{id}")) do |parsed_data|
|
46
54
|
new(parsed_data[:data])
|
@@ -50,7 +58,8 @@ module Her
|
|
50
58
|
# Fetch a collection of resources
|
51
59
|
#
|
52
60
|
# @example
|
53
|
-
# @users = User.all
|
61
|
+
# @users = User.all
|
62
|
+
# # Fetched via GET "/users"
|
54
63
|
def all(params={}) # {{{
|
55
64
|
request(params.merge(:_method => :get, :_path => "#{@her_collection_path}")) do |parsed_data|
|
56
65
|
new_collection(parsed_data)
|
@@ -60,7 +69,8 @@ module Her
|
|
60
69
|
# Create a resource and return it
|
61
70
|
#
|
62
71
|
# @example
|
63
|
-
# @user = User.create({ :fullname => "Tobias Fünke" })
|
72
|
+
# @user = User.create({ :fullname => "Tobias Fünke" })
|
73
|
+
# # Called via POST "/users/1"
|
64
74
|
def create(params={}) # {{{
|
65
75
|
resource = new(params)
|
66
76
|
perform_hook(resource, :before, :create)
|
@@ -80,7 +90,8 @@ module Her
|
|
80
90
|
# Save an existing resource and return it
|
81
91
|
#
|
82
92
|
# @example
|
83
|
-
# @user = User.save_existing(1, { :fullname => "Tobias Fünke" })
|
93
|
+
# @user = User.save_existing(1, { :fullname => "Tobias Fünke" })
|
94
|
+
# # Called via PUT "/users/1"
|
84
95
|
def save_existing(id, params) # {{{
|
85
96
|
resource = new(params.merge(:id => id))
|
86
97
|
resource.save
|
@@ -89,32 +100,44 @@ module Her
|
|
89
100
|
# Save a resource
|
90
101
|
#
|
91
102
|
# @example Save a resource after fetching it
|
92
|
-
# @user = User.find(1)
|
103
|
+
# @user = User.find(1)
|
104
|
+
# # Fetched via GET "/users/1"
|
93
105
|
# @user.fullname = "Tobias Fünke"
|
94
|
-
# @user.save
|
106
|
+
# @user.save
|
107
|
+
# # Called via PUT "/users/1"
|
95
108
|
#
|
96
109
|
# @example Save a new resource by creating it
|
97
110
|
# @user = User.new({ :fullname => "Tobias Fünke" })
|
98
|
-
# @user.save
|
111
|
+
# @user.save
|
112
|
+
# # Called via POST "/users"
|
99
113
|
def save # {{{
|
100
114
|
params = @data.dup
|
115
|
+
resource = self
|
101
116
|
if @data[:id]
|
102
|
-
self.class.
|
103
|
-
|
117
|
+
self.class.class_eval do
|
118
|
+
perform_hook(resource, :before, :update)
|
119
|
+
perform_hook(resource, :before, :save)
|
120
|
+
end
|
104
121
|
self.class.request(params.merge(:_method => :put, :_path => "#{self.class.collection_path}/#{id}")) do |parsed_data|
|
105
122
|
@data = parsed_data[:data]
|
106
123
|
end
|
107
|
-
self.class.
|
108
|
-
|
124
|
+
self.class.class_eval do
|
125
|
+
perform_hook(resource, :after, :save)
|
126
|
+
perform_hook(resource, :after, :update)
|
127
|
+
end
|
109
128
|
self
|
110
129
|
else
|
111
|
-
self.class.
|
112
|
-
|
130
|
+
self.class.class_eval do
|
131
|
+
perform_hook(resource, :before, :create)
|
132
|
+
perform_hook(resource, :before, :save)
|
133
|
+
end
|
113
134
|
self.class.request(params.merge(:_method => :post, :_path => "#{self.class.collection_path}")) do |parsed_data|
|
114
135
|
@data = parsed_data[:data]
|
115
136
|
end
|
116
|
-
self.class.
|
117
|
-
|
137
|
+
self.class.class_eval do
|
138
|
+
perform_hook(resource, :after, :save)
|
139
|
+
perform_hook(resource, :after, :create)
|
140
|
+
end
|
118
141
|
end
|
119
142
|
self
|
120
143
|
end # }}}
|
@@ -122,22 +145,25 @@ module Her
|
|
122
145
|
# Destroy a resource
|
123
146
|
#
|
124
147
|
# @example
|
125
|
-
# @user = User.find(1)
|
126
|
-
# @user.destroy
|
148
|
+
# @user = User.find(1)
|
149
|
+
# @user.destroy
|
150
|
+
# # Called via DELETE "/users/1"
|
127
151
|
def destroy # {{{
|
128
152
|
params = @data.dup
|
129
|
-
|
153
|
+
resource = self
|
154
|
+
self.class.class_eval { perform_hook(resource, :before, :destroy) }
|
130
155
|
self.class.request(params.merge(:_method => :delete, :_path => "#{self.class.collection_path}/#{id}")) do |parsed_data|
|
131
156
|
@data = parsed_data[:data]
|
132
157
|
end
|
133
|
-
self.class.perform_hook(
|
158
|
+
self.class.class_eval { perform_hook(resource, :after, :destroy) }
|
134
159
|
self
|
135
160
|
end # }}}
|
136
161
|
|
137
162
|
# Destroy an existing resource
|
138
163
|
#
|
139
164
|
# @example
|
140
|
-
# User.destroy_existing(1)
|
165
|
+
# User.destroy_existing(1)
|
166
|
+
# # Called via DELETE "/users/1"
|
141
167
|
def destroy_existing(id) # {{{
|
142
168
|
params = {}
|
143
169
|
request(params.merge(:_method => :delete, :_path => "#{collection_path}/#{id}")) do |parsed_data|
|
@@ -28,13 +28,24 @@ module Her
|
|
28
28
|
data
|
29
29
|
end # }}}
|
30
30
|
|
31
|
-
# Define an *has_many* relationship
|
31
|
+
# Define an *has_many* relationship.
|
32
32
|
#
|
33
|
-
#
|
34
|
-
#
|
35
|
-
#
|
36
|
-
#
|
37
|
-
#
|
33
|
+
# @param [Symbol] name The name of the model
|
34
|
+
# @param [Hash] attrs Options (currently not used)
|
35
|
+
#
|
36
|
+
# @example
|
37
|
+
# class User
|
38
|
+
# include Her::API
|
39
|
+
# has_many :articles
|
40
|
+
# end
|
41
|
+
#
|
42
|
+
# class Article
|
43
|
+
# include Her::API
|
44
|
+
# end
|
45
|
+
#
|
46
|
+
# @user = User.find(1)
|
47
|
+
# @user.articles # => [#<Article(articles/2) id=2 title="Hello world.">]
|
48
|
+
# # Fetched via GET "/users/1/articles"
|
38
49
|
def has_many(name, attrs={}) # {{{
|
39
50
|
@her_relationships ||= {}
|
40
51
|
(@her_relationships[:has_many] ||= []) << attrs.merge(:name => name)
|
@@ -46,12 +57,24 @@ module Her
|
|
46
57
|
end
|
47
58
|
end # }}}
|
48
59
|
|
49
|
-
# Define an *has_one* relationship
|
60
|
+
# Define an *has_one* relationship.
|
61
|
+
#
|
62
|
+
# @param [Symbol] name The name of the model
|
63
|
+
# @param [Hash] attrs Options (currently not used)
|
64
|
+
#
|
65
|
+
# @example
|
66
|
+
# class User
|
67
|
+
# include Her::API
|
68
|
+
# has_one :organization
|
69
|
+
# end
|
50
70
|
#
|
51
|
-
#
|
52
|
-
#
|
53
|
-
#
|
54
|
-
#
|
71
|
+
# class Organization
|
72
|
+
# include Her::API
|
73
|
+
# end
|
74
|
+
#
|
75
|
+
# @user = User.find(1)
|
76
|
+
# @user.organization # => #<Organization(organizations/2) id=2 name="Foobar Inc.">
|
77
|
+
# # Fetched via GET "/users/1/organization"
|
55
78
|
def has_one(name, attrs={}) # {{{
|
56
79
|
@her_relationships ||= {}
|
57
80
|
(@her_relationships[:has_one] ||= []) << attrs.merge(:name => name)
|
@@ -63,12 +86,24 @@ module Her
|
|
63
86
|
end
|
64
87
|
end # }}}
|
65
88
|
|
66
|
-
# Define a *belongs_to* relationship
|
89
|
+
# Define a *belongs_to* relationship.
|
90
|
+
#
|
91
|
+
# @param [Symbol] name The name of the model
|
92
|
+
# @param [Hash] attrs Options (currently not used)
|
93
|
+
#
|
94
|
+
# @example
|
95
|
+
# class User
|
96
|
+
# include Her::API
|
97
|
+
# belongs_to :team
|
98
|
+
# end
|
99
|
+
#
|
100
|
+
# class Team
|
101
|
+
# include Her::API
|
102
|
+
# end
|
67
103
|
#
|
68
|
-
#
|
69
|
-
#
|
70
|
-
#
|
71
|
-
# make an extra HTTP request (to `/organizations/:organization_id`) if there was no "organization" key
|
104
|
+
# @user = User.find(1)
|
105
|
+
# @user.team # => #<Team(teams/2) id=2 name="Developers">
|
106
|
+
# # Fetched via GET "/teams/2"
|
72
107
|
def belongs_to(name, attrs={}) # {{{
|
73
108
|
@her_relationships ||= {}
|
74
109
|
(@her_relationships[:belongs_to] ||= []) << attrs.merge(:name => name)
|