hal_api-rails 0.2.9 → 0.3.0
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.
- checksums.yaml +4 -4
- data/README.md +45 -1
- data/lib/hal_api/controller/actions.rb +3 -3
- data/lib/hal_api/controller/exceptions.rb +6 -7
- data/lib/hal_api/controller/resources.rb +1 -4
- data/lib/hal_api/paged_collection.rb +6 -0
- data/lib/hal_api/paged_collection_representer.rb +63 -0
- data/lib/hal_api/rails/version.rb +1 -1
- data/lib/hal_api/represented_model.rb +4 -0
- data/lib/hal_api/representer/embeds.rb +14 -6
- metadata +4 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: d5fd9d4857d9ce82ac91cae49c2b239e1ed4ebac
|
4
|
+
data.tar.gz: 9f19281381dbdfc58f76b942421c36a7531aacac
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: c8f2041c5eceda12f490af0169b5058ea32b9f782fddeb0c1bbf15ad19973fe2a08dc38f90956accf7557160393a24709e20744ecf53dd4b7fb18d9aee5d60d7
|
7
|
+
data.tar.gz: c6c89868387c3416b6ea2ca71114e46a13b33f9a20552a47fab404e31dac0bec96f8af99c97b0f02f4e59d1a072829e0541aa3acd17e0604ccd403a5e8124524
|
data/README.md
CHANGED
@@ -24,7 +24,51 @@ Or install it yourself as:
|
|
24
24
|
|
25
25
|
## Usage
|
26
26
|
|
27
|
-
|
27
|
+
This gem provides a number of additions to the `roar` gem HAL support.
|
28
|
+
|
29
|
+
There are several parts of it that need to be used in your apps:
|
30
|
+
|
31
|
+
1) Add to your API controllers:
|
32
|
+
|
33
|
+
```ruby
|
34
|
+
require 'hal_api/rails'
|
35
|
+
|
36
|
+
class Api::BaseController < ApplicationController
|
37
|
+
include HalApi::Controller
|
38
|
+
...
|
39
|
+
end
|
40
|
+
```
|
41
|
+
|
42
|
+
2) Add to your `ActiveRecord` models used in your API (perhaps in a base model class):
|
43
|
+
```ruby
|
44
|
+
class BaseModel < ActiveRecord::Base
|
45
|
+
self.abstract_class = true
|
46
|
+
|
47
|
+
include RepresentedModel
|
48
|
+
end
|
49
|
+
```
|
50
|
+
|
51
|
+
3) Use the base representer, define your own CURIEs:
|
52
|
+
```ruby
|
53
|
+
class Api::BaseRepresenter < HalApi::Representer
|
54
|
+
curies(:prx) do
|
55
|
+
[{
|
56
|
+
name: :foo,
|
57
|
+
href: "http://foo.bar/relation/{rel}",
|
58
|
+
templated: true
|
59
|
+
}]
|
60
|
+
end
|
61
|
+
|
62
|
+
def index_url_params
|
63
|
+
'{?page,per,zoom}'
|
64
|
+
end
|
65
|
+
|
66
|
+
def show_url_params
|
67
|
+
'{?zoom}'
|
68
|
+
end
|
69
|
+
end
|
70
|
+
```
|
71
|
+
|
28
72
|
|
29
73
|
## Development
|
30
74
|
|
@@ -50,7 +50,7 @@ module HalApi::Controller::Actions
|
|
50
50
|
def index_options
|
51
51
|
valid_params_for_action(:index).tap do |options|
|
52
52
|
options[:_keys] = options.keys
|
53
|
-
options[:represent_with] =
|
53
|
+
options[:represent_with] = HalApi::PagedCollection.representer
|
54
54
|
end
|
55
55
|
end
|
56
56
|
|
@@ -77,8 +77,8 @@ module HalApi::Controller::Actions
|
|
77
77
|
|
78
78
|
def zoom_param
|
79
79
|
@zoom_param ||= begin
|
80
|
-
if (zp = params[:zoom]) && zp.
|
81
|
-
zp.split(',').map(&:strip).compact.sort
|
80
|
+
if (zp = params[:zoom]) && !zp.nil?
|
81
|
+
Array(zp.split(',')).map(&:strip).compact.sort
|
82
82
|
end
|
83
83
|
end
|
84
84
|
end
|
@@ -10,13 +10,12 @@ module HalApi::Controller::Exceptions
|
|
10
10
|
wrapper = ::ActionDispatch::ExceptionWrapper.new(env, exception)
|
11
11
|
log_error(env, wrapper)
|
12
12
|
|
13
|
-
error =
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
end
|
13
|
+
error = exception
|
14
|
+
if !error.is_a?(HalApi::Errors::ApiError)
|
15
|
+
error = HalApi::Errors::ApiError.new(error.message).tap do |e|
|
16
|
+
e.set_backtrace(error.backtrace)
|
17
|
+
end
|
18
|
+
end
|
20
19
|
|
21
20
|
respond_with(
|
22
21
|
error,
|
@@ -82,15 +82,12 @@ module HalApi::Controller::Resources
|
|
82
82
|
# Decorations
|
83
83
|
|
84
84
|
def decorate_query(res)
|
85
|
-
filtered(paged(sorted(scoped(res))))
|
85
|
+
filtered(paged(sorted(scoped(included(res)))))
|
86
86
|
end
|
87
87
|
|
88
88
|
def filtered(arel)
|
89
89
|
keys = self.class.resources_params || []
|
90
90
|
where_hash = params.slice(*keys)
|
91
|
-
if where_hash.key?('story_id')
|
92
|
-
where_hash['piece_id'] = where_hash.delete('story_id')
|
93
|
-
end
|
94
91
|
where_hash = where_hash.permit(where_hash.keys)
|
95
92
|
arel = arel.where(where_hash) unless where_hash.blank?
|
96
93
|
arel
|
@@ -0,0 +1,63 @@
|
|
1
|
+
require 'hal_api/representer'
|
2
|
+
|
3
|
+
class HalApi::PagedCollectionRepresenter < HalApi::Representer
|
4
|
+
property :count
|
5
|
+
property :total
|
6
|
+
|
7
|
+
embeds :items, decorator: lambda{|*| item_decorator }, class: lambda{|*| item_class }, zoom: :always
|
8
|
+
|
9
|
+
link :prev do
|
10
|
+
href_url_helper(params.merge(page: represented.prev_page)) unless represented.first_page?
|
11
|
+
end
|
12
|
+
|
13
|
+
link :next do
|
14
|
+
href_url_helper(params.merge(page: represented.next_page)) unless represented.last_page?
|
15
|
+
end
|
16
|
+
|
17
|
+
link :first do
|
18
|
+
href_url_helper(params.merge(page: nil)) if represented.total_pages > 1
|
19
|
+
end
|
20
|
+
|
21
|
+
link :last do
|
22
|
+
href_url_helper(params.merge(page: represented.total_pages)) if represented.total_pages > 1
|
23
|
+
end
|
24
|
+
|
25
|
+
def params
|
26
|
+
represented.params
|
27
|
+
end
|
28
|
+
|
29
|
+
def self_url(represented)
|
30
|
+
href_url_helper(represented.params)
|
31
|
+
end
|
32
|
+
|
33
|
+
def profile_url(represented)
|
34
|
+
model_uri(:collection, represented.item_class)
|
35
|
+
end
|
36
|
+
|
37
|
+
# refactor to use single property, :url, that can be a method name, a string, or a lambda
|
38
|
+
# if it is a method name, execute against self - the representer - which has local url helpers methods
|
39
|
+
# if it is a sym/string, but self does not respond to it, then just use that string
|
40
|
+
# if it is a lambda, execute in the context against the represented.parent (if there is one) or represented
|
41
|
+
def href_url_helper(options={})
|
42
|
+
if represented_url.nil?
|
43
|
+
result = url_for(options.merge(only_path: true)) rescue nil
|
44
|
+
if represented.parent
|
45
|
+
result ||= polymorphic_path([:api, represented.parent, represented.item_class], options) rescue nil
|
46
|
+
end
|
47
|
+
result ||= polymorphic_path([:api, represented.item_class], options) rescue nil
|
48
|
+
return result
|
49
|
+
end
|
50
|
+
|
51
|
+
if represented_url.respond_to?(:call)
|
52
|
+
self.instance_exec(options, &represented_url)
|
53
|
+
elsif self.respond_to?(represented_url)
|
54
|
+
self.send(represented_url, options)
|
55
|
+
else
|
56
|
+
represented_url.to_s
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
def represented_url
|
61
|
+
@represented_url ||= represented.try(:url)
|
62
|
+
end
|
63
|
+
end
|
@@ -1,4 +1,3 @@
|
|
1
|
-
# encoding: utf-8
|
2
1
|
require 'active_support/concern'
|
3
2
|
require 'hal_api/paged_collection'
|
4
3
|
|
@@ -10,15 +9,24 @@ module HalApi::Representer::Embeds
|
|
10
9
|
Representable::Mapper.send(:include, Resources) if !Representable::Mapper.include?(Resources)
|
11
10
|
end
|
12
11
|
|
12
|
+
def normalize_options!(options)
|
13
|
+
propagated_options, private_options = super(options)
|
14
|
+
|
15
|
+
# we want this to propogate, and be available for `skip_property?`, so don't delete
|
16
|
+
private_options[:zoom] = options[:zoom] if options.key?(:zoom)
|
17
|
+
|
18
|
+
[propagated_options, private_options]
|
19
|
+
end
|
20
|
+
|
13
21
|
module Resources
|
14
22
|
|
15
|
-
def skip_property?(binding,
|
16
|
-
super(binding,
|
23
|
+
def skip_property?(binding, private_options)
|
24
|
+
super(binding, private_options) || suppress_embed?(binding, private_options)
|
17
25
|
end
|
18
26
|
|
19
27
|
# embed if zoomed
|
20
28
|
def suppress_embed?(binding, options)
|
21
|
-
name
|
29
|
+
name = binding[:as].evaluate(self).to_s || binding.name
|
22
30
|
embedded = !!binding[:embedded]
|
23
31
|
|
24
32
|
# not embedded, return false - nothing to suppress
|
@@ -28,7 +36,7 @@ module HalApi::Representer::Embeds
|
|
28
36
|
!embed_zoomed?(name, binding[:zoom], options[:zoom])
|
29
37
|
end
|
30
38
|
|
31
|
-
def embed_zoomed?(name, zoom_def=nil, zoom_param=nil)
|
39
|
+
def embed_zoomed?(name, zoom_def = nil, zoom_param = nil)
|
32
40
|
# if the embed in the representer definition has `zoom: :always` defined
|
33
41
|
# always embed it, even if it is in another embed
|
34
42
|
# (this is really meant for collections where embedded items must be included)
|
@@ -70,7 +78,7 @@ module HalApi::Representer::Embeds
|
|
70
78
|
per = getter_per == :all ? send(name).count : getter_per
|
71
79
|
HalApi::PagedCollection.new(send(name).page(1).per(per), nil, opts.merge(parent: self))
|
72
80
|
end
|
73
|
-
options[:decorator] =
|
81
|
+
options[:decorator] = HalApi::PagedCollection.representer
|
74
82
|
end
|
75
83
|
|
76
84
|
property(name, options)
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: hal_api-rails
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.3.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Chris Rhoden
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: exe
|
11
11
|
cert_chain: []
|
12
|
-
date:
|
12
|
+
date: 2017-10-27 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: activemodel
|
@@ -219,6 +219,7 @@ files:
|
|
219
219
|
- lib/hal_api/controller/resources.rb
|
220
220
|
- lib/hal_api/errors.rb
|
221
221
|
- lib/hal_api/paged_collection.rb
|
222
|
+
- lib/hal_api/paged_collection_representer.rb
|
222
223
|
- lib/hal_api/rails.rb
|
223
224
|
- lib/hal_api/rails/version.rb
|
224
225
|
- lib/hal_api/represented_model.rb
|
@@ -250,7 +251,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
250
251
|
version: '0'
|
251
252
|
requirements: []
|
252
253
|
rubyforge_project:
|
253
|
-
rubygems_version: 2.
|
254
|
+
rubygems_version: 2.4.5.2
|
254
255
|
signing_key:
|
255
256
|
specification_version: 4
|
256
257
|
summary: JSON HAL APIs on Rails in the style of PRX
|