grape-roar 0.4.0 → 0.4.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitignore +1 -0
- data/.rspec +1 -0
- data/.rubocop.yml +6 -2
- data/.rubocop_todo.yml +38 -9
- data/.travis.yml +29 -3
- data/Appraisals +9 -0
- data/CHANGELOG.md +10 -0
- data/Gemfile +6 -3
- data/README.md +218 -0
- data/Rakefile +3 -1
- data/gemfiles/with_activerecord.gemfile +22 -0
- data/gemfiles/with_mongoid.gemfile +22 -0
- data/grape-roar.gemspec +3 -0
- data/lib/grape-roar.rb +2 -0
- data/lib/grape/roar.rb +3 -0
- data/lib/grape/roar/decorator.rb +2 -0
- data/lib/grape/roar/extensions.rb +3 -0
- data/lib/grape/roar/extensions/relations.rb +23 -0
- data/lib/grape/roar/extensions/relations/adapters.rb +22 -0
- data/lib/grape/roar/extensions/relations/adapters/active_record.rb +35 -0
- data/lib/grape/roar/extensions/relations/adapters/base.rb +49 -0
- data/lib/grape/roar/extensions/relations/adapters/mongoid.rb +38 -0
- data/lib/grape/roar/extensions/relations/dsl_methods.rb +86 -0
- data/lib/grape/roar/extensions/relations/exceptions.rb +14 -0
- data/lib/grape/roar/extensions/relations/mapper.rb +89 -0
- data/lib/grape/roar/extensions/relations/validations.rb +5 -0
- data/lib/grape/roar/extensions/relations/validations/active_record.rb +67 -0
- data/lib/grape/roar/extensions/relations/validations/misc.rb +18 -0
- data/lib/grape/roar/extensions/relations/validations/mongoid.rb +88 -0
- data/lib/grape/roar/formatter.rb +2 -0
- data/lib/grape/roar/representer.rb +2 -0
- data/lib/grape/roar/version.rb +3 -1
- data/spec/config/mongoid.yml +6 -0
- data/spec/decorator_spec.rb +3 -1
- data/spec/extensions/relations/adapters/active_record_spec.rb +26 -0
- data/spec/extensions/relations/adapters/adapters_module_spec.rb +11 -0
- data/spec/extensions/relations/adapters/mongoid_spec.rb +26 -0
- data/spec/extensions/relations/dsl_methods_spec.rb +159 -0
- data/spec/extensions/relations/mapper_spec.rb +88 -0
- data/spec/extensions/relations/validations/active_record_spec.rb +46 -0
- data/spec/extensions/relations/validations/mongoid_spec.rb +88 -0
- data/spec/nested_representer_spec.rb +4 -13
- data/spec/present_with_spec.rb +3 -12
- data/spec/relations_spec.rb +76 -0
- data/spec/representer_spec.rb +3 -12
- data/spec/spec_helper.rb +15 -1
- data/spec/support/{article.rb → all/article.rb} +3 -1
- data/spec/support/{article_representer.rb → all/article_representer.rb} +2 -0
- data/spec/support/all/grape_app_context.rb +18 -0
- data/spec/support/{order.rb → all/order.rb} +3 -1
- data/spec/support/{order_representer.rb → all/order_representer.rb} +3 -1
- data/spec/support/{product.rb → all/product.rb} +2 -0
- data/spec/support/{product_representer.rb → all/product_representer.rb} +3 -1
- data/spec/support/{user.rb → all/user.rb} +2 -0
- data/spec/support/{user_representer.rb → all/user_representer.rb} +2 -0
- data/spec/support/mongoid/relational_models/cart.rb +7 -0
- data/spec/support/mongoid/relational_models/item.rb +7 -0
- data/spec/support/mongoid/relational_models/mongoid_cart_representer.rb +27 -0
- data/spec/support/mongoid/relational_models/mongoid_item_representer.rb +13 -0
- metadata +55 -11
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 275fcec452345c4903f635a7a4d3cf87ac5f662a
|
4
|
+
data.tar.gz: fa6541ccfd36c24e05460da5a5eb9f3c7b837f7e
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 773562779d81ea01fdeb3cf9b51ebc85d222f39945204424a917b07586bfa3a7b426b220ba5aa8b5c2daf16797e001c795cba7114c976aed348e98d4c929da77
|
7
|
+
data.tar.gz: 3b3f6c811fa78c9b3215fd2c100d1acbd94cd2fe53b00812837b0674284f0668e34a6c3c355adaab69085056439765d3772a50a4b5ef8510c88332599d959637
|
data/.gitignore
CHANGED
data/.rspec
CHANGED
data/.rubocop.yml
CHANGED
data/.rubocop_todo.yml
CHANGED
@@ -1,20 +1,49 @@
|
|
1
|
-
# This configuration was generated by
|
2
|
-
#
|
1
|
+
# This configuration was generated by
|
2
|
+
# `rubocop --auto-gen-config`
|
3
|
+
# on 2017-07-02 09:34:39 -0400 using RuboCop version 0.49.1.
|
3
4
|
# The point is for the user to remove these configuration records
|
4
5
|
# one by one as the offenses are removed from the code base.
|
5
6
|
# Note that changes in the inspected code, or installation of new
|
6
7
|
# versions of RuboCop, may require this file to be generated again.
|
7
8
|
|
8
|
-
# Offense count:
|
9
|
-
# Configuration parameters: AllowURI, URISchemes.
|
9
|
+
# Offense count: 7
|
10
|
+
# Configuration parameters: AllowHeredoc, AllowURI, URISchemes, IgnoreCopDirectives, IgnoredPatterns.
|
11
|
+
# URISchemes: http, https
|
10
12
|
Metrics/LineLength:
|
11
|
-
Max:
|
13
|
+
Max: 108
|
12
14
|
|
13
|
-
# Offense count:
|
15
|
+
# Offense count: 14
|
14
16
|
Style/Documentation:
|
15
|
-
|
17
|
+
Exclude:
|
18
|
+
- 'spec/**/*'
|
19
|
+
- 'test/**/*'
|
20
|
+
- 'lib/grape/roar/decorator.rb'
|
21
|
+
- 'lib/grape/roar/extensions/relations.rb'
|
22
|
+
- 'lib/grape/roar/extensions/relations/adapters.rb'
|
23
|
+
- 'lib/grape/roar/extensions/relations/adapters/active_record.rb'
|
24
|
+
- 'lib/grape/roar/extensions/relations/adapters/base.rb'
|
25
|
+
- 'lib/grape/roar/extensions/relations/adapters/mongoid.rb'
|
26
|
+
- 'lib/grape/roar/extensions/relations/dsl_methods.rb'
|
27
|
+
- 'lib/grape/roar/extensions/relations/mapper.rb'
|
28
|
+
- 'lib/grape/roar/extensions/relations/validations/active_record.rb'
|
29
|
+
- 'lib/grape/roar/extensions/relations/validations/misc.rb'
|
30
|
+
- 'lib/grape/roar/extensions/relations/validations/mongoid.rb'
|
31
|
+
- 'lib/grape/roar/formatter.rb'
|
32
|
+
- 'lib/grape/roar/representer.rb'
|
16
33
|
|
17
34
|
# Offense count: 1
|
18
|
-
# Configuration parameters:
|
35
|
+
# Configuration parameters: ExpectMatchingDefinition, Regex, IgnoreExecutableScripts, AllowedAcronyms.
|
36
|
+
# AllowedAcronyms: CLI, DSL, ACL, API, ASCII, CPU, CSS, DNS, EOF, GUID, HTML, HTTP, HTTPS, ID, IP, JSON, LHS, QPS, RAM, RHS, RPC, SLA, SMTP, SQL, SSH, TCP, TLS, TTL, UDP, UI, UID, UUID, URI, URL, UTF8, VM, XML, XMPP, XSRF, XSS
|
19
37
|
Style/FileName:
|
20
|
-
|
38
|
+
Exclude:
|
39
|
+
- 'lib/grape-roar.rb'
|
40
|
+
|
41
|
+
# Offense count: 3
|
42
|
+
# Configuration parameters: NamePrefix, NamePrefixBlacklist, NameWhitelist.
|
43
|
+
# NamePrefix: is_, has_, have_
|
44
|
+
# NamePrefixBlacklist: is_, has_, have_
|
45
|
+
# NameWhitelist: is_a?
|
46
|
+
Style/PredicateName:
|
47
|
+
Exclude:
|
48
|
+
- 'spec/**/*'
|
49
|
+
- 'lib/grape/roar/extensions/relations/validations/active_record.rb'
|
data/.travis.yml
CHANGED
@@ -5,6 +5,32 @@ language: ruby
|
|
5
5
|
cache: bundler
|
6
6
|
|
7
7
|
rvm:
|
8
|
-
-
|
9
|
-
- 2.
|
10
|
-
|
8
|
+
- 2.4.1
|
9
|
+
- 2.3.4
|
10
|
+
|
11
|
+
gemfile:
|
12
|
+
- Gemfile
|
13
|
+
- gemfiles/with_activerecord.gemfile
|
14
|
+
- gemfiles/with_mongoid.gemfile
|
15
|
+
|
16
|
+
services:
|
17
|
+
- mongodb
|
18
|
+
- pg
|
19
|
+
|
20
|
+
matrix:
|
21
|
+
include:
|
22
|
+
- env: SPEC_OPTS="--tag active_record"
|
23
|
+
gemfile: gemfiles/with_activerecord.gemfile
|
24
|
+
rvm: 2.4.1
|
25
|
+
- env: SPEC_OPTS="--tag mongoid"
|
26
|
+
gemfile: gemfiles/with_mongoid.gemfile
|
27
|
+
rvm: 2.4.1
|
28
|
+
- env: SPEC_OPTS="--tag active_record"
|
29
|
+
gemfile: gemfiles/with_activerecord.gemfile
|
30
|
+
rvm: 2.3.4
|
31
|
+
- env: SPEC_OPTS="--tag mongoid"
|
32
|
+
gemfile: gemfiles/with_mongoid.gemfile
|
33
|
+
rvm: 2.3.4
|
34
|
+
|
35
|
+
|
36
|
+
script: bundle exec rake
|
data/Appraisals
ADDED
data/CHANGELOG.md
CHANGED
@@ -1,17 +1,27 @@
|
|
1
|
+
0.4.1 (07/14/2017)
|
2
|
+
----
|
3
|
+
|
4
|
+
* [#22](https://github.com/ruby-grape/grape-roar/pull/22): Adds Grape::Roar::Extensions::Relations.
|
5
|
+
|
6
|
+
|
1
7
|
0.4.0 (02/18/2017)
|
2
8
|
------------------
|
9
|
+
|
3
10
|
* [#21](https://github.com/ruby-grape/grape-roar/pull/21): Fixes serialization issue due to [representable](https://github.com/trailblazer/representable) API change, drop support for Ruby < `2.1.0` - [@mach-kernel](https://github.com/mach-kernel).
|
4
11
|
|
12
|
+
|
5
13
|
0.3.0 (12/31/2014)
|
6
14
|
------------------
|
7
15
|
|
8
16
|
* Added support for Roar 1.0 - [@dblock](https://github.com/dblock).
|
9
17
|
|
18
|
+
|
10
19
|
0.2.0 (12/18/2014)
|
11
20
|
------------------
|
12
21
|
|
13
22
|
* [#10](https://github.com/ruby-grape/grape-roar/pull/10): Support for Roar decorator - [@sdbondi](https://github.com/sdbondi).
|
14
23
|
|
24
|
+
|
15
25
|
0.1.0 (7/17/2014)
|
16
26
|
-----------------
|
17
27
|
|
data/Gemfile
CHANGED
@@ -1,17 +1,20 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
source 'https://rubygems.org'
|
2
4
|
|
3
5
|
gemspec
|
4
6
|
|
5
7
|
group :development do
|
6
|
-
gem '
|
8
|
+
gem 'appraisal', '2.2.0'
|
7
9
|
end
|
8
10
|
|
9
11
|
group :test do
|
10
|
-
gem 'rspec', '~> 3.1'
|
11
12
|
gem 'rack-test'
|
13
|
+
gem 'rspec', '~> 3.1'
|
12
14
|
end
|
13
15
|
|
14
16
|
group :development, :test do
|
15
|
-
gem 'rubocop', '0.28.0'
|
16
17
|
gem 'nokogiri', '1.6.3.1'
|
18
|
+
gem 'rake', '~> 10.5.0'
|
19
|
+
gem 'rubocop', '0.49.1'
|
17
20
|
end
|
data/README.md
CHANGED
@@ -121,6 +121,224 @@ get 'products' do
|
|
121
121
|
end
|
122
122
|
```
|
123
123
|
|
124
|
+
### Relation Extensions
|
125
|
+
|
126
|
+
If you use either `ActiveRecord` or `Mongoid`, you can use the `Grape::Roar::Extensions::Relations` DSL to expose the relationships in between your models as a HAL response. The DSL methods used are the same regardless of what your ORM/ODM is, as long as there exists [an adapter for it](#designing-adapters).
|
127
|
+
|
128
|
+
#### Designing Representers
|
129
|
+
|
130
|
+
Arguments passed to `#relation` are forwarded to `roar`. Single member relations (e.g. `belongs_to`) are represented using `#property`, collections are represented using `#collection`; arguments provided to `#relation` will be passed through these methods (i.e. additional arguments [roar](https://github.com/trailblazer/roar) and [representable](http://trailblazer.to/gems/representable/3.0/api.html) accept).
|
131
|
+
|
132
|
+
A default base URI is constructed from a `Grape::Request` by concatenating the `#base_url` and `#script_name` properties. The resource path is extracted from the name of the relation.
|
133
|
+
|
134
|
+
Otherwise, the extensions attempt to look up the correct representer module/class for the objects (e.g. we infer the `extend` argument). You can always specify the correct representer to use on your own.
|
135
|
+
|
136
|
+
##### Example Models
|
137
|
+
|
138
|
+
```ruby
|
139
|
+
class Item < ActiveRecord::Base
|
140
|
+
belongs_to :cart
|
141
|
+
end
|
142
|
+
|
143
|
+
class Cart < ActiveRecord::Base
|
144
|
+
has_many :items
|
145
|
+
end
|
146
|
+
```
|
147
|
+
|
148
|
+
##### Example Representers
|
149
|
+
|
150
|
+
```ruby
|
151
|
+
class ItemEntity < Grape::Roar::Decorator
|
152
|
+
include Roar::JSON
|
153
|
+
include Roar::JSON::HAL
|
154
|
+
include Roar::Hypermedia
|
155
|
+
|
156
|
+
include Grape::Roar::Extensions::Relations
|
157
|
+
|
158
|
+
# Cart will be presented under the _embedded key
|
159
|
+
relation :belongs_to, :cart, embedded: true
|
160
|
+
|
161
|
+
link_self
|
162
|
+
end
|
163
|
+
|
164
|
+
class CartEntity < Grape::Roar::Decorator
|
165
|
+
include Roar::JSON
|
166
|
+
include Roar::JSON::HAL
|
167
|
+
include Roar::Hypermedia
|
168
|
+
|
169
|
+
include Grape::Roar::Extensions::Relations
|
170
|
+
|
171
|
+
# Items will be presented under the _links key
|
172
|
+
relation :has_many, :items, embedded: false
|
173
|
+
|
174
|
+
link_self
|
175
|
+
end
|
176
|
+
```
|
177
|
+
|
178
|
+
Although this example uses `Grape::Roar::Decorator`, you can also use a module as show in prior examples above. If doing so, you no longer have to mix in `Grape::Roar::Representer`.
|
179
|
+
|
180
|
+
##### Example Item
|
181
|
+
```javascript
|
182
|
+
{
|
183
|
+
"_embedded": {
|
184
|
+
"cart": {
|
185
|
+
"_links": {
|
186
|
+
"self": {
|
187
|
+
"href": "http://example.org/carts/1"
|
188
|
+
},
|
189
|
+
"items": [{
|
190
|
+
"href": "http://example.org/items/1"
|
191
|
+
}]
|
192
|
+
}
|
193
|
+
}
|
194
|
+
},
|
195
|
+
"_links": {
|
196
|
+
"self": {
|
197
|
+
"href": "http://example.org/items/1"
|
198
|
+
}
|
199
|
+
}
|
200
|
+
}
|
201
|
+
```
|
202
|
+
|
203
|
+
##### Example Cart
|
204
|
+
```javascript
|
205
|
+
{
|
206
|
+
"_links": {
|
207
|
+
"self": {
|
208
|
+
"href": "http://example.org/carts/1"
|
209
|
+
},
|
210
|
+
"items": [{
|
211
|
+
"href": "http://example.org/items/1"
|
212
|
+
}, {
|
213
|
+
"href": "http://example.org/items/2"
|
214
|
+
}, {
|
215
|
+
"href": "http://example.org/items/3"
|
216
|
+
}, {
|
217
|
+
"href": "http://example.org/items/4"
|
218
|
+
}, {
|
219
|
+
"href": "http://example.org/items/5"
|
220
|
+
}]
|
221
|
+
}
|
222
|
+
}
|
223
|
+
```
|
224
|
+
|
225
|
+
#### Errors
|
226
|
+
|
227
|
+
Should you incorrectly describe a relationship (e.g. you specify has_one but your model specifies has_many), an exception will be raised to notify you of the mismatch:
|
228
|
+
|
229
|
+
```ruby
|
230
|
+
Grape::Roar::Extensions::Relations::Exceptions::InvalidRelationError:
|
231
|
+
Expected Mongoid::Relations::Referenced::One, got Mongoid::Relations::Referenced::Many!
|
232
|
+
```
|
233
|
+
|
234
|
+
#### Change how URLs are presented
|
235
|
+
|
236
|
+
The `opts` hash below is the same one as shown in prior examples.
|
237
|
+
|
238
|
+
##### Override base URI mappings
|
239
|
+
```ruby
|
240
|
+
class BarEntity < Grape::Roar::Decorator
|
241
|
+
include Roar::JSON
|
242
|
+
include Roar::JSON::HAL
|
243
|
+
include Roar::Hypermedia
|
244
|
+
|
245
|
+
include Grape::Roar::Extensions::Relations
|
246
|
+
|
247
|
+
# This is our default implementation
|
248
|
+
map_base_url do |opts|
|
249
|
+
request = Grape::Request.new(opts[:env])
|
250
|
+
"#{request.base_url}#{request.script_name}"
|
251
|
+
end
|
252
|
+
|
253
|
+
relation :has_many, :bars, embedded: false
|
254
|
+
end
|
255
|
+
```
|
256
|
+
|
257
|
+
##### Override resource URI mappings
|
258
|
+
```ruby
|
259
|
+
class BarEntity < Grape::Roar::Decorator
|
260
|
+
include Roar::JSON
|
261
|
+
include Roar::JSON::HAL
|
262
|
+
include Roar::Hypermedia
|
263
|
+
|
264
|
+
include Grape::Roar::Extensions::Relations
|
265
|
+
|
266
|
+
# This is our default implementation
|
267
|
+
map_resource_path do |_opts, object, relation_name|
|
268
|
+
"#{relation_name}/#{object.id}"
|
269
|
+
end
|
270
|
+
|
271
|
+
relation :has_many, :bars, embedded: false
|
272
|
+
end
|
273
|
+
```
|
274
|
+
|
275
|
+
#### Designing Adapters
|
276
|
+
|
277
|
+
If you have custom domain objects, you can create an adapter to make your models compatible with the DSL methods. Below is an example of the `ActiveRecord` adapter.
|
278
|
+
|
279
|
+
##### Example: ActiveRecord Adapter
|
280
|
+
|
281
|
+
```ruby
|
282
|
+
module Extensions
|
283
|
+
module RelationalModels
|
284
|
+
module Adapter
|
285
|
+
class ActiveRecord < Base
|
286
|
+
include Validations::ActiveRecord
|
287
|
+
|
288
|
+
# We map your domain object to the correct adapter
|
289
|
+
# during runtime.
|
290
|
+
valid_for { |klass| klass < ::ActiveRecord::Base }
|
291
|
+
|
292
|
+
def collection_methods
|
293
|
+
@collection_methods ||= %i(has_many has_and_belongs_to_many)
|
294
|
+
end
|
295
|
+
|
296
|
+
def name_for_represented(represented)
|
297
|
+
klass_name = case represented
|
298
|
+
when ::ActiveRecord::Relation
|
299
|
+
represented.klass.name
|
300
|
+
else
|
301
|
+
represented.class.name
|
302
|
+
end
|
303
|
+
klass_name.demodulize.pluralize.downcase
|
304
|
+
end
|
305
|
+
|
306
|
+
def single_entity_methods
|
307
|
+
@single_entity_methods ||= %i(has_one belongs_to)
|
308
|
+
end
|
309
|
+
end
|
310
|
+
end
|
311
|
+
end
|
312
|
+
end
|
313
|
+
```
|
314
|
+
|
315
|
+
##### Validations
|
316
|
+
|
317
|
+
Errors are handled by creating methods corresponding to those in `collection_methods` and `single_entity_methods`. For example, this is the validator for `belongs_to`:
|
318
|
+
|
319
|
+
```ruby
|
320
|
+
module ActiveRecord
|
321
|
+
include Validations::Misc
|
322
|
+
|
323
|
+
def belongs_to_valid?(relation)
|
324
|
+
relation = klass.reflections[relation]
|
325
|
+
|
326
|
+
return true if relation.is_a?(
|
327
|
+
::ActiveRecord::Reflection::BelongsToReflection
|
328
|
+
)
|
329
|
+
|
330
|
+
# Provided by Validations::Misc
|
331
|
+
invalid_relation(
|
332
|
+
::ActiveRecord::Reflection::BelongsToReflection,
|
333
|
+
relation.class
|
334
|
+
)
|
335
|
+
end
|
336
|
+
end
|
337
|
+
```
|
338
|
+
|
339
|
+
After writing your validation methods, just mix them into your adapter. You can choose to not write validation methods; they are only invoked if your adapter responds to them.
|
340
|
+
|
341
|
+
|
124
342
|
Contributing
|
125
343
|
------------
|
126
344
|
|
data/Rakefile
CHANGED
@@ -0,0 +1,22 @@
|
|
1
|
+
# This file was generated by Appraisal
|
2
|
+
|
3
|
+
source "https://rubygems.org"
|
4
|
+
|
5
|
+
gem "activerecord", ">= 4.0.0", require: "active_record"
|
6
|
+
|
7
|
+
group :development do
|
8
|
+
gem "appraisal", "2.2.0"
|
9
|
+
end
|
10
|
+
|
11
|
+
group :test do
|
12
|
+
gem "rack-test"
|
13
|
+
gem "rspec", "~> 3.1"
|
14
|
+
end
|
15
|
+
|
16
|
+
group :development, :test do
|
17
|
+
gem "nokogiri", "1.6.3.1"
|
18
|
+
gem "rake", "~> 10.5.0"
|
19
|
+
gem "rubocop", "0.49.1"
|
20
|
+
end
|
21
|
+
|
22
|
+
gemspec path: "../"
|