lms-api 1.22.0 → 1.23.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,604 @@
1
+ module CanvasApi
2
+ module GoHelpers
3
+ def struct_fields(model, resource_name)
4
+ if !model["properties"]
5
+ puts "NO properties for #{resource_name} !!!!!!!!!!!!!!!!!!!!!"
6
+ return []
7
+ end
8
+
9
+ time_required = false
10
+ fields = model["properties"].map do |name, property|
11
+ description = ""
12
+ description << "#{safe_rb(property['description'].gsub("\n", "\n //"))}." if property["description"].present?
13
+ description << "Example: #{safe_rb(property['example'])}".gsub("..", "").gsub("\n", " ") if property["example"].present?
14
+
15
+ # clean up name
16
+ name = nested_arg(name)
17
+
18
+ if type = go_type(name, property, false, model, "")
19
+ if type.include? "time.Time"
20
+ time_required = true
21
+ end
22
+ go_declaration(name, type) + " // #{description}"
23
+ else
24
+ raise "Unable to determine type for #{name}"
25
+ end
26
+ end.compact
27
+
28
+ [fields, time_required]
29
+ end
30
+
31
+ # go_struct_fields handles the various forms of parameters documented in the Canvas API
32
+ # Examples:
33
+ #
34
+ # notification_preferences[<X>][frequency]
35
+ # Generates:
36
+ # NotificationPreferences map[string]string `json:"notification_preferences"`
37
+ #
38
+ # calendar_event[child_event_data][X][start_at]
39
+ # Generates:
40
+ # type ChildEventData struct {
41
+ # StartAt time.Time `json:"start_at"` // (Optional)
42
+ # EndAt time.Time `json:"end_at"` // (Optional)
43
+ # ContextCode string `json:"context_code"` // (Optional)
44
+ # }
45
+ # CalendarEvent struct {
46
+ # ChildEventData map[string]*ChildEventData
47
+ # }
48
+ #
49
+ # module_item[completion_requirement][type]
50
+ #
51
+ # events[start_at]
52
+ #
53
+ # Nested param
54
+ # account_notification[subject]
55
+ # Generates:
56
+ # AccountNotification struct {
57
+ # Subject string `json:"subject"` // (Required)
58
+ # Message string `json:"message"` // (Required)
59
+ # StartAt time.Time `json:"start_at"` // (Required)
60
+ # EndAt time.Time `json:"end_at"` // (Required)
61
+ # Icon string `json:"icon"` // (Optional) . Must be one of warning, information, question, error, calendar
62
+ # } `json:"account_notification"`
63
+ #
64
+ def go_struct_fields(nickname, params)
65
+ nested = {}
66
+ params.each do |p|
67
+ structs, name = split_nested(p)
68
+ go_to_tree(nickname, nested, structs, name, p)
69
+ end
70
+ go_render_params(nested)
71
+ end
72
+
73
+ def go_render_params(nested)
74
+ out = ""
75
+ nested.each do |name, val|
76
+ if val["paramType"]
77
+ out << "\n" + go_param_to_field(val, name)
78
+ elsif val[:array_of]
79
+ out << "\n#{struct_name(name)} #{val[:array_of]}"
80
+ elsif val[:map_of]
81
+ out << "\n#{struct_name(name)} #{val[:map_of]}"
82
+ else
83
+ out << "\n#{struct_name(name)} struct {"
84
+ out << go_render_params(val)
85
+ out << "\n} `json:\"#{name.underscore.gsub("`", "")}\" url:\"#{name.underscore.gsub("`", "")},omitempty\"`\n"
86
+ end
87
+ end
88
+ out
89
+ end
90
+
91
+ def go_render_child_structs
92
+ out = ""
93
+ @child_structs&.each do |name, params|
94
+ out << "\ntype #{struct_name(name)} struct {"
95
+ params.each do |n, p|
96
+ out << "\n" + go_param_to_field(p, n)
97
+ end
98
+ out << "\n}\n"
99
+ end
100
+ out
101
+ end
102
+
103
+ # HACK for https://canvas.instructure.com/doc/api/quiz_submissions.html
104
+ # update_student_question_scores_and_comments has a param with the following form
105
+ # {"paramType"=>"form", "name"=>"quiz_submissions[questions]", "type"=>"array", "format"=>nil, "required"=>false, "deprecated"=>false, "items"=>{"$ref"=>"Hash"}}
106
+ QuizSubmissionOverrides = "QuizSubmissionOverrides"
107
+
108
+ def go_to_tree(nickname, nested, structs, name, param)
109
+ @child_structs ||= {}
110
+
111
+ # HACK for https://canvas.instructure.com/doc/api/quiz_submissions.html
112
+ if nickname == "update_student_question_scores_and_comments"
113
+ @child_structs[QuizSubmissionOverrides] = {
114
+ "score" => {"name"=>"score", "type"=>"float"},
115
+ "comment" => {"name"=>"comment", "type"=>"string"},
116
+ }
117
+ end
118
+
119
+ if structs.length > 0
120
+ struct, rest = structs.first, structs[1..-1]
121
+ nested[struct] ||= {}
122
+ if rest
123
+ if is_x_param?(rest[1])
124
+ type = go_property_type(name, param)
125
+ child_name = rest[0]
126
+ child_struct = "#{struct_name(nickname)}#{struct_name(child_name)}"
127
+ @child_structs[child_struct] ||= {}
128
+ @child_structs[child_struct][name] = param
129
+ nested[struct][child_name] = {
130
+ "name" => "#{struct}[#{child_name}]",
131
+ "type" => "map[string]#{child_struct}",
132
+ "paramType" => param["paramType"],
133
+ "keep_type" => true,
134
+ }
135
+ rest.shift
136
+ rest.shift
137
+ elsif is_x_param?(rest[0])
138
+ if rest[0] == structs[1]
139
+ child_name = structs[0]
140
+ child_struct = "#{struct_name(nickname)}#{struct_name(child_name)}"
141
+ nested[struct][:map_of] = "map[string]#{child_struct}"
142
+ @child_structs[child_struct] ||= {}
143
+ @child_structs[child_struct][name] = param
144
+ else
145
+ type = go_property_type(name, param)
146
+ nested[struct][:map_of] = "map[string]#{type}"
147
+ end
148
+ rest.shift
149
+ end
150
+ end
151
+
152
+ if rest && rest.length > 0
153
+ go_to_tree(nickname, nested[struct], rest, name, param)
154
+ else
155
+ if @child_structs && child_struct = nested[struct][:array_of]
156
+ @child_structs[child_struct][name] = param
157
+ else
158
+ nested[struct][name] = param
159
+ end
160
+ end
161
+ else
162
+ nested[name] = param
163
+ if param["type"] == "array" && ["events"].include?(param["name"])
164
+ child_struct = "#{struct_name(nickname)}#{struct_name(param["name"])}"
165
+ @child_structs ||= {}
166
+ @child_structs[child_struct] ||= {}
167
+ nested[name][:array_of] = child_struct
168
+ puts "******** Using custom struct #{child_struct}"
169
+ end
170
+ end
171
+ end
172
+
173
+ def go_param_path(param)
174
+ if is_x_param?(param["name"])
175
+ "#{go_param_kind(param)}.#{go_name(param["name"])}"
176
+ elsif is_nested?(param)
177
+ structs, name = split_nested(param)
178
+ "#{go_param_kind(param)}.#{structs.map{|s| struct_name(s)}.join('.')}.#{go_name(name)}"
179
+ else
180
+ "#{go_param_kind(param)}.#{go_name(param["name"])}"
181
+ end
182
+ end
183
+
184
+ def is_x_param?(name)
185
+ if name
186
+ name.include?("[<X>]") ||
187
+ name.include?("<X>") ||
188
+ name.include?("X") ||
189
+ name.include?("<student_id>") ||
190
+ name.include?("0")
191
+ end
192
+ end
193
+
194
+ def is_nested?(param)
195
+ param["name"].include?("[")
196
+ end
197
+
198
+ def is_array(param)
199
+ param["type"] == "array"
200
+ end
201
+
202
+ def split_nested(param)
203
+ parts = param["name"].split("[").map{|p| p.gsub("]", "")}
204
+ [
205
+ parts[0...-1],
206
+ parts.last,
207
+ ]
208
+ end
209
+
210
+ def go_param_to_field(parameter, name = nil)
211
+ name ||= parameter["name"]
212
+ type = go_type(name, parameter)
213
+ go_declaration(name, type) + " // " + go_comments(parameter, false)
214
+ end
215
+
216
+ def go_comments(parameter, include_description = true)
217
+ out = " (#{parameter["required"] ? 'Required' : 'Optional'}) "
218
+ if parameter["enum"]
219
+ out << ". Must be one of #{parameter["enum"].join(', ')}"
220
+ end
221
+ if include_description && parameter["description"]
222
+ out << parameter["description"].gsub("\n", "\n// ")
223
+ end
224
+ out
225
+ end
226
+
227
+ def go_parameter_doc(parameter)
228
+ name = parameter["name"]
229
+ out = "# #{go_param_path(parameter)}"
230
+ out << go_comments(parameter)
231
+ out
232
+ end
233
+
234
+ def go_param_empty_value(parameter)
235
+ name = parameter["name"]
236
+ if is_x_param?(name)
237
+ return "nil"
238
+ end
239
+ type = go_type(name, parameter)
240
+ case type
241
+ when "int64"
242
+ when "int"
243
+ when "float64"
244
+ "0"
245
+ when "string"
246
+ '""'
247
+ when "time.Time"
248
+ "nil"
249
+ when "map[string](interface{})"
250
+ "nil"
251
+ else
252
+ if type.include?("[]")
253
+ "nil"
254
+ else
255
+ "need empty value for #{type}"
256
+ end
257
+ end
258
+ end
259
+
260
+ def is_required_field(parameter)
261
+ parameter["required"] && !["bool", "int64", "int", "float64"].include?(go_type(parameter["name"], parameter))
262
+ end
263
+
264
+ def go_declaration(name, type)
265
+ json = name.underscore.split("[")[0].gsub("`rlid`", "rlid")
266
+ out = "#{go_name(name)} #{type} `json:\"#{json}\" url:\"#{json},omitempty\"`"
267
+ end
268
+
269
+ def go_name(name)
270
+ parts = name.split("[")
271
+ parts[0].camelize.gsub("-", "").gsub("_", "")
272
+ .gsub("`rlid`", "RLID")
273
+ .gsub("Id", "ID")
274
+ .gsub("url", "URL")
275
+ .gsub("Sis", "SIS")
276
+ .gsub("MediaTrackk", "MediaTrack")
277
+ .gsub("Https:::::Canvas.instructure.com::Lti::Submission", "CanvasLTISubmission")
278
+ end
279
+
280
+ def struct_name(type)
281
+ # Remove chars and fix spelling errors
282
+ cleaned = type.split('|').first.strip.gsub(" ", "_")
283
+ go_name(cleaned)
284
+ end
285
+
286
+ def go_require_models(parameters, nickname, return_type)
287
+ parameters.any? { |p| go_type(p["name"], p).include?("models") } ||
288
+ ["assign_unassigned_members"].include?(@nickname) ||
289
+ (return_type &&
290
+ return_type != "bool" &&
291
+ !return_type.include?("string") &&
292
+ !return_type.include?("SuccessResponse") &&
293
+ !return_type.include?("UnreadCount")
294
+ )
295
+ end
296
+
297
+ def time_required?(parameters)
298
+ parameters.any? { |p| go_type(p["name"], p).include?("time.Time") }
299
+ end
300
+
301
+ def go_type(name, property, return_type = false, model = nil, namespace = "models.")
302
+ if property["$ref"]
303
+ "*#{namespace}#{struct_name(property['$ref'])}"
304
+ else
305
+ go_property_type(name, property, return_type, model, namespace)
306
+ end
307
+ end
308
+
309
+ def go_property_type(name, property, return_type = false, model = nil, namespace = "models.")
310
+ return property["type"] if property["keep_type"]
311
+ return property[:array_of] if property[:array_of]
312
+
313
+ # Canvas API docs are wrong for these so we HACK in the right type
314
+ return "float64" if name.downcase == "points_possible"
315
+
316
+ type = property["type"].downcase
317
+ case type
318
+ when "{success: true}"
319
+ "canvasapi.SuccessResponse"
320
+ when "integer", "string", "boolean", "datetime", "number", "date"
321
+ go_primitive(name, type, property["format"])
322
+ when "void"
323
+ "bool" # TODO this doesn't seem right?
324
+ when "array"
325
+ go_ref_property_type(property, namespace)
326
+ when "object"
327
+ puts "Using string type for '#{name}' ('#{property}') of type object."
328
+ "map[string](interface{})"
329
+ else
330
+ if property["type"] == "list of content items"
331
+ # HACK There's no list of content items object so we return an array of string
332
+ "[]string"
333
+ elsif property["type"].include?('{ "unread_count": "integer" }')
334
+ "canvasapi.UnreadCount"
335
+ elsif return_type
336
+ "*#{namespace}#{struct_name(property["type"])}"
337
+ elsif property["type"] == "Hash"
338
+ "map[string](interface{})"
339
+ elsif property["type"] == "String[]"
340
+ "[]string"
341
+ elsif property["type"] == "[Answer]"
342
+ "[]*models.Answer"
343
+ elsif property["type"] == "QuizUserConversation"
344
+ "canvasapi.QuizUserConversation"
345
+ elsif [
346
+ "Assignment",
347
+ "BlueprintRestriction",
348
+ "RubricAssessment",
349
+ ].include?(property["type"])
350
+ "*models.#{property["type"]}"
351
+ elsif property["type"] == "multiple BlueprintRestrictions"
352
+ "[]*models.BlueprintRestriction"
353
+ elsif property["type"] == "File"
354
+ # This won't work. If we ever need to use this type we'll need to do some refactoring
355
+ "string"
356
+ elsif property["type"] == "Deprecated"
357
+ "string"
358
+ elsif property["type"] == "SerializedHash"
359
+ # Not sure this will work
360
+ "map[string](interface{})"
361
+ elsif property["type"].downcase == "json"
362
+ "map[string](interface{})"
363
+ elsif ["Numeric", "float"].include?(property["type"])
364
+ "float64"
365
+ elsif property["type"] == "GroupMembership | Progress"
366
+ "no-op" # this is handled further up the stack
367
+ elsif property["type"] == "URL"
368
+ "string"
369
+ else
370
+ raise "Unable to match '#{name}' requested property '#{property}' to Go Type."
371
+ end
372
+ end
373
+ end
374
+
375
+ def go_ref_property_type(property, namespace)
376
+ ref_type = property.dig("items", "$ref")
377
+ if ref_type == nil
378
+ if property["type"] == "array"
379
+ "[]string"
380
+ else
381
+ "string"
382
+ end
383
+ elsif ref_type == "Hash"
384
+ # HACK for https://canvas.instructure.com/doc/api/quiz_submissions.html
385
+ if property["name"] == "quiz_submissions[questions]"
386
+ "map[string]QuizSubmissionOverrides"
387
+ else
388
+ raise "No type available for #{property}"
389
+ end
390
+ elsif ref_type == "[Integer]"
391
+ "[]int"
392
+ elsif ref_type == "Array"
393
+ "[]string"
394
+ elsif ref_type == "[String]"
395
+ "[]string"
396
+ elsif ref_type == "DateTime" || ref_type == "Date"
397
+ "[]time.Time"
398
+ elsif ref_type == "object"
399
+ "map[string](interface{})"
400
+ elsif ref_type
401
+ # HACK on https://canvas.instructure.com/doc/api/submissions.json
402
+ # the ref value is set to a full sentence rather than a
403
+ # simple type, so we look for that specific value
404
+ if ref_type.include?("UserDisplay if anonymous grading is not enabled")
405
+ "[]*#{namespace}UserDisplay"
406
+ elsif ref_type.include?("Url String The url to the result that was created")
407
+ "string"
408
+ else
409
+ "[]*#{namespace}#{struct_name(ref_type)}"
410
+ end
411
+ else
412
+ "[]#{go_primitive(name, property["items"]["type"].downcase, property["items"]["format"])}"
413
+ end
414
+ rescue
415
+ raise "Unable to discover Go list type for '#{name}' ('#{property}')."
416
+ end
417
+
418
+ def go_primitive(name, type, format)
419
+ case type
420
+ when "integer"
421
+ if name.end_with?("_ids")
422
+ "[]int64"
423
+ else
424
+ "int64"
425
+ end
426
+ when "number"
427
+ if format == "Float"
428
+ "float64"
429
+ else
430
+ # TODO many of the LMS types with 'number' don't indicate a type so we have to guess
431
+ # Hopefully that changes. For now we go with float
432
+ "float64"
433
+ end
434
+ when "string"
435
+ "string"
436
+ when "boolean"
437
+ "bool"
438
+ when "datetime"
439
+ "time.Time"
440
+ when "date"
441
+ "time.Time"
442
+ else
443
+ raise "Unable to match requested primitive '#{type}' to Go Type."
444
+ end
445
+ end
446
+
447
+ def go_field_validation(model)
448
+ return nil unless model["properties"]
449
+ allowable = {}
450
+ model["properties"].each do |name, property|
451
+ if property["allowableValues"]
452
+ values = property["allowableValues"]["values"].map do |value|
453
+ "\"#{value}\""
454
+ end
455
+ allowable[name] = {
456
+ values: values,
457
+ type: property["type"],
458
+ }
459
+ end
460
+ end
461
+ allowable
462
+ end
463
+
464
+ def go_param_kind(parmeter)
465
+ case parmeter["paramType"]
466
+ when "path"
467
+ "Path"
468
+ when "query"
469
+ "Query"
470
+ when "form"
471
+ "Form"
472
+ else
473
+ "Unknown paramType"
474
+ end
475
+ end
476
+
477
+ def go_path_params(params)
478
+ select_params("path", params)
479
+ end
480
+
481
+ def go_query_params(params)
482
+ select_params("query", params)
483
+ end
484
+
485
+ def go_form_params(params)
486
+ select_params("form", params)
487
+ end
488
+
489
+ def select_params(type, parameters)
490
+ params = parameters.select{|p| p["paramType"] == type}
491
+ if params && !params.nil? && params.length > 0
492
+ params
493
+ else
494
+ nil
495
+ end
496
+ end
497
+
498
+ def go_api_url
499
+ url = @api_url
500
+ @args.each do |arg|
501
+ url.gsub(arg, "+\"#{go_name(arg)}\"+")
502
+ end
503
+ url
504
+ end
505
+
506
+ def is_paged?(operation)
507
+ operation["type"] == "array"
508
+ end
509
+
510
+ def next_param(operation)
511
+ if is_paged?(operation)
512
+ ", next *url.URL"
513
+ end
514
+ end
515
+
516
+ def go_do_return_statement(operation, nickname)
517
+ if nickname == "assign_unassigned_members" || is_paged?(operation)
518
+ "return nil, nil, err"
519
+ elsif type = go_return_type(operation)
520
+ if type == "bool"
521
+ "return false, err"
522
+ elsif type == "string"
523
+ 'return "", err'
524
+ elsif type == "integer"
525
+ "return 0, err"
526
+ else
527
+ "return nil, err"
528
+ end
529
+ else
530
+ "return err"
531
+ end
532
+ end
533
+
534
+ def go_do_final_return_statement(operation, nickname)
535
+ if nickname == "assign_unassigned_members"
536
+ "return &groupMembership, &progress, nil"
537
+ elsif go_return_type(operation)
538
+ if is_paged?(operation)
539
+ "return ret, pagedResource, nil"
540
+ elsif operation["type"] == "boolean" || operation["type"] == "string" || operation["type"] == "integer"
541
+ "return ret, nil"
542
+ else
543
+ "return &ret, nil"
544
+ end
545
+ else
546
+ "return nil"
547
+ end
548
+ end
549
+
550
+ def go_do_return_value(operation, nickname)
551
+ if nickname == "assign_unassigned_members"
552
+ # HACK. harded coded because Assign unassigned members returns different values based on input
553
+ # see https://canvas.instructure.com/doc/api/group_categories.html#method.group_categories.assign_unassigned_members
554
+ "(*models.GroupMembership, *models.Progress, error)"
555
+ elsif type = go_return_type(operation)
556
+ if is_paged?(operation)
557
+ "(#{type}, *canvasapi.PagedResource, error)"
558
+ else
559
+ "(#{type}, error)"
560
+ end
561
+ else
562
+ "error"
563
+ end
564
+ end
565
+
566
+ def go_return_type(operation, is_decl = false)
567
+ prefix = is_decl ? "" : "*"
568
+ suffix = is_decl ? "{}" : ""
569
+ if operation["type"] == "void"
570
+ nil
571
+ elsif is_paged?(operation)
572
+ model = operation.dig("items", "$ref")
573
+ if model.include?(" ")
574
+ # Handle cases with spaces using go_property_type
575
+ type = go_property_type(operation["nickname"], operation)
576
+ if type == "string"
577
+ type = "[]#{type}"
578
+ end
579
+ "#{type}#{suffix}"
580
+ else
581
+ "[]*models.#{go_name(model)}#{suffix}"
582
+ end
583
+ elsif operation["type"] == "boolean"
584
+ "bool"
585
+ elsif operation["type"] == "integer"
586
+ "int64"
587
+ elsif model = operation["type"]
588
+ if model.include?(" ")
589
+ # Handle cases with spaces using go_property_type
590
+ type = go_property_type(operation["nickname"], operation)
591
+ if type == "string"
592
+ type
593
+ else
594
+ "#{prefix}#{type}#{suffix}"
595
+ end
596
+ else
597
+ "#{prefix}models.#{go_name(model)}#{suffix}"
598
+ end
599
+ else
600
+ raise "No return type found for #{operation}"
601
+ end
602
+ end
603
+ end
604
+ end
@@ -0,0 +1,17 @@
1
+ module CanvasApi
2
+ def nested_arg(str)
3
+ # TODO/HACK we are replacing values from the string here to get things to work for now.
4
+ # However, removing these symbols means that the methods that use the arguments
5
+ # generated herein will have bugs and be unusable.
6
+ str.gsub("[", "_").
7
+ gsub("]", "").
8
+ gsub("*", "star").
9
+ gsub("<", "_").
10
+ gsub(">", "_").
11
+ gsub("`", "").
12
+ gsub("https://canvas.instructure.com/lti/", "").
13
+ gsub("https://www.instructure.com/", "").
14
+ gsub("https://purl.imsglobal.org/spec/lti/claim/", "").
15
+ gsub(".", "")
16
+ end
17
+ end
@@ -93,6 +93,13 @@ module CanvasApi
93
93
  return str unless str.is_a?(String)
94
94
  str.gsub('"', "'")
95
95
  end
96
+
97
+ def graphql_resolver_class(name)
98
+ # HACK Some resolvers have both singular and plural versions, so keep the plural on those
99
+ return name.camelize if name == "get_custom_colors"
100
+
101
+ name.classify
102
+ end
96
103
  end
97
104
 
98
- end
105
+ end
@@ -9,7 +9,7 @@ module CanvasApi
9
9
  if property["$ref"]
10
10
  canvas_name(property['$ref'], input_type)
11
11
  elsif property["allowableValues"]
12
- enum_class_name(model, name)
12
+ enum_class_name(model, name, input_type)
13
13
  else
14
14
  type = property["type"].downcase
15
15
  case type
@@ -106,11 +106,11 @@ module CanvasApi
106
106
  end
107
107
  end
108
108
 
109
- def enum_class_name(model, field_name)
110
- "#{model['id'].classify}#{field_name.classify}Enum"
109
+ def enum_class_name(model, field_name, input_type)
110
+ "#{model['id'].classify}#{input_type ? 'Input' : ''}#{field_name.classify}Enum"
111
111
  end
112
112
 
113
- def graphql_field_enums(model)
113
+ def graphql_field_enums(model, input_type = false)
114
114
  return unless model["properties"]
115
115
  enums = model["properties"].map do |name, property|
116
116
  if property["allowableValues"]
@@ -118,7 +118,7 @@ module CanvasApi
118
118
  "value \"#{value}\""
119
119
  end.join("\n ")
120
120
  <<-CODE
121
- class #{enum_class_name(model, name)} < ::GraphQL::Schema::Enum
121
+ class #{enum_class_name(model, name, input_type)} < ::GraphQL::Schema::Enum
122
122
  #{values}
123
123
  end
124
124
  CODE
@@ -200,7 +200,7 @@ field :#{name.underscore}, #{type}, "#{description}", resolver_method: :resolve_
200
200
  end
201
201
 
202
202
  def make_file_name(str)
203
- str.underscore.split("/").last.split("|").first.gsub("canvas_", "").gsub(" ", "_").strip.singularize
203
+ str.underscore.split("/").last.split("|").first.gsub(/^canvas_?/, "").gsub(" ", "_").strip.singularize
204
204
  end
205
205
 
206
206
  def require_from_operation(operation)
@@ -232,22 +232,6 @@ field :#{name.underscore}, #{type}, "#{description}", resolver_method: :resolve_
232
232
  str.gsub('"', "'")
233
233
  end
234
234
 
235
- def nested_arg(str)
236
- # TODO/HACK we are replacing values from the string here to get things to work for now.
237
- # However, removing these symbols means that the methods that use the arguments
238
- # generated herein will have bugs and be unusable.
239
- str.gsub("[", "_").
240
- gsub("]", "").
241
- gsub("*", "star").
242
- gsub("<", "_").
243
- gsub(">", "_").
244
- gsub("`", "").
245
- gsub("https://canvas.instructure.com/lti/", "").
246
- gsub("https://www.instructure.com/", "").
247
- gsub("https://purl.imsglobal.org/spec/lti/claim/", "").
248
- gsub(".", "")
249
- end
250
-
251
235
  def params_as_string(parameters, paramTypes)
252
236
  filtered = parameters.select{ |p| paramTypes.include?(p["paramType"]) }
253
237
  if filtered && !filtered.empty?