insights-api-common 3.8.0 → 3.9.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 7d2889f1fb8a92c64f95de6f5d4a97f111d35e796a2ab4fb6a6b54ade5bbef05
4
- data.tar.gz: 951defb8fb43a566b3f16b49e76f340d95d68f839831c1d6896b72c91dd0428d
3
+ metadata.gz: 484591366a853923b1456ad224f13ea7462cf54c7e2e50091307ab3f6e70dffd
4
+ data.tar.gz: 0cfbc0b28162bcf862173cd1a4941a6cd406e9ca301316be1adb4856dcd834d6
5
5
  SHA512:
6
- metadata.gz: 37ea90782a5dad4f376bcc9b99f051394e855b02f4689c93c8049f7a292cf373da4e4f20f8730efd4f8830e6a680b14e61849c2bf3c5198104b5efb9c167b9ef
7
- data.tar.gz: 8d331fdbfa57116010b32374e8dfc0ef016249336db7e86dc40d5f685f2f382ff2277064aea57dc9eca451e8be1248f40039828f97762358f3d0d7f9c121f9ed
6
+ metadata.gz: 3632e7ccbe7eea9360829aef22960d5605235d95a01b725e7113392787836adb73272ac5280853ea78d610b0bd3b731a507845fd4aecf9dfa2e68d1f5830c72f
7
+ data.tar.gz: 18460ede94fc0d761284dd1b497e31dd9a0993caa17cc949a982098a6faca24b54d1efb3daf78f776a0f0e2ef79f63eeaeb46940fbf1892de99472cba0d06f6a
data/README.md CHANGED
@@ -49,43 +49,76 @@ Or install it yourself as:
49
49
 
50
50
  After implementing filtering in your application, this is the way to filter via parameters on index functions:
51
51
 
52
- | Query Parameter | Ruby Client Parameter <br> **GraphQL filter: Parameter** |
53
- | --------------- | -------------------------------------------------------- |
54
- |"?filter[name]=reviews"|`{:filter => { :name => "reviews" }}`<br> **`filter: { name: "reviews" }`**|
55
- |"?filter[name][eq]=reviews"|`{:filter => { :name => { :eq => "reviews" } }}` <br> **`filter: { name: { eq: "reviews" } }`**|
56
- |"?filter[name][starts_with]=a"|`{:filter => { :name => { :starts_with => "a" } }}` <br> **`filter: { name: { starts_with: "a" } }`**|
57
- |"?filter[name][ends_with]=manager"|`{:filter => { :name => { :ends_with => "manager" } }}` <br> **`filter: { name: { ends_with: "manager" } }`**|
58
- |"?filter[name][contains]=openshift"|`{:filter => { :name => { :contains => "openshift" } }}` <br> **`filter: { name: { contains: "openshift" } }`**|
59
- |"?filter[id]=5"|`{:filter => { :id => "5" }}` <br> **`filter: { id: "5" }`**|
60
- |"?filter[id][eq]=5"|`{:filter => { :id => { :eq => "5" }}}` <br> **`filter: { id: { eq: "5" } }`**|
61
- |"?filter[id][gt]=180"|`{:filter => { :id => { :gt => "180" }}}` <br> **`filter: { id: { gt: "180" } }`**|
62
- |"?filter[id][gte]=190"|`{:filter => { :id => { :gte => "190" }}}` <br> **`filter: { id: { gte: "190" } }`**|
63
- |"?filter[id][lt]=5"|`{:filter => { :id => { :lt => "5" }}} ` <br> **`filter: { id: { lt: "5" } }`**|
64
- |"?filter[id][lte]=5"|`{:filter => { :id => { :lte => "5" }}}` <br> **`filter: { id: { lte: "5" } }`**|
65
- |"?filter[id][]=5&filter[id][]=10&filter[id][]=15&filter[id][]=20"|`{:filter => { :id => ["5", "10", "15", "20"]}}` <br> **`filter: { id: ["5", "10", "15", "20"] }`**|
66
- |"?filter[id][eq][]=5&filter[id][eq][]=10&filter[id][eq][]=15&filter[id][eq][]=20"|`{:filter => { :id => { :eq => ["5", "10", "15", "20"]}}}` <br> **`filter: { id: { eq: ["5", "10", "15", "20"] }`**|
52
+ | Query Parameter | Ruby Client Parameter | GraphQL Parameter |
53
+ | --------------- | --------------------- | ----------------- |
54
+ | "?filter[name]=reviews" | { :filter => { :name => "reviews" } } | filter: { name: "reviews" } |
55
+ | "?filter[name][eq]=reviews" | { :filter => { :name => { :eq => "reviews" } } } | filter: { name: { eq: "reviews" } } |
56
+ | "?filter[name][starts_with]=a" | { :filter => { :name => { :starts_with => "a" } } } | filter: { name: { starts_with: "a" } } |
57
+ | "?filter[name][ends_with]=manager" | { :filter => { :name => { :ends_with => "manager" } } } | filter: { name: { ends_with: "manager" } } |
58
+ | "?filter[name][contains]=openshift" | { :filter => { :name => { :contains => "openshift" } } } | filter: { name: { contains: "openshift" } } |
59
+ | "?filter[id]=5" | { :filter => { :id => "5" } } | filter: { id: "5" } |
60
+ | "?filter[id][eq]=5" | { :filter => { :id => { :eq => "5" } } } | filter: { id: { eq: "5" } } |
61
+ | "?filter[id][gt]=180" | { :filter => { :id => { :gt => "180" } } } | filter: { id: { gt: "180" } } |
62
+ | "?filter[id][gte]=190" | { :filter => { :id => { :gte => "190" } } } | filter: { id: { gte: "190" } } |
63
+ | "?filter[id][lt]=5" | { :filter => { :id => { :lt => "5" } } } | filter: { id: { lt: "5" } } |
64
+ | "?filter[id][lte]=5" | { :filter => { :id => { :lte => "5" } } } | filter: { id: { lte: "5" } } |
65
+ | "?filter[id][]=5&filter[id][]=10&filter[id][]=15&filter[id][]=20" | { :filter => { :id => ["5", "10", "15", "20"] } } | filter: { id: ["5", "10", "15", "20"] } |
66
+ | "?filter[id][eq][]=5&filter[id][eq][]=10&filter[id][eq][]=15&filter[id][eq][]=20" | { :filter => { :id => { :eq => ["5", "10", "15", "20"] } } } | filter: { id: { eq: ["5", "10", "15", "20"] } |
67
67
 
68
68
  #### Sorting Results
69
69
 
70
70
  Sorting query results is controlled via the _sort_by_ query parameter. The _sort_by_ parameter is available for both REST API and GraphQL requests.
71
71
 
72
- The syntax for the _sort_by_ parameter supports:
72
+ The _sort_by_ parameter specifies which attribute name to sort the results by, and may include a sort order of ascending _asc_ or descending _desc_. The default behavior when no sorting order is specified is to sort by ascending order.
73
+
74
+ The syntax for the _sort_by_ parameter is as follows:
73
75
 
74
- - a single string representing the attribute name to sort by which may be followed by :asc or :desc
75
- - **attribute** (_default order is ascending_)
76
- - **attribute:asc** (_ascending order_)
77
- - **attribute:desc** (_descending order_)
78
- - an array of strings of the above syntax
76
+ - One or more object keys representing the attribute name(s) to sort by which may be assigned the **asc** or **desc** value for the sort order.
77
+
78
+ - [**attribute**] (_default order is ascending_)
79
+ - [**attribute**]=**asc** (_ascending order_)
80
+ - [**attribute**]=**desc** (_descending order_)
79
81
 
80
82
  ##### Sort_by Examples:
81
83
 
82
- - GET /api/v1.0/sources?sort_by=name
83
- - GET /api/v1.0/vms?sort_by[]=power_state\&sort_by[]=memory:desc
84
+ - GET /api/v2.0/sources?sort_by[name]
85
+ - GET /api/v2.0/vms?sort_by[power_state]&sort_by[memory]=desc
86
+
87
+ | Query Parameter | Ruby Client Parameter | GraphQL Parameter |
88
+ | --------------- | --------------------- | ----------------- |
89
+ | "?sort_by[name]" | { :sort_by => { :name => nil } } | sort_by: { name: null } |
90
+ | "?sort_by[name]=asc" | { :sort_by => { :name => "asc" } } | sort_by: { name: "asc" } |
91
+ | "?sort_by[power_state]&sort_by[memory]=desc" | { :sort_by => { :power_state => nil, :memory => "desc" } } | sort_by: { power_state: null, memory: "desc" } |
92
+
93
+ #### Filtering and Sorting by Association attribute
94
+
95
+ Requests can also be filtered by assocation attribute and sorted by association attribute and count in addition to the direct attribute specified as in the above examples.
96
+
97
+ Single level association can be specified as follows:
98
+
99
+ ##### Filter by association attribute:
100
+
101
+ | Query Parameter | Ruby Client Parameter | GraphQL Parameter |
102
+ | --------------- | --------------------- | ----------------- |
103
+ | "?filter[association][name]=reviews" | { :filter => { :association => { :name => "reviews" } } } | filter: { association: { name: "reviews" } } |
104
+ | "?filter[association][name][eq]=reviews" | { :filter => { :association => { :name => { :eq => "reviews" } } } } | filter: { association: { name: { eq: "reviews" } } } |
105
+
106
+ ##### Sort by association attributes and count:
107
+
108
+ The _sort_by_ parameter can also be used to choose to sort by attributes of association objects as well as sorting by
109
+ the count of association records by specifying the **__count** special attribute as follows:
110
+
111
+ | Query Parameter | Ruby Client Parameter | GraphQL Parameter |
112
+ | --------------- | --------------------- | ----------------- |
113
+ | "?sort_by[association][name]" | { :sort_by => { :association => { :name => nil } } } | sort_by: { association: { name: null } } |
114
+ | "?sort_by[association][name]=desc" | { :sort_by => { :association => { :name => "desc" } } } | sort_by: { association: { name: "desc" } } |
115
+ | "?sort_by[association][__count]=asc" | { :sort_by => { :association => { :__count => "asc" } } } | sort_by: { association: { __count: "asc" } } |
116
+
117
+ ##### Combined Filtering and Sorting example:
84
118
 
85
119
  | Query Parameter | Ruby Client Parameter | GraphQL Parameter |
86
120
  | --------------- | --------------------- | ----------------- |
87
- | "?sort_by=name" | { :sort_by => "name" } | sort_by: "name" |
88
- | "?sort_by[]=power_state\&sort_by[]=memory:desc" | { :sort_by => ["power_state", "memory:desc"] } | sort_by: ["power_state, "memory:desc"] |
121
+ | "?filter[name][starts_with]=sample_&sort_by[application_types][__count]=desc&sort_by[name]=asc" | { :filter => { :name => { :starts_with => "sample_" } }, :sort_by => { :application_types => { :__count => "desc" }, :name => "asc" } } | filter: { name: { starts_with: "sample_" } }, sort_by: { application_types: { __count: "desc" }, name: "asc" } |
89
122
 
90
123
  ## Development
91
124
 
@@ -17,6 +17,10 @@ module Insights
17
17
  self.class.send(:api_doc_definition)
18
18
  end
19
19
 
20
+ def api_doc_definitions
21
+ self.class.send(:api_doc_definitions)
22
+ end
23
+
20
24
  module ClassMethods
21
25
  private
22
26
 
@@ -28,6 +32,10 @@ module Insights
28
32
  @api_doc_definition ||= api_doc.definitions[name.split("::").last[0..-11].singularize]
29
33
  end
30
34
 
35
+ def api_doc_definitions
36
+ @api_doc_definitions ||= api_doc.definitions
37
+ end
38
+
31
39
  def api_version
32
40
  @api_version ||= name.split("::")[1].downcase
33
41
  end
@@ -90,7 +90,11 @@ module Insights
90
90
 
91
91
  def filtered
92
92
  check_if_openapi_enabled
93
- Insights::API::Common::Filter.new(model, safe_params_for_list[:filter], api_doc_definition, extra_attributes_for_filtering).apply
93
+ association_attribute_properties =
94
+ Insights::API::Common::Filter.association_attribute_properties(api_doc_definitions, safe_params_for_list[:filter])
95
+ extra_attribute_properties = extra_attributes_for_filtering.merge(association_attribute_properties)
96
+
97
+ Insights::API::Common::Filter.new(model, safe_params_for_list[:filter], api_doc_definition, extra_attribute_properties).apply
94
98
  end
95
99
 
96
100
  def extra_attributes_for_filtering
@@ -4,6 +4,7 @@ module Insights
4
4
  class Filter
5
5
  INTEGER_COMPARISON_KEYWORDS = ["eq", "gt", "gte", "lt", "lte", "nil", "not_nil"].freeze
6
6
  STRING_COMPARISON_KEYWORDS = ["contains", "contains_i", "eq", "eq_i", "starts_with", "starts_with_i", "ends_with", "ends_with_i", "nil", "not_nil"].freeze
7
+ ALL_COMPARISON_KEYWORDS = (INTEGER_COMPARISON_KEYWORDS + STRING_COMPARISON_KEYWORDS).uniq.freeze
7
8
 
8
9
  attr_reader :apply, :arel_table, :api_doc_definition, :extra_filterable_attributes, :model
9
10
 
@@ -23,18 +24,23 @@ module Insights
23
24
  # A new Filter object, call #apply to get the filtered set of results.
24
25
  #
25
26
  def initialize(model, raw_filter, api_doc_definition, extra_filterable_attributes = {})
26
- self.query = model
27
+ @raw_filter = raw_filter
27
28
  @api_doc_definition = api_doc_definition
28
29
  @arel_table = model.arel_table
29
30
  @extra_filterable_attributes = extra_filterable_attributes
30
31
  @model = model
31
- @raw_filter = raw_filter
32
32
  end
33
33
 
34
+ def query
35
+ @query ||= filter_associations.present? ? model.left_outer_joins(filter_associations) : model
36
+ end
37
+ attr_writer :query
38
+
34
39
  def apply
35
40
  return query if @raw_filter.blank?
36
- @raw_filter.each do |k, v|
37
- next unless attribute = attribute_for_key(k)
41
+
42
+ self.class.compact_filter(@raw_filter).each do |k, v|
43
+ next unless (attribute = attribute_for_key(k))
38
44
 
39
45
  if attribute["type"] == "string"
40
46
  type = determine_string_attribute_type(attribute)
@@ -48,13 +54,86 @@ module Insights
48
54
  query
49
55
  end
50
56
 
57
+ # Compact filters to support association filtering
58
+ #
59
+ # Input: {"source_type"=>{"name"=>{"eq"=>"rhev"}}}
60
+ # Output: {"source_type.name"=>{"eq"=>"rhev"}}
61
+ #
62
+ # Input: {"source_type"=>{"name"=>{"eq"=>["openstack", "openshift"]}}}
63
+ # Output: {"source_type.name"=>{"eq"=>["openstack", "openshift"]}}
64
+ #
65
+ def self.compact_filter(filter)
66
+ result = {}
67
+ return result if filter.blank?
68
+ return filter unless filter.kind_of?(Hash) || filter.kind_of?(ActionController::Parameters)
69
+
70
+ filter = Hash(filter.permit!) if filter.kind_of?(ActionController::Parameters)
71
+
72
+ filter.each do |ak, av|
73
+ if av.kind_of?(Hash)
74
+ av.each do |atk, atv|
75
+ if !ALL_COMPARISON_KEYWORDS.include?(atk)
76
+ result["#{ak}.#{atk}"] = atv
77
+ else
78
+ result[ak] = av
79
+ end
80
+ end
81
+ else
82
+ result[ak] = av
83
+ end
84
+ end
85
+ result
86
+ end
87
+
88
+ def self.association_attribute_properties(api_doc_definitions, raw_filter)
89
+ return {} if raw_filter.blank?
90
+
91
+ association_attributes = compact_filter(raw_filter).keys.select { |key| key.include?('.') }.compact.uniq
92
+ return {} if association_attributes.blank?
93
+
94
+ association_attributes.each_with_object({}) do |key, hash|
95
+ association, attr = key.split('.')
96
+ hash[key] = api_doc_definitions[association.singularize.classify].properties[attr.to_s]
97
+ end
98
+ end
99
+
51
100
  private
52
101
 
53
- attr_accessor :query
54
102
  delegate(:arel_attribute, :to => :model)
55
103
 
56
104
  class Error < ArgumentError; end
57
105
 
106
+ def key_model_attribute(key)
107
+ if key.include?('.')
108
+ association, attr = key.split('.')
109
+ [association.classify.constantize, attr]
110
+ else
111
+ [model, key]
112
+ end
113
+ end
114
+
115
+ def model_arel_attribute(key)
116
+ key_model, attr = key_model_attribute(key)
117
+ key_model.arel_attribute(attr)
118
+ end
119
+
120
+ def model_arel_table(key)
121
+ key_model, attr = key_model_attribute(key)
122
+ key_model.arel_table
123
+ end
124
+
125
+ def filter_associations
126
+ return nil if @raw_filter.blank?
127
+
128
+ @filter_associations ||= begin
129
+ self.class.compact_filter(@raw_filter).keys.collect do |key|
130
+ next unless key.include?('.')
131
+
132
+ key.split('.').first.to_sym
133
+ end.compact.uniq
134
+ end
135
+ end
136
+
58
137
  def attribute_for_key(key)
59
138
  attribute = api_doc_definition.properties[key.to_s]
60
139
  attribute ||= extra_filterable_attributes[key.to_s]
@@ -74,7 +153,7 @@ module Insights
74
153
  end
75
154
 
76
155
  def string(k, val)
77
- if val.kind_of?(ActionController::Parameters)
156
+ if val.kind_of?(Hash)
78
157
  val.each do |comparator, value|
79
158
  add_filter(comparator, STRING_COMPARISON_KEYWORDS, k, value)
80
159
  end
@@ -99,7 +178,7 @@ module Insights
99
178
  end
100
179
 
101
180
  def timestamp(k, val)
102
- if val.kind_of?(ActionController::Parameters)
181
+ if val.kind_of?(Hash)
103
182
  val.each do |comparator, value|
104
183
  add_filter(comparator, INTEGER_COMPARISON_KEYWORDS, k, value)
105
184
  end
@@ -118,7 +197,7 @@ module Insights
118
197
  end
119
198
 
120
199
  def integer(k, val)
121
- if val.kind_of?(ActionController::Parameters)
200
+ if val.kind_of?(Hash)
122
201
  val.each do |comparator, value|
123
202
  add_filter(comparator, INTEGER_COMPARISON_KEYWORDS, k, value)
124
203
  end
@@ -128,69 +207,69 @@ module Insights
128
207
  end
129
208
 
130
209
  def arel_lower(key)
131
- Arel::Nodes::NamedFunction.new("LOWER", [arel_attribute(key)])
210
+ Arel::Nodes::NamedFunction.new("LOWER", [model_arel_attribute(key)])
132
211
  end
133
212
 
134
213
  def comparator_contains(key, value)
135
214
  return value.each { |v| comparator_contains(key, v) } if value.kind_of?(Array)
136
215
 
137
- self.query = query.where(arel_attribute(key).matches("%#{query.sanitize_sql_like(value)}%", nil, true))
216
+ self.query = query.where(model_arel_attribute(key).matches("%#{query.sanitize_sql_like(value)}%", nil, true))
138
217
  end
139
218
 
140
219
  def comparator_contains_i(key, value)
141
220
  return value.each { |v| comparator_contains_i(key, v) } if value.kind_of?(Array)
142
221
 
143
- self.query = query.where(arel_table.grouping(arel_lower(key).matches("%#{query.sanitize_sql_like(value.downcase)}%", nil, true)))
222
+ self.query = query.where(model_arel_table(key).grouping(arel_lower(key).matches("%#{query.sanitize_sql_like(value.downcase)}%", nil, true)))
144
223
  end
145
224
 
146
225
  def comparator_starts_with(key, value)
147
- self.query = query.where(arel_attribute(key).matches("#{query.sanitize_sql_like(value)}%", nil, true))
226
+ self.query = query.where(model_arel_attribute(key).matches("#{query.sanitize_sql_like(value)}%", nil, true))
148
227
  end
149
228
 
150
229
  def comparator_starts_with_i(key, value)
151
- self.query = query.where(arel_table.grouping(arel_lower(key).matches("#{query.sanitize_sql_like(value.downcase)}%", nil, true)))
230
+ self.query = query.where(model_arel_table(key).grouping(arel_lower(key).matches("#{query.sanitize_sql_like(value.downcase)}%", nil, true)))
152
231
  end
153
232
 
154
233
  def comparator_ends_with(key, value)
155
- self.query = query.where(arel_attribute(key).matches("%#{query.sanitize_sql_like(value)}", nil, true))
234
+ self.query = query.where(model_arel_attribute(key).matches("%#{query.sanitize_sql_like(value)}", nil, true))
156
235
  end
157
236
 
158
237
  def comparator_ends_with_i(key, value)
159
- self.query = query.where(arel_table.grouping(arel_lower(key).matches("%#{query.sanitize_sql_like(value.downcase)}", nil, true)))
238
+ self.query = query.where(model_arel_table(key).grouping(arel_lower(key).matches("%#{query.sanitize_sql_like(value.downcase)}", nil, true)))
160
239
  end
161
240
 
162
241
  def comparator_eq(key, value)
163
- self.query = query.where(arel_attribute(key).eq_any(Array(value)))
242
+ self.query = query.where(model_arel_attribute(key).eq_any(Array(value)))
164
243
  end
165
244
 
166
245
  def comparator_eq_i(key, value)
167
246
  values = Array(value).map { |v| query.sanitize_sql_like(v.downcase) }
168
247
 
169
- self.query = query.where(arel_table.grouping(arel_lower(key).matches_any(values)))
248
+ self.query = query.where(model_arel_table(key).grouping(arel_lower(key).matches_any(values)))
170
249
  end
171
250
 
172
251
  def comparator_gt(key, value)
173
- self.query = query.where(arel_attribute(key).gt(value))
252
+ self.query = query.where(model_arel_attribute(key).gt(value))
174
253
  end
175
254
 
176
255
  def comparator_gte(key, value)
177
- self.query = query.where(arel_attribute(key).gteq(value))
256
+ self.query = query.where(model_arel_attribute(key).gteq(value))
178
257
  end
179
258
 
180
259
  def comparator_lt(key, value)
181
- self.query = query.where(arel_attribute(key).lt(value))
260
+ self.query = query.where(model_arel_attribute(key).lt(value))
182
261
  end
183
262
 
184
263
  def comparator_lte(key, value)
185
- self.query = query.where(arel_attribute(key).lteq(value))
264
+ self.query = query.where(model_arel_attribute(key).lteq(value))
186
265
  end
187
266
 
188
267
  def comparator_nil(key, _value = nil)
189
- self.query = query.where(arel_attribute(key).eq(nil))
268
+ self.query = query.where(model_arel_attribute(key).eq(nil))
190
269
  end
191
270
 
192
271
  def comparator_not_nil(key, _value = nil)
193
- self.query = query.where.not(arel_attribute(key).eq(nil))
272
+ self.query = query.where.not(model_arel_attribute(key).eq(nil))
194
273
  end
195
274
  end
196
275
  end
@@ -34,10 +34,13 @@ QueryType = ::GraphQL::ObjectType.define do
34
34
  if args[:filter]
35
35
  openapi_doc = ::Insights::API::Common::OpenApi::Docs.instance["<%= api_version %>"]
36
36
  openapi_schema_name, _schema = ::Insights::API::Common::GraphQL::Generator.openapi_schema(openapi_doc, klass_name)
37
+ association_attribute_properties =
38
+ Insights::API::Common::Filter.association_attribute_properties(openapi_doc.definitions, ActionController::Parameters.new(args[:filter]))
37
39
  scope = ::Insights::API::Common::Filter.new(
38
40
  scope,
39
41
  ActionController::Parameters.new(args[:filter]),
40
- openapi_doc.definitions[openapi_schema_name]).apply
42
+ openapi_doc.definitions[openapi_schema_name],
43
+ association_attribute_properties).apply
41
44
  end
42
45
  scope = ::Insights::API::Common::GraphQL.search_options(scope, args)
43
46
  if <%= graphql_options[:use_pagination_v2] %> == true
@@ -12,7 +12,7 @@ module Insights
12
12
 
13
13
  Service.call(RBACApiClient::GroupApi) do |api|
14
14
  uuids = SortedSet.new
15
- Service.paginate(api, :list_groups, {}).each { |group| uuids << group.uuid }
15
+ Service.paginate(api, :list_groups, {:uuid => @group_uuids.to_a}).each { |group| uuids << group.uuid }
16
16
  missing = @group_uuids - uuids
17
17
  raise Insights::API::Common::InvalidParameter, "The following group uuids are missing #{missing.to_a.join(",")}" unless missing.empty?
18
18
  end
@@ -1,7 +1,7 @@
1
1
  module Insights
2
2
  module API
3
3
  module Common
4
- VERSION = "3.8.0".freeze
4
+ VERSION = "3.9.0".freeze
5
5
  end
6
6
  end
7
7
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: insights-api-common
3
3
  version: !ruby/object:Gem::Version
4
- version: 3.8.0
4
+ version: 3.9.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Insights Authors
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2020-03-24 00:00:00.000000000 Z
11
+ date: 2020-04-02 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: acts_as_tenant
@@ -134,14 +134,14 @@ dependencies:
134
134
  requirements:
135
135
  - - "~>"
136
136
  - !ruby/object:Gem::Version
137
- version: 0.6.1
137
+ version: 0.10.0
138
138
  type: :runtime
139
139
  prerelease: false
140
140
  version_requirements: !ruby/object:Gem::Requirement
141
141
  requirements:
142
142
  - - "~>"
143
143
  - !ruby/object:Gem::Version
144
- version: 0.6.1
144
+ version: 0.10.0
145
145
  - !ruby/object:Gem::Dependency
146
146
  name: graphql
147
147
  requirement: !ruby/object:Gem::Requirement