forest_admin_agent 1.12.14 → 1.12.15

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.
Files changed (28) hide show
  1. checksums.yaml +4 -4
  2. data/lib/forest_admin_agent/routes/abstract_authenticated_route.rb +7 -5
  3. data/lib/forest_admin_agent/routes/abstract_related_route.rb +9 -7
  4. data/lib/forest_admin_agent/routes/abstract_route.rb +7 -3
  5. data/lib/forest_admin_agent/routes/action/actions.rb +31 -25
  6. data/lib/forest_admin_agent/routes/capabilities/collections.rb +4 -4
  7. data/lib/forest_admin_agent/routes/charts/api_chart_collection.rb +10 -10
  8. data/lib/forest_admin_agent/routes/charts/api_chart_datasource.rb +8 -7
  9. data/lib/forest_admin_agent/routes/charts/charts.rb +64 -66
  10. data/lib/forest_admin_agent/routes/request_context.rb +17 -0
  11. data/lib/forest_admin_agent/routes/resources/count.rb +9 -9
  12. data/lib/forest_admin_agent/routes/resources/csv.rb +11 -11
  13. data/lib/forest_admin_agent/routes/resources/delete.rb +20 -19
  14. data/lib/forest_admin_agent/routes/resources/list.rb +14 -14
  15. data/lib/forest_admin_agent/routes/resources/native_query.rb +9 -9
  16. data/lib/forest_admin_agent/routes/resources/related/associate_related.rb +32 -29
  17. data/lib/forest_admin_agent/routes/resources/related/count_related.rb +9 -9
  18. data/lib/forest_admin_agent/routes/resources/related/csv_related.rb +10 -9
  19. data/lib/forest_admin_agent/routes/resources/related/dissociate_related.rb +63 -40
  20. data/lib/forest_admin_agent/routes/resources/related/list_related.rb +12 -11
  21. data/lib/forest_admin_agent/routes/resources/related/update_related.rb +60 -52
  22. data/lib/forest_admin_agent/routes/resources/show.rb +8 -8
  23. data/lib/forest_admin_agent/routes/resources/store.rb +18 -15
  24. data/lib/forest_admin_agent/routes/resources/update.rb +9 -9
  25. data/lib/forest_admin_agent/routes/resources/update_field.rb +17 -17
  26. data/lib/forest_admin_agent/utils/schema/schema_emitter.rb +1 -1
  27. data/lib/forest_admin_agent/version.rb +1 -1
  28. metadata +2 -1
@@ -19,25 +19,25 @@ module ForestAdminAgent
19
19
  end
20
20
 
21
21
  def handle_request(args = {})
22
- build(args)
23
- @permissions.can?(:browse, @collection)
24
- @permissions.can?(:export, @collection)
22
+ context = build(args)
23
+ context.permissions.can?(:browse, context.collection)
24
+ context.permissions.can?(:export, context.collection)
25
25
  filter = ForestAdminDatasourceToolkit::Components::Query::Filter.new(
26
26
  condition_tree: ConditionTreeFactory.intersect(
27
27
  [
28
- @permissions.get_scope(@collection),
29
- parse_query_segment(@collection, args, @permissions, @caller),
28
+ context.permissions.get_scope(context.collection),
29
+ parse_query_segment(context.collection, args, context.permissions, context.caller),
30
30
  QueryStringParser.parse_condition_tree(
31
- @collection, args
31
+ context.collection, args
32
32
  )
33
33
  ]
34
34
  ),
35
- search: QueryStringParser.parse_search(@collection, args),
35
+ search: QueryStringParser.parse_search(context.collection, args),
36
36
  search_extended: QueryStringParser.parse_search_extended(args),
37
- sort: QueryStringParser.parse_sort(@collection, args),
38
- segment: QueryStringParser.parse_segment(@collection, args)
37
+ sort: QueryStringParser.parse_sort(context.collection, args),
38
+ segment: QueryStringParser.parse_segment(context.collection, args)
39
39
  )
40
- projection = QueryStringParser.parse_projection(@collection, args)
40
+ projection = QueryStringParser.parse_projection(context.collection, args)
41
41
  filename = args[:params][:filename] || args[:params]['collection_name']
42
42
  filename += '.csv' unless /\.csv$/i.match?(filename)
43
43
  header = args[:params][:header]
@@ -47,7 +47,7 @@ module ForestAdminAgent
47
47
  filename_with_timestamp = filename.gsub('.csv', "_export_#{now}.csv")
48
48
 
49
49
  # Return streaming enumerator instead of full CSV string
50
- list_records = ->(batch_filter) { @collection.list(@caller, batch_filter, projection) }
50
+ list_records = ->(batch_filter) { context.collection.list(context.caller, batch_filter, projection) }
51
51
 
52
52
  {
53
53
  content: {
@@ -17,35 +17,36 @@ module ForestAdminAgent
17
17
  end
18
18
 
19
19
  def handle_request(args = {})
20
- build(args)
21
- @permissions.can?(:delete, @collection)
22
- primary_key_values = Utils::Id.unpack_id(@collection, args[:params]['id'], with_key: true)
23
- delete_records(args, { ids: [primary_key_values], are_excluded: false })
20
+ context = build(args)
21
+ context.permissions.can?(:delete, context.collection)
22
+ primary_key_values = Utils::Id.unpack_id(context.collection, args[:params]['id'], with_key: true)
23
+ delete_records(args, { ids: [primary_key_values], are_excluded: false }, context)
24
24
 
25
25
  { content: nil, status: 204 }
26
26
  end
27
27
 
28
28
  def handle_request_bulk(args = {})
29
- build(args)
30
- @permissions.can?(:delete, @collection)
31
- selection_ids = Utils::Id.parse_selection_ids(@collection, args[:params], with_key: true)
32
- delete_records(args, selection_ids)
29
+ context = build(args)
30
+ context.permissions.can?(:delete, context.collection)
31
+ selection_ids = Utils::Id.parse_selection_ids(context.collection, args[:params], with_key: true)
32
+ delete_records(args, selection_ids, context)
33
33
 
34
34
  { content: nil, status: 204 }
35
35
  end
36
36
 
37
- def delete_records(args, selection_ids)
38
- condition_tree_ids = ConditionTree::ConditionTreeFactory.match_records(@collection, selection_ids[:ids])
37
+ def delete_records(args, selection_ids, context)
38
+ condition_tree_ids = ConditionTree::ConditionTreeFactory.match_records(context.collection,
39
+ selection_ids[:ids])
39
40
  condition_tree_ids = condition_tree_ids.inverse if selection_ids[:are_excluded]
40
41
 
41
- @collection.schema[:fields].each_value do |field_schema|
42
+ context.collection.schema[:fields].each_value do |field_schema|
42
43
  next unless ['PolymorphicOneToOne', 'PolymorphicOneToMany'].include?(field_schema.type)
43
44
 
44
45
  origin_values = selection_ids[:ids].map do |pk_hash|
45
46
  if pk_hash.is_a?(Hash)
46
47
  pk_hash[field_schema.origin_key_target]
47
48
  else
48
- pk_names = ForestAdminDatasourceToolkit::Utils::Schema.primary_keys(@collection)
49
+ pk_names = ForestAdminDatasourceToolkit::Utils::Schema.primary_keys(context.collection)
49
50
  index = pk_names.index(field_schema.origin_key_target)
50
51
  pk_hash[index] if index
51
52
  end
@@ -56,26 +57,26 @@ module ForestAdminAgent
56
57
  [
57
58
  Nodes::ConditionTreeLeaf.new(field_schema.origin_key, Operators::IN, origin_values),
58
59
  Nodes::ConditionTreeLeaf.new(field_schema.origin_type_field, Operators::EQUAL,
59
- @collection.name.gsub('__', '::'))
60
+ context.collection.name.gsub('__', '::'))
60
61
  ]
61
62
  )
62
63
  filter = Filter.new(condition_tree: condition_tree)
63
- @datasource.get_collection(field_schema.foreign_collection)
64
- .update(@caller, filter, { field_schema.origin_key => nil,
65
- field_schema.origin_type_field => nil })
64
+ context.datasource.get_collection(field_schema.foreign_collection)
65
+ .update(context.caller, filter, { field_schema.origin_key => nil,
66
+ field_schema.origin_type_field => nil })
66
67
  end
67
68
 
68
69
  filter = ForestAdminDatasourceToolkit::Components::Query::Filter.new(
69
70
  condition_tree: ConditionTree::ConditionTreeFactory.intersect(
70
71
  [
71
- Utils::QueryStringParser.parse_condition_tree(@collection, args),
72
+ Utils::QueryStringParser.parse_condition_tree(context.collection, args),
72
73
  condition_tree_ids,
73
- @permissions.get_scope(@collection)
74
+ context.permissions.get_scope(context.collection)
74
75
  ]
75
76
  )
76
77
  )
77
78
 
78
- @collection.delete(@caller, filter)
79
+ context.collection.delete(context.caller, filter)
79
80
  end
80
81
  end
81
82
  end
@@ -15,45 +15,45 @@ module ForestAdminAgent
15
15
  end
16
16
 
17
17
  def handle_request(args = {})
18
- build(args)
19
- @permissions.can?(:browse, @collection)
18
+ context = build(args)
19
+ context.permissions.can?(:browse, context.collection)
20
20
 
21
21
  filter = ForestAdminDatasourceToolkit::Components::Query::Filter.new(
22
22
  condition_tree: ConditionTreeFactory.intersect(
23
23
  [
24
- @permissions.get_scope(@collection),
25
- QueryStringParser.parse_condition_tree(@collection, args),
26
- parse_query_segment(@collection, args, @permissions, @caller)
24
+ context.permissions.get_scope(context.collection),
25
+ QueryStringParser.parse_condition_tree(context.collection, args),
26
+ parse_query_segment(context.collection, args, context.permissions, context.caller)
27
27
  ]
28
28
  ),
29
29
  page: QueryStringParser.parse_pagination(args),
30
- search: QueryStringParser.parse_search(@collection, args),
30
+ search: QueryStringParser.parse_search(context.collection, args),
31
31
  search_extended: QueryStringParser.parse_search_extended(args),
32
- sort: QueryStringParser.parse_sort(@collection, args),
33
- segment: QueryStringParser.parse_segment(@collection, args)
32
+ sort: QueryStringParser.parse_sort(context.collection, args),
33
+ segment: QueryStringParser.parse_segment(context.collection, args)
34
34
  )
35
35
 
36
- projection = QueryStringParser.parse_projection_with_pks(@collection, args)
37
- records = @collection.list(@caller, filter, projection)
36
+ projection = QueryStringParser.parse_projection_with_pks(context.collection, args)
37
+ records = context.collection.list(context.caller, filter, projection)
38
38
 
39
39
  {
40
40
  name: args[:params]['collection_name'],
41
41
  content: JSONAPI::Serializer.serialize(
42
42
  records,
43
- class_name: @collection.name,
43
+ class_name: context.collection.name,
44
44
  is_collection: true,
45
45
  serializer: Serializer::ForestSerializer,
46
46
  include: projection.relations(only_keys: true),
47
- meta: handle_search_decorator(args[:params]['search'], records)
47
+ meta: handle_search_decorator(args[:params]['search'], records, context.collection)
48
48
  )
49
49
  }
50
50
  end
51
51
 
52
- def handle_search_decorator(search_value, records)
52
+ def handle_search_decorator(search_value, records, collection)
53
53
  decorator = { decorators: [] }
54
54
  unless search_value.nil?
55
55
  records.each_with_index do |entry, index|
56
- decorator[:decorators][index] = { id: Utils::Id.pack_id(@collection, entry), search: [] }
56
+ decorator[:decorators][index] = { id: Utils::Id.pack_id(collection, entry), search: [] }
57
57
  # attributes method is defined on ActiveRecord::Base model
58
58
  attributes = entry.respond_to?(:attributes) ? entry.attributes : entry
59
59
 
@@ -26,7 +26,7 @@ module ForestAdminAgent
26
26
  end
27
27
 
28
28
  def handle_request(args = {})
29
- build(args)
29
+ context = build(args)
30
30
  query = args[:params][:query].strip
31
31
 
32
32
  QueryValidator.valid?(query)
@@ -34,31 +34,31 @@ module ForestAdminAgent
34
34
  raise ForestAdminAgent::Http::Exceptions::UnprocessableError, 'Missing native query connection attribute'
35
35
  end
36
36
 
37
- @permissions.can_chart?(args[:params])
37
+ context.permissions.can_chart?(args[:params])
38
38
 
39
39
  query.gsub!('?', args[:params][:record_id].to_s) if args[:params][:record_id]
40
- self.type = args[:params][:type]
40
+ type = validate_and_get_type(args[:params][:type])
41
41
  result = execute_query(
42
- @datasource,
42
+ context.datasource,
43
43
  query,
44
44
  args[:params][:connectionName],
45
- @permissions,
46
- @caller,
45
+ context.permissions,
46
+ context.caller,
47
47
  args[:params][:contextVariables]
48
48
  )
49
49
 
50
- { content: Serializer::ForestChartSerializer.serialize(send(:"make_#{@type}", result)) }
50
+ { content: Serializer::ForestChartSerializer.serialize(send(:"make_#{type}", result)) }
51
51
  end
52
52
 
53
53
  private
54
54
 
55
- def type=(type)
55
+ def validate_and_get_type(type)
56
56
  chart_types = %w[Value Objective Pie Line Leaderboard]
57
57
  unless chart_types.include?(type)
58
58
  raise ForestAdminDatasourceToolkit::Exceptions::ForestException, "Invalid Chart type #{type}"
59
59
  end
60
60
 
61
- @type = type.downcase
61
+ type.downcase
62
62
  end
63
63
 
64
64
  def raise_error(result, key_names)
@@ -21,21 +21,21 @@ module ForestAdminAgent
21
21
  end
22
22
 
23
23
  def handle_request(args = {})
24
- build(args)
25
- @permissions.can?(:edit, @collection)
24
+ context = build(args)
25
+ context.permissions.can?(:edit, context.collection)
26
26
 
27
- parent_primary_key_values = Utils::Id.unpack_id(@collection, args[:params]['id'], with_key: true)
28
- target_primary_key_values = Utils::Id.unpack_id(@child_collection, args[:params]['data'][0]['id'],
27
+ parent_primary_key_values = Utils::Id.unpack_id(context.collection, args[:params]['id'], with_key: true)
28
+ target_primary_key_values = Utils::Id.unpack_id(context.child_collection, args[:params]['data'][0]['id'],
29
29
  with_key: true)
30
- relation = Schema.get_to_many_relation(@collection, args[:params]['relation_name'])
30
+ relation = Schema.get_to_many_relation(context.collection, args[:params]['relation_name'])
31
31
 
32
32
  case relation.type
33
33
  when 'OneToMany'
34
- associate_one_to_many(relation, parent_primary_key_values, target_primary_key_values)
34
+ associate_one_to_many(relation, parent_primary_key_values, target_primary_key_values, context)
35
35
  when 'ManyToMany'
36
- associate_many_to_many(relation, parent_primary_key_values, target_primary_key_values)
36
+ associate_many_to_many(relation, parent_primary_key_values, target_primary_key_values, context)
37
37
  when 'PolymorphicOneToMany'
38
- associate_polymorphic_one_to_many(relation, parent_primary_key_values, target_primary_key_values)
38
+ associate_polymorphic_one_to_many(relation, parent_primary_key_values, target_primary_key_values, context)
39
39
  end
40
40
 
41
41
  { content: nil, status: 204 }
@@ -43,52 +43,55 @@ module ForestAdminAgent
43
43
 
44
44
  private
45
45
 
46
- def associate_one_to_many(relation, parent_primary_key_values, target_primary_key_values)
47
- id = Schema.primary_keys(@child_collection)[0]
48
- value = Collection.get_value(@child_collection, @caller, target_primary_key_values, id)
46
+ def associate_one_to_many(relation, parent_primary_key_values, target_primary_key_values, context)
47
+ id = Schema.primary_keys(context.child_collection)[0]
48
+ value = Collection.get_value(context.child_collection, context.caller, target_primary_key_values, id)
49
49
  filter = Filter.new(
50
50
  condition_tree: ConditionTree::ConditionTreeFactory.intersect(
51
51
  [
52
52
  ConditionTree::Nodes::ConditionTreeLeaf.new(id, 'Equal', value),
53
- @permissions.get_scope(@collection)
53
+ context.permissions.get_scope(context.collection)
54
54
  ]
55
55
  )
56
56
  )
57
- value = Collection.get_value(@collection, @caller, parent_primary_key_values, relation.origin_key_target)
57
+ value = Collection.get_value(context.collection, context.caller, parent_primary_key_values,
58
+ relation.origin_key_target)
58
59
 
59
- @child_collection.update(@caller, filter, { relation.origin_key => value })
60
+ context.child_collection.update(context.caller, filter, { relation.origin_key => value })
60
61
  end
61
62
 
62
- def associate_polymorphic_one_to_many(relation, parent_primary_key_values, target_primary_key_values)
63
- id = Schema.primary_keys(@child_collection)[0]
64
- value = Collection.get_value(@child_collection, @caller, target_primary_key_values, id)
63
+ def associate_polymorphic_one_to_many(relation, parent_primary_key_values, target_primary_key_values, context)
64
+ id = Schema.primary_keys(context.child_collection)[0]
65
+ value = Collection.get_value(context.child_collection, context.caller, target_primary_key_values, id)
65
66
  filter = Filter.new(
66
67
  condition_tree: ConditionTree::ConditionTreeFactory.intersect(
67
68
  [
68
69
  ConditionTree::Nodes::ConditionTreeLeaf.new(id, 'Equal', value),
69
- @permissions.get_scope(@collection)
70
+ context.permissions.get_scope(context.collection)
70
71
  ]
71
72
  )
72
73
  )
73
74
 
74
- value = Collection.get_value(@collection, @caller, parent_primary_key_values, relation.origin_key_target)
75
+ value = Collection.get_value(context.collection, context.caller, parent_primary_key_values,
76
+ relation.origin_key_target)
75
77
 
76
- @child_collection.update(
77
- @caller,
78
+ context.child_collection.update(
79
+ context.caller,
78
80
  filter,
79
- { relation.origin_key => value, relation.origin_type_field => @collection.name.gsub('__', '::') }
81
+ { relation.origin_key => value, relation.origin_type_field => context.collection.name.gsub('__', '::') }
80
82
  )
81
83
  end
82
84
 
83
- def associate_many_to_many(relation, parent_primary_key_values, target_primary_key_values)
84
- id = Schema.primary_keys(@child_collection)[0]
85
- foreign_value = Collection.get_value(@child_collection, @caller, target_primary_key_values, id)
86
- id = Schema.primary_keys(@collection)[0]
87
- origin_value = Collection.get_value(@collection, @caller, parent_primary_key_values, id)
85
+ def associate_many_to_many(relation, parent_primary_key_values, target_primary_key_values, context)
86
+ id = Schema.primary_keys(context.child_collection)[0]
87
+ foreign_value = Collection.get_value(context.child_collection, context.caller, target_primary_key_values,
88
+ id)
89
+ id = Schema.primary_keys(context.collection)[0]
90
+ origin_value = Collection.get_value(context.collection, context.caller, parent_primary_key_values, id)
88
91
  record = { relation.origin_key => origin_value, relation.foreign_key => foreign_value }
89
92
 
90
- through_collection = @datasource.get_collection(relation.through_collection)
91
- through_collection.create(@caller, record)
93
+ through_collection = context.datasource.get_collection(relation.through_collection)
94
+ through_collection.create(context.caller, record)
92
95
  end
93
96
  end
94
97
  end
@@ -20,23 +20,23 @@ module ForestAdminAgent
20
20
  end
21
21
 
22
22
  def handle_request(args = {})
23
- build(args)
24
- @permissions.can?(:browse, @collection)
23
+ context = build(args)
24
+ context.permissions.can?(:browse, context.collection)
25
25
 
26
- if @child_collection.is_countable?
27
- filter = Filter.new(condition_tree: @permissions.get_scope(@collection))
28
- primary_key_values = Utils::Id.unpack_id(@collection, args[:params]['id'], with_key: true)
26
+ if context.child_collection.is_countable?
27
+ filter = Filter.new(condition_tree: context.permissions.get_scope(context.collection))
28
+ primary_key_values = Utils::Id.unpack_id(context.collection, args[:params]['id'], with_key: true)
29
29
  result = Collection.aggregate_relation(
30
- @collection,
30
+ context.collection,
31
31
  primary_key_values,
32
32
  args[:params]['relation_name'],
33
- @caller,
33
+ context.caller,
34
34
  filter,
35
35
  Aggregation.new(operation: 'Count')
36
36
  )
37
37
 
38
38
  return {
39
- name: @child_collection.name,
39
+ name: context.child_collection.name,
40
40
  content: {
41
41
  count: result.empty? ? 0 : result[0]['value']
42
42
  }
@@ -44,7 +44,7 @@ module ForestAdminAgent
44
44
  end
45
45
 
46
46
  {
47
- name: @child_collection.name,
47
+ name: context.child_collection.name,
48
48
  content: {
49
49
  count: 'deactivated'
50
50
  }
@@ -20,22 +20,23 @@ module ForestAdminAgent
20
20
  end
21
21
 
22
22
  def handle_request(args = {})
23
- build(args)
24
- @permissions.can?(:browse, @collection)
25
- @permissions.can?(:export, @collection)
23
+ context = build(args)
24
+ context.permissions.can?(:browse, context.collection)
25
+ context.permissions.can?(:export, context.collection)
26
26
 
27
27
  filter = ForestAdminDatasourceToolkit::Components::Query::Filter.new(
28
28
  condition_tree: ConditionTreeFactory.intersect(
29
29
  [
30
- @permissions.get_scope(@collection),
31
- ForestAdminAgent::Utils::QueryStringParser.parse_condition_tree(@child_collection, args)
30
+ context.permissions.get_scope(context.collection),
31
+ ForestAdminAgent::Utils::QueryStringParser.parse_condition_tree(context.child_collection, args)
32
32
  ]
33
33
  )
34
34
  )
35
- projection = ForestAdminAgent::Utils::QueryStringParser.parse_projection_with_pks(@child_collection, args)
35
+ projection = ForestAdminAgent::Utils::QueryStringParser.parse_projection_with_pks(context.child_collection,
36
+ args)
36
37
 
37
38
  # Get the parent record primary keys
38
- primary_key_values = Utils::Id.unpack_id(@collection, args[:params]['id'], with_key: true)
39
+ primary_key_values = Utils::Id.unpack_id(context.collection, args[:params]['id'], with_key: true)
39
40
  relation_name = args[:params]['relation_name']
40
41
 
41
42
  # Generate timestamp for filename
@@ -47,10 +48,10 @@ module ForestAdminAgent
47
48
  # Create a callable to fetch related records
48
49
  list_records = lambda do |batch_filter|
49
50
  ForestAdminDatasourceToolkit::Utils::Collection.list_relation(
50
- @collection,
51
+ context.collection,
51
52
  primary_key_values,
52
53
  relation_name,
53
- @caller,
54
+ context.caller,
54
55
  batch_filter,
55
56
  projection
56
57
  )
@@ -20,28 +20,33 @@ module ForestAdminAgent
20
20
  end
21
21
 
22
22
  def handle_request(args = {})
23
- build(args)
23
+ context = build(args)
24
24
 
25
- parent_primary_key_values = Utils::Id.unpack_id(@collection, args[:params]['id'], with_key: true)
25
+ parent_primary_key_values = Utils::Id.unpack_id(context.collection, args[:params]['id'], with_key: true)
26
26
  is_delete_mode = !args.dig(:params, :delete).nil?
27
27
 
28
28
  if is_delete_mode
29
- @permissions.can?(:delete, @child_collection)
29
+ context.permissions.can?(:delete, context.child_collection)
30
30
  else
31
- @permissions.can?(:edit, @collection)
31
+ context.permissions.can?(:edit, context.collection)
32
32
  end
33
33
 
34
- filter = get_base_foreign_filter(args)
35
- relation = Schema.get_to_many_relation(@collection, args[:params]['relation_name'])
34
+ filter = get_base_foreign_filter(args, context)
35
+ relation = Schema.get_to_many_relation(context.collection, args[:params]['relation_name'])
36
+
37
+ relation_name = args[:params]['relation_name']
38
+ options = {
39
+ relation: relation,
40
+ relation_name: relation_name,
41
+ parent_pk_values: parent_primary_key_values,
42
+ is_delete_mode: is_delete_mode,
43
+ filter: filter
44
+ }
36
45
 
37
46
  if ['OneToMany', 'PolymorphicOneToMany'].include?(relation.type)
38
- dissociate_or_delete_one_to_many(
39
- relation, args[:params]['relation_name'], parent_primary_key_values, is_delete_mode, filter
40
- )
47
+ dissociate_or_delete_one_to_many(options, context)
41
48
  else
42
- dissociate_or_delete_many_to_many(
43
- relation, args[:params]['relation_name'], parent_primary_key_values, is_delete_mode, filter
44
- )
49
+ dissociate_or_delete_many_to_many(options, context)
45
50
  end
46
51
 
47
52
  { content: nil, status: 204 }
@@ -49,51 +54,69 @@ module ForestAdminAgent
49
54
 
50
55
  private
51
56
 
52
- def dissociate_or_delete_one_to_many(relation, relation_name, parent_primary_key_values, is_delete_mode,
53
- filter)
54
- foreign_filter = FilterFactory.make_foreign_filter(@collection, parent_primary_key_values, relation_name,
55
- @caller, filter)
57
+ def dissociate_or_delete_one_to_many(options, context)
58
+ foreign_filter = FilterFactory.make_foreign_filter(
59
+ context.collection,
60
+ options[:parent_pk_values],
61
+ options[:relation_name],
62
+ context.caller,
63
+ options[:filter]
64
+ )
56
65
 
57
- if is_delete_mode
58
- @child_collection.delete(@caller, foreign_filter)
66
+ if options[:is_delete_mode]
67
+ context.child_collection.delete(context.caller, foreign_filter)
59
68
  else
60
- patch = if relation.type == 'PolymorphicOneToMany'
61
- { relation.origin_key => nil, relation.origin_type_field => nil }
69
+ patch = if options[:relation].type == 'PolymorphicOneToMany'
70
+ { options[:relation].origin_key => nil, options[:relation].origin_type_field => nil }
62
71
  else
63
- { relation.origin_key => nil }
72
+ { options[:relation].origin_key => nil }
64
73
  end
65
- @child_collection.update(@caller, foreign_filter, patch)
74
+ context.child_collection.update(context.caller, foreign_filter, patch)
66
75
  end
67
76
  end
68
77
 
69
- def dissociate_or_delete_many_to_many(relation, relation_name, parent_primary_key_values, is_delete_mode,
70
- filter)
71
- through_collection = @datasource.get_collection(relation.through_collection)
78
+ def dissociate_or_delete_many_to_many(options, context)
79
+ through_collection = context.datasource.get_collection(options[:relation].through_collection)
72
80
 
73
- if is_delete_mode
81
+ if options[:is_delete_mode]
74
82
  # Generate filters _BEFORE_ deleting stuff, otherwise things break.
75
- foreign_filter = FilterFactory.make_foreign_filter(@collection, parent_primary_key_values, relation_name,
76
- @caller, filter)
77
- through_filter = FilterFactory.make_through_filter(@collection, parent_primary_key_values, relation_name,
78
- @caller, filter)
83
+ foreign_filter = FilterFactory.make_foreign_filter(
84
+ context.collection,
85
+ options[:parent_pk_values],
86
+ options[:relation_name],
87
+ context.caller,
88
+ options[:filter]
89
+ )
90
+ through_filter = FilterFactory.make_through_filter(
91
+ context.collection,
92
+ options[:parent_pk_values],
93
+ options[:relation_name],
94
+ context.caller,
95
+ options[:filter]
96
+ )
79
97
 
80
98
  # Delete records from through collection
81
- through_collection.delete(@caller, through_filter)
99
+ through_collection.delete(context.caller, through_filter)
82
100
 
83
101
  # Let the datasource crash when:
84
102
  # - the records in the foreignCollection are linked to other records in the origin collection
85
103
  # - the underlying database/api is not cascading deletes
86
- @child_collection.delete(@caller, foreign_filter)
104
+ context.child_collection.delete(context.caller, foreign_filter)
87
105
  else
88
- through_filter = FilterFactory.make_through_filter(@collection, parent_primary_key_values, relation_name,
89
- @caller, filter)
90
- through_collection.delete(@caller, through_filter)
106
+ through_filter = FilterFactory.make_through_filter(
107
+ context.collection,
108
+ options[:parent_pk_values],
109
+ options[:relation_name],
110
+ context.caller,
111
+ options[:filter]
112
+ )
113
+ through_collection.delete(context.caller, through_filter)
91
114
  end
92
115
  end
93
116
 
94
- def get_base_foreign_filter(args)
95
- selection_ids = Utils::Id.parse_selection_ids(@child_collection, args[:params])
96
- selected_ids = ConditionTree::ConditionTreeFactory.match_ids(@child_collection, selection_ids[:ids])
117
+ def get_base_foreign_filter(args, context)
118
+ selection_ids = Utils::Id.parse_selection_ids(context.child_collection, args[:params])
119
+ selected_ids = ConditionTree::ConditionTreeFactory.match_ids(context.child_collection, selection_ids[:ids])
97
120
 
98
121
  selected_ids = selected_ids.inverse if selection_ids[:are_excluded]
99
122
 
@@ -104,8 +127,8 @@ module ForestAdminAgent
104
127
  Filter.new(
105
128
  condition_tree: ConditionTree::ConditionTreeFactory.intersect(
106
129
  [
107
- @permissions.get_scope(@child_collection),
108
- Utils::QueryStringParser.parse_condition_tree(@child_collection, args),
130
+ context.permissions.get_scope(context.child_collection),
131
+ Utils::QueryStringParser.parse_condition_tree(context.child_collection, args),
109
132
  selected_ids
110
133
  ]
111
134
  )
@@ -21,36 +21,37 @@ module ForestAdminAgent
21
21
  end
22
22
 
23
23
  def handle_request(args = {})
24
- build(args)
25
- @permissions.can?(:browse, @collection)
24
+ context = build(args)
25
+ context.permissions.can?(:browse, context.collection)
26
26
 
27
27
  filter = ForestAdminDatasourceToolkit::Components::Query::Filter.new(
28
28
  condition_tree: ConditionTreeFactory.intersect(
29
29
  [
30
- @permissions.get_scope(@collection),
31
- ForestAdminAgent::Utils::QueryStringParser.parse_condition_tree(@child_collection, args)
30
+ context.permissions.get_scope(context.collection),
31
+ ForestAdminAgent::Utils::QueryStringParser.parse_condition_tree(context.child_collection, args)
32
32
  ]
33
33
  ),
34
34
  page: ForestAdminAgent::Utils::QueryStringParser.parse_pagination(args),
35
- sort: ForestAdminAgent::Utils::QueryStringParser.parse_sort(@child_collection, args)
35
+ sort: ForestAdminAgent::Utils::QueryStringParser.parse_sort(context.child_collection, args)
36
36
  )
37
- projection = ForestAdminAgent::Utils::QueryStringParser.parse_projection_with_pks(@child_collection, args)
38
- primary_key_values = Utils::Id.unpack_id(@collection, args[:params]['id'], with_key: true)
37
+ projection = ForestAdminAgent::Utils::QueryStringParser.parse_projection_with_pks(context.child_collection,
38
+ args)
39
+ primary_key_values = Utils::Id.unpack_id(context.collection, args[:params]['id'], with_key: true)
39
40
  records = Collection.list_relation(
40
- @collection,
41
+ context.collection,
41
42
  primary_key_values,
42
43
  args[:params]['relation_name'],
43
- @caller,
44
+ context.caller,
44
45
  filter,
45
46
  projection
46
47
  )
47
48
 
48
49
  {
49
- name: @child_collection.name,
50
+ name: context.child_collection.name,
50
51
  content: JSONAPI::Serializer.serialize(
51
52
  records,
52
53
  is_collection: true,
53
- class_name: @child_collection.name,
54
+ class_name: context.child_collection.name,
54
55
  serializer: Serializer::ForestSerializer,
55
56
  include: projection.relations.keys
56
57
  )