graphiti 1.2.33 → 1.2.34

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
  SHA256:
3
- metadata.gz: 1fd3e0460824b4c80d8bf5e1cb798b94a297bdb39ab077cb655b9fe085779bd2
4
- data.tar.gz: 3ae7e9ef0209b9bd0c823cd323bc3f066f2116a807ad66f714d3c63205351649
3
+ metadata.gz: 3c877600c2b854433fd506185d43e64fce4e9f6c3a7cd37846fe60f724acd8f4
4
+ data.tar.gz: d1e30c54a384eda5a2b2f5224da346808c47a54aadf57610b1ccd7339d780234
5
5
  SHA512:
6
- metadata.gz: 8e294afd7a47b32fbc4aa0ba695aafbeb43f42bf4c32d6f05eb2a182bca4e6b0ab0bdd68ad8a54dda8b7cee24636b0097b52629895adb758c3d2b148e3dda7c7
7
- data.tar.gz: 8454b4433f15af9464d9b708dad9cb16dff9fb368085b1297aa733f5a8dcb56a0621f4cfdbb63bfe06931d24bd17378c42655059b68a763025a33a5903605c34
6
+ metadata.gz: 68b7f4d1d96c67d6d28976ed9ba8071e5d8376835cfbc61a2744e9792467e93dee4b4338fbeb4d7d3492f8a03aa935657726c0b66d0af69f4d061b5cdc29f1b7
7
+ data.tar.gz: 62a8b811497bfc1ffc06e4bb85f86ac573be0f7eb7b0a41cf915f6c0ee9fdf85460612c17708956c89472a6b7dad0d43c0087212db2779e0320211d9f99a93c9
data/CHANGELOG.md CHANGED
@@ -1,6 +1,7 @@
1
1
  ## Unreleased
2
2
 
3
3
  Features:
4
+ - [329](https://github.com/graphiti-api/graphiti/pull/329) Propagate `extra_fields` to related resource links.
4
5
  - [242](https://github.com/graphiti-api/graphiti/pull/242) Bump `jsonapi-renderer` to `~0.2.2` now that (https://github.com/jsonapi-rb/jsonapi-renderer/pull/36) is fixed.
5
6
  - [158](https://github.com/graphiti-api/graphiti/pull/158) Filters options `allow_nil: true`
6
7
  Option can be set at the resource level `Resource.filters_accept_nil_by_default = true`.
data/lib/graphiti.rb CHANGED
@@ -142,6 +142,7 @@ require "graphiti/scoping/sort"
142
142
  require "graphiti/scoping/paginate"
143
143
  require "graphiti/scoping/extra_attributes"
144
144
  require "graphiti/scoping/filterable"
145
+ require "graphiti/scoping/filter_group_validator"
145
146
  require "graphiti/scoping/default_filter"
146
147
  require "graphiti/scoping/filter"
147
148
  require "graphiti/stats/dsl"
@@ -14,13 +14,12 @@ module Graphiti
14
14
  end
15
15
 
16
16
  class NullRelation
17
- extend ActiveModel::Naming
18
17
  attr_accessor :id, :errors, :pointer
19
18
 
20
19
  def initialize(id, pointer)
21
20
  @id = id
22
21
  @pointer = pointer
23
- @errors = ActiveModel::Errors.new(self)
22
+ @errors = Graphiti::Util::SimpleErrors.new(self)
24
23
  end
25
24
 
26
25
  def self.human_attribute_name(attr, options = {})
@@ -817,5 +816,34 @@ module Graphiti
817
816
 
818
817
  class ConflictRequest < InvalidRequest
819
818
  end
819
+
820
+ class FilterGroupInvalidRequirement < Base
821
+ def initialize(resource, valid_required_values)
822
+ @resource = resource
823
+ @valid_required_values = valid_required_values
824
+ end
825
+
826
+ def message
827
+ <<-MSG.gsub(/\s+/, " ").strip
828
+ The filter group required: value on resource #{@resource.class} must be one of the following:
829
+ #{@valid_required_values.join(", ")}
830
+ MSG
831
+ end
832
+ end
833
+
834
+ class FilterGroupMissingRequiredFilters < Base
835
+ def initialize(resource, filter_names, required)
836
+ @resource = resource
837
+ @filter_names = filter_names
838
+ @required_label = required == :all ? "All" : "One"
839
+ end
840
+
841
+ def message
842
+ <<-MSG.gsub(/\s+/, " ").strip
843
+ #{@required_label} of the following filters must be provided on resource #{@resource.type}:
844
+ #{@filter_names.join(", ")}
845
+ MSG
846
+ end
847
+ end
820
848
  end
821
849
  end
@@ -46,9 +46,9 @@ module Graphiti
46
46
  next false unless instance_exec(&options[:if])
47
47
  end
48
48
 
49
- @extra_fields &&
50
- @extra_fields[@_type] &&
51
- @extra_fields[@_type].include?(name)
49
+ next false unless @extra_fields
50
+
51
+ @extra_fields[@_type]&.include?(name) || @extra_fields[@resource&.type]&.include?(name)
52
52
  }
53
53
 
54
54
  attribute name, if: allow_field, &blk
@@ -199,6 +199,7 @@ module Graphiti
199
199
  @config ||=
200
200
  {
201
201
  filters: {},
202
+ grouped_filters: {},
202
203
  default_filters: {},
203
204
  stats: {},
204
205
  sort_all: nil,
@@ -235,6 +236,10 @@ module Graphiti
235
236
  config[:filters]
236
237
  end
237
238
 
239
+ def grouped_filters
240
+ config[:grouped_filters]
241
+ end
242
+
238
243
  def sorts
239
244
  config[:sorts]
240
245
  end
@@ -273,6 +278,10 @@ module Graphiti
273
278
  self.class.filters
274
279
  end
275
280
 
281
+ def grouped_filters
282
+ self.class.grouped_filters
283
+ end
284
+
276
285
  def sort_all
277
286
  self.class.sort_all
278
287
  end
@@ -44,6 +44,17 @@ module Graphiti
44
44
  end
45
45
  end
46
46
 
47
+ def filter_group(filter_names, *args)
48
+ opts = args.extract_options!
49
+
50
+ Scoping::FilterGroupValidator.raise_unless_filter_group_requirement_valid!(self, opts[:required])
51
+
52
+ config[:grouped_filters] = {
53
+ names: filter_names,
54
+ required: opts[:required]
55
+ }
56
+ end
57
+
47
58
  def sort_all(&blk)
48
59
  if block_given?
49
60
  config[:_sort_all] = blk
@@ -3,6 +3,11 @@ module Graphiti
3
3
  include Scoping::Filterable
4
4
 
5
5
  def apply
6
+ Graphiti::Scoping::FilterGroupValidator.new(
7
+ resource,
8
+ query_hash
9
+ ).raise_unless_filter_group_requirements_met!
10
+
6
11
  if missing_required_filters.any? && !@opts[:bypass_required_filters]
7
12
  raise Errors::RequiredFilter.new(resource, missing_required_filters)
8
13
  end
@@ -0,0 +1,78 @@
1
+ module Graphiti
2
+ class Scoping::FilterGroupValidator
3
+ VALID_REQUIRED_VALUES = %i[all any]
4
+
5
+ def self.raise_unless_filter_group_requirement_valid!(resource, requirement)
6
+ unless VALID_REQUIRED_VALUES.include?(requirement)
7
+ raise Errors::FilterGroupInvalidRequirement.new(
8
+ resource,
9
+ VALID_REQUIRED_VALUES
10
+ )
11
+ end
12
+
13
+ true
14
+ end
15
+
16
+ def initialize(resource, query_hash)
17
+ @resource = resource
18
+ @query_hash = query_hash
19
+ end
20
+
21
+ def raise_unless_filter_group_requirements_met!
22
+ return if grouped_filters.empty?
23
+
24
+ case filter_group_requirement
25
+ when :all
26
+ raise_unless_all_requirements_met!
27
+ when :any
28
+ raise_unless_any_requirements_met!
29
+ end
30
+
31
+ true
32
+ end
33
+
34
+ private
35
+
36
+ attr_reader :resource, :query_hash
37
+
38
+ def raise_unless_all_requirements_met!
39
+ met = filter_group_names.all? { |filter_name| filter_group_filter_param.key?(filter_name) }
40
+
41
+ unless met
42
+ raise Errors::FilterGroupMissingRequiredFilters.new(
43
+ resource,
44
+ filter_group_names,
45
+ filter_group_requirement
46
+ )
47
+ end
48
+ end
49
+
50
+ def raise_unless_any_requirements_met!
51
+ met = filter_group_names.any? { |filter_name| filter_group_filter_param.key?(filter_name) }
52
+
53
+ unless met
54
+ raise Errors::FilterGroupMissingRequiredFilters.new(
55
+ resource,
56
+ filter_group_names,
57
+ filter_group_requirement
58
+ )
59
+ end
60
+ end
61
+
62
+ def filter_group_names
63
+ grouped_filters.fetch(:names, [])
64
+ end
65
+
66
+ def filter_group_requirement
67
+ grouped_filters.fetch(:required, :invalid)
68
+ end
69
+
70
+ def grouped_filters
71
+ resource.grouped_filters
72
+ end
73
+
74
+ def filter_group_filter_param
75
+ query_hash.fetch(:filter, {})
76
+ end
77
+ end
78
+ end
@@ -136,6 +136,14 @@ module Graphiti
136
136
  base_filter(parents)
137
137
  end
138
138
 
139
+ def link_extra_fields
140
+ extra_fields_name = [association_name, resource.type].find { |param|
141
+ context.params.dig(:extra_fields, param)
142
+ }
143
+
144
+ {resource.type => context.params.dig(:extra_fields, extra_fields_name)} if extra_fields_name
145
+ end
146
+
139
147
  # The parent resource is a remote,
140
148
  # AND the sideload is a remote to the same endpoint
141
149
  def shared_remote?
@@ -63,6 +63,10 @@ module Graphiti
63
63
  params[:filter] = @sideload.link_filter([@model])
64
64
  end
65
65
 
66
+ if (extra_fields = @sideload.link_extra_fields)
67
+ params[:extra_fields] ||= extra_fields
68
+ end
69
+
66
70
  @sideload.params_proc&.call(params, [@model], context)
67
71
  end
68
72
  end
@@ -1,3 +1,3 @@
1
1
  module Graphiti
2
- VERSION = "1.2.33"
2
+ VERSION = "1.2.34"
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: graphiti
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.2.33
4
+ version: 1.2.34
5
5
  platform: ruby
6
6
  authors:
7
7
  - Lee Richmond
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2021-03-07 00:00:00.000000000 Z
11
+ date: 2021-03-16 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: jsonapi-serializable
@@ -308,6 +308,7 @@ files:
308
308
  - lib/graphiti/scoping/default_filter.rb
309
309
  - lib/graphiti/scoping/extra_attributes.rb
310
310
  - lib/graphiti/scoping/filter.rb
311
+ - lib/graphiti/scoping/filter_group_validator.rb
311
312
  - lib/graphiti/scoping/filterable.rb
312
313
  - lib/graphiti/scoping/paginate.rb
313
314
  - lib/graphiti/scoping/sort.rb
@@ -360,7 +361,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
360
361
  - !ruby/object:Gem::Version
361
362
  version: '0'
362
363
  requirements: []
363
- rubygems_version: 3.0.6
364
+ rubygems_version: 3.0.1
364
365
  signing_key:
365
366
  specification_version: 4
366
367
  summary: Easily build jsonapi.org-compatible APIs