hal_api-rails 0.6.0 → 1.1.2

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 4f8ad6ad0044a8438881c35775259d46cce7448d
4
- data.tar.gz: c4dd5e6a42a4cca9d744e7050a91dc6d06e335f9
3
+ metadata.gz: fee32a82297c2cc6ec8a4c5dd9c3ad19c78ed8b1
4
+ data.tar.gz: c6e4ce2430011f64b1e80beef0d5d3da9bb20d30
5
5
  SHA512:
6
- metadata.gz: ae0cf7fc44f171df5972c660d732cbd837f89216e001ef76f8b9aa97a0cc25b8581e975a90efdfdee7401cc7e9ae3ad947442239119828a374806ac023b3ce3a
7
- data.tar.gz: 9d8eb8563e870a584b7eb69696a8d205cbb03b5b6ea68b33c64913ced078a158cfc21a37fb62a0c349b2a66c4cb026a8e3448080139f27ec88bc939ebd6e0d12
6
+ metadata.gz: d5403262dc8862444f9156f96bab7ccb9140ee37f7cb96e3083ca47453c35024636894160fd8ce6e46f983d8b45820f9641c49f93940f9f95c2541526786f737
7
+ data.tar.gz: 59ca15c8aee5039fd78639b0f494dfd5f3c889f6b6b145528f57b4e0d25844c445c4c54baa8cc36f3be656fe6d25ea304447b6873fda4581e67dbdf945310a2b
@@ -1,3 +1,3 @@
1
1
  language: ruby
2
2
  rvm:
3
- - 2.2.2
3
+ - 2.4.9
@@ -23,13 +23,13 @@ Gem::Specification.new do |spec|
23
23
  spec.add_dependency "actionpack", ">= 3.0.0"
24
24
  spec.add_dependency "rack-test"
25
25
  spec.add_dependency "activesupport", ">= 3.0.0"
26
- spec.add_dependency "responders", "~> 2.0"
27
- spec.add_dependency "roar-rails", "~> 1.0.2"
26
+ spec.add_dependency "responders", "~> 3.0"
27
+ spec.add_dependency "roar-rails", "~> 1.1.0"
28
28
  spec.add_dependency "multi_json"
29
29
 
30
30
  spec.add_development_dependency "bundler"
31
31
  spec.add_development_dependency "rake", "~> 10.0"
32
- spec.add_development_dependency "rails", "~> 4.2.1"
32
+ spec.add_development_dependency "rails", "~> 5.2.4"
33
33
  spec.add_development_dependency "pry-byebug"
34
34
  spec.add_development_dependency "minitest"
35
35
  spec.add_development_dependency "kaminari"
@@ -71,7 +71,9 @@ module HalApi::Controller::Actions
71
71
 
72
72
  def valid_params_for_action(action)
73
73
  (params.permit(*self.class.valid_params_list(action)) || {}).tap do |p|
74
- p[:zoom] = zoom_param if zoom_param
74
+ if zoom_param
75
+ p[:user_options] = (p[:user_options] || {}).merge(zoom: zoom_param)
76
+ end
75
77
  end.
76
78
  to_h
77
79
  end
@@ -11,10 +11,10 @@ module HalApi::Controller::Exceptions
11
11
  when 5
12
12
  ::ActionDispatch::ExceptionWrapper.new(ActiveSupport::BacktraceCleaner.new, exception)
13
13
  else
14
- ::ActionDispatch::ExceptionWrapper.new(env, exception)
14
+ ::ActionDispatch::ExceptionWrapper.new(request.env, exception)
15
15
  end
16
16
 
17
- log_error(env, wrapper)
17
+ log_error(request.env, wrapper)
18
18
 
19
19
  error = exception
20
20
  if !error.is_a?(HalApi::Errors::ApiError)
@@ -53,6 +53,24 @@ module HalApi::Controller::Filtering
53
53
  @filters ||= parse_filters_param
54
54
  end
55
55
 
56
+ def filter_facets
57
+ end
58
+
59
+ def index_collection
60
+ collection = defined?(super) ? super : HalApi::PagedCollection.new([])
61
+
62
+ # add facets if defined, removing filters/facets with counts of 0
63
+ non_zero_facets = (filter_facets || {}).with_indifferent_access.tap do |hash|
64
+ hash.each do |filter_key, facets|
65
+ hash[filter_key] = facets.try(:select) { |f| f.try(:[], :count) > 0 }
66
+ hash.delete(filter_key) if hash[filter_key].blank?
67
+ end
68
+ end
69
+ collection.facets = non_zero_facets unless non_zero_facets.blank?
70
+
71
+ collection
72
+ end
73
+
56
74
  private
57
75
 
58
76
  def parse_filters_param
@@ -75,6 +75,10 @@ module HalApi::Controller::Resources
75
75
  self.class.resource_class.where(nil)
76
76
  end
77
77
 
78
+ def resources_query
79
+ filtered(scoped(resources_base))
80
+ end
81
+
78
82
  def find_base
79
83
  filtered(scoped(included(resources_base)))
80
84
  end
@@ -6,7 +6,7 @@ class HalApi::PagedCollection
6
6
  extend ActiveModel::Naming
7
7
  extend Forwardable
8
8
 
9
- attr_accessor :items, :request, :options
9
+ attr_accessor :items, :request, :options, :facets
10
10
 
11
11
  def_delegators :items, :total_count, :prev_page, :next_page, :total_pages, :first_page?, :last_page?
12
12
  alias_method :total, :total_count
@@ -1,5 +1,5 @@
1
1
  module HalApi
2
2
  module Rails
3
- VERSION = "0.6.0"
3
+ VERSION = '1.1.2'
4
4
  end
5
5
  end
@@ -21,5 +21,6 @@ class HalApi::Representer < Roar::Decorator
21
21
  include HalApi::Representer::Caches
22
22
  include HalApi::Representer::LinkSerialize
23
23
  self_link
24
+ vary_link
24
25
  profile_link
25
26
  end
@@ -7,6 +7,7 @@ module HalApi::Representer::CollectionPaging
7
7
  class_eval do
8
8
  property :count
9
9
  property :total
10
+ property :facets
10
11
 
11
12
  embeds :items, decorator: lambda{|*| item_decorator }, class: lambda{|*| item_class }, zoom: :always
12
13
 
@@ -36,6 +37,14 @@ module HalApi::Representer::CollectionPaging
36
37
  href_url_helper(represented.params)
37
38
  end
38
39
 
40
+ def vary_url(represented)
41
+ href_url_helper(represented.params.except(*vary_params))
42
+ end
43
+
44
+ def vary_params
45
+ %w(page per zoom filters sorts)
46
+ end
47
+
39
48
  def profile_url(represented)
40
49
  model_uri(:collection, represented.item_class)
41
50
  end
@@ -46,6 +55,7 @@ module HalApi::Representer::CollectionPaging
46
55
  # if it is a lambda, execute in the context against the represented.parent (if there is one) or represented
47
56
  def href_url_helper(options={})
48
57
  if represented_url.nil?
58
+ options = options.except(:format)
49
59
  result = url_for(options.merge(only_path: true)) rescue nil
50
60
  if represented.parent
51
61
  result ||= polymorphic_path([:api, represented.parent, represented.item_class], options) rescue nil
@@ -1,39 +1,47 @@
1
1
  require 'active_support/concern'
2
2
  require 'hal_api/paged_collection'
3
+ require "representable/pipeline_factories"
3
4
 
4
5
  # expects underlying model to have filename, class, and id attributes
5
6
  module HalApi::Representer::Embeds
6
7
  extend ActiveSupport::Concern
7
8
 
8
9
  included do
9
- Representable::Mapper.send(:include, Resources) if !Representable::Mapper.include?(Resources)
10
+ Representable::Binding.send(:include, HalApiRailsRenderPipeline) if !Representable::Binding.include?(HalApiRailsRenderPipeline)
10
11
  end
11
12
 
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
-
21
- module Resources
13
+ module HalApiRailsRenderPipeline
22
14
 
23
15
  def skip_property?(binding, private_options)
24
16
  super(binding, private_options) || suppress_embed?(binding, private_options)
25
17
  end
26
18
 
19
+ def render_functions
20
+ funcs = super
21
+ f = ->(input, options) do
22
+ if suppress_embed?(input, options)
23
+ return Representable::Pipeline::Stop
24
+ end
25
+ end
26
+ [f] + funcs
27
+ end
28
+
27
29
  # embed if zoomed
28
- def suppress_embed?(binding, options)
29
- name = binding[:as].evaluate(self).to_s || binding.name
30
- embedded = !!binding[:embedded]
30
+ def suppress_embed?(input, options)
31
+ binding = options[:binding]
32
+
33
+ # guard against non-hal representers
34
+ return false unless binding[:as].present?
35
+
36
+ name = binding.evaluate_option(:as, input, options)
37
+
38
+ embedded = binding[:embedded]
31
39
 
32
- # not embedded, return false - nothing to suppress
33
40
  return false if !embedded
34
41
 
35
- # check if it should be zoomed, suppress if not
36
- !embed_zoomed?(name, binding[:zoom], options[:zoom])
42
+ ## check if it should be zoomed, suppress if not
43
+ user_zooms = options[:options].try(:[], :user_options).try(:[], :zoom)
44
+ !embed_zoomed?(name, binding[:zoom], user_zooms)
37
45
  end
38
46
 
39
47
  def embed_zoomed?(name, zoom_def = nil, zoom_param = nil)
@@ -77,7 +85,9 @@ module HalApi::Representer::Embeds
77
85
  options[:getter] ||= ->(*) do
78
86
  cnt = send(name).count
79
87
  per = getter_per == :all ? cnt : getter_per
80
- if cnt <= per
88
+ if cnt == 0
89
+ items = send(name).page(1).per(Kaminari.config.default_per_page)
90
+ elsif cnt <= per
81
91
  items = Kaminari.paginate_array(send(name)).page(1).per(per)
82
92
  else
83
93
  items = send(name).page(1).per(per)
@@ -15,8 +15,9 @@ module HalApi::Representer::LinkSerialize
15
15
  if options.is_a?(Hash) && (options.delete(:writeable) || options[:reader])
16
16
  name = options[:rel].to_s.split(':').last.split('/').last
17
17
  pname = "set_#{name}_uri"
18
- reader = options.delete(:reader) || ->(doc, _args) do
18
+ reader = options.delete(:reader) || ->(represented:, doc:, **) do
19
19
  try("#{name}_id=", id_from_url(doc[pname])) if doc[pname]
20
+ Representable::Pipeline::Stop
20
21
  end
21
22
 
22
23
  property(pname, readable: false, reader: reader)
@@ -21,6 +21,15 @@ module HalApi::Representer::UriMethods
21
21
  end
22
22
  end
23
23
 
24
+ def vary_link
25
+ link(:vary) do
26
+ {
27
+ href: vary_url(represented) + vary_query_params,
28
+ templated: true,
29
+ } if vary_url(represented).present? && vary_params.present?
30
+ end
31
+ end
32
+
24
33
  def profile_link
25
34
  link(:profile) { profile_url(represented) }
26
35
  end
@@ -46,6 +55,18 @@ module HalApi::Representer::UriMethods
46
55
  polymorphic_path([:api, rep])
47
56
  end
48
57
 
58
+ def vary_url(represented)
59
+ self_url(represented)
60
+ end
61
+
62
+ def vary_params
63
+ []
64
+ end
65
+
66
+ def vary_query_params
67
+ "{?#{vary_params.join(',')}}"
68
+ end
69
+
49
70
  def becomes_represented_class(rep)
50
71
  return rep unless rep.respond_to?(:becomes)
51
72
  klass = rep.try(:item_class) || rep.class.try(:base_class)
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.6.0
4
+ version: 1.1.2
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: 2019-08-16 00:00:00.000000000 Z
12
+ date: 2020-06-09 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: activemodel
@@ -73,28 +73,28 @@ dependencies:
73
73
  requirements:
74
74
  - - "~>"
75
75
  - !ruby/object:Gem::Version
76
- version: '2.0'
76
+ version: '3.0'
77
77
  type: :runtime
78
78
  prerelease: false
79
79
  version_requirements: !ruby/object:Gem::Requirement
80
80
  requirements:
81
81
  - - "~>"
82
82
  - !ruby/object:Gem::Version
83
- version: '2.0'
83
+ version: '3.0'
84
84
  - !ruby/object:Gem::Dependency
85
85
  name: roar-rails
86
86
  requirement: !ruby/object:Gem::Requirement
87
87
  requirements:
88
88
  - - "~>"
89
89
  - !ruby/object:Gem::Version
90
- version: 1.0.2
90
+ version: 1.1.0
91
91
  type: :runtime
92
92
  prerelease: false
93
93
  version_requirements: !ruby/object:Gem::Requirement
94
94
  requirements:
95
95
  - - "~>"
96
96
  - !ruby/object:Gem::Version
97
- version: 1.0.2
97
+ version: 1.1.0
98
98
  - !ruby/object:Gem::Dependency
99
99
  name: multi_json
100
100
  requirement: !ruby/object:Gem::Requirement
@@ -143,14 +143,14 @@ dependencies:
143
143
  requirements:
144
144
  - - "~>"
145
145
  - !ruby/object:Gem::Version
146
- version: 4.2.1
146
+ version: 5.2.4
147
147
  type: :development
148
148
  prerelease: false
149
149
  version_requirements: !ruby/object:Gem::Requirement
150
150
  requirements:
151
151
  - - "~>"
152
152
  - !ruby/object:Gem::Version
153
- version: 4.2.1
153
+ version: 5.2.4
154
154
  - !ruby/object:Gem::Dependency
155
155
  name: pry-byebug
156
156
  requirement: !ruby/object:Gem::Requirement
@@ -255,7 +255,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
255
255
  version: '0'
256
256
  requirements: []
257
257
  rubyforge_project:
258
- rubygems_version: 2.5.2.3
258
+ rubygems_version: 2.6.14.4
259
259
  signing_key:
260
260
  specification_version: 4
261
261
  summary: JSON HAL APIs on Rails in the style of PRX