activeadmin-graphql 0.2.0 → 0.3.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 +4 -4
- data/CHANGELOG.md +24 -0
- data/CODE_OF_CONDUCT.md +14 -19
- data/CONTRIBUTING.md +12 -16
- data/README.md +19 -2
- data/activeadmin-graphql.gemspec +11 -7
- data/app/controllers/active_admin/graphql_controller.rb +50 -8
- data/docs/graphql-api.md +36 -11
- data/lib/active_admin/graphql/integration.rb +22 -23
- data/lib/active_admin/graphql/mutation_execution_error.rb +16 -0
- data/lib/active_admin/graphql/mutation_input_config.rb +11 -0
- data/lib/active_admin/graphql/mutation_input_definition_dsl.rb +22 -0
- data/lib/active_admin/graphql/policy_set_cache.rb +64 -0
- data/lib/active_admin/graphql/resource_config.rb +21 -2
- data/lib/active_admin/graphql/resource_definition_dsl.rb +19 -0
- data/lib/active_admin/graphql/resource_methods.rb +55 -0
- data/lib/active_admin/graphql/resource_query_proxy.rb +20 -0
- data/lib/active_admin/graphql/run_action_payload.rb +2 -1
- data/lib/active_admin/graphql/schema_builder/graph_params.rb +2 -2
- data/lib/active_admin/graphql/schema_builder/mutation_create.rb +6 -2
- data/lib/active_admin/graphql/schema_builder/mutation_update_destroy.rb +19 -9
- data/lib/active_admin/graphql/schema_builder/query_type_policies.rb +17 -5
- data/lib/active_admin/graphql/schema_builder/types_inputs.rb +24 -4
- data/lib/active_admin/graphql/schema_builder/types_object.rb +5 -2
- data/lib/active_admin/graphql/schema_builder/wire.rb +11 -1
- data/lib/active_admin/graphql/version.rb +1 -1
- data/lib/active_admin/graphql.rb +9 -1
- data/sig/active_admin/graphql.rbs +7 -0
- metadata +89 -35
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
require_relative "run_action_mutation_config"
|
|
4
|
+
require_relative "mutation_input_config"
|
|
4
5
|
|
|
5
6
|
module ActiveAdmin
|
|
6
7
|
module GraphQL
|
|
@@ -10,14 +11,16 @@ module ActiveAdmin
|
|
|
10
11
|
attr_accessor :graphql_type_name
|
|
11
12
|
attr_accessor :only_attributes
|
|
12
13
|
attr_accessor :exclude_attributes
|
|
14
|
+
attr_accessor :permit_params_attributes
|
|
15
|
+
attr_accessor :html_permit_params_attributes
|
|
13
16
|
attr_accessor :extension_block
|
|
14
17
|
|
|
15
18
|
# Optional resolver overrides (set from +graphql do+). SchemaBuilder still owns field names,
|
|
16
19
|
# arguments, and types; procs replace only the Ruby resolution body.
|
|
17
20
|
attr_accessor :resolve_index_proc
|
|
18
21
|
attr_accessor :resolve_show_proc
|
|
19
|
-
|
|
20
|
-
|
|
22
|
+
attr_writer :resolve_create_proc
|
|
23
|
+
attr_writer :resolve_update_proc
|
|
21
24
|
attr_accessor :resolve_destroy_proc
|
|
22
25
|
|
|
23
26
|
# Default return type for run-action mutations (+batch+, +member+, +collection+) when a kind-specific
|
|
@@ -33,6 +36,22 @@ module ActiveAdmin
|
|
|
33
36
|
!enabled
|
|
34
37
|
end
|
|
35
38
|
|
|
39
|
+
def create_input
|
|
40
|
+
@create_input ||= MutationInputConfig.new
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
def update_input
|
|
44
|
+
@update_input ||= MutationInputConfig.new
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
def resolve_create_proc
|
|
48
|
+
@resolve_create_proc || create_input.resolve_proc
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
def resolve_update_proc
|
|
52
|
+
@resolve_update_proc || update_input.resolve_proc
|
|
53
|
+
end
|
|
54
|
+
|
|
36
55
|
def batch_run_action
|
|
37
56
|
@batch_run_action ||= RunActionMutationConfig.new
|
|
38
57
|
end
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
require_relative "run_action_mutation_config"
|
|
4
4
|
require_relative "run_action_mutation_dsl"
|
|
5
|
+
require_relative "mutation_input_definition_dsl"
|
|
5
6
|
|
|
6
7
|
module ActiveAdmin
|
|
7
8
|
module GraphQL
|
|
@@ -18,6 +19,7 @@ module ActiveAdmin
|
|
|
18
19
|
def type_name(name)
|
|
19
20
|
@config.graphql_type_name = name.to_s
|
|
20
21
|
end
|
|
22
|
+
alias_method :graphql_name, :type_name
|
|
21
23
|
|
|
22
24
|
def only(*attrs)
|
|
23
25
|
@config.only_attributes = attrs.flatten.map(&:to_sym)
|
|
@@ -28,6 +30,23 @@ module ActiveAdmin
|
|
|
28
30
|
end
|
|
29
31
|
alias_method :exclude, :except
|
|
30
32
|
|
|
33
|
+
def permit_params(*attrs)
|
|
34
|
+
@config.permit_params_attributes = attrs.flatten.map(&:to_sym)
|
|
35
|
+
end
|
|
36
|
+
alias_method :permit, :permit_params
|
|
37
|
+
|
|
38
|
+
def create(&block)
|
|
39
|
+
return unless block
|
|
40
|
+
|
|
41
|
+
MutationInputDefinitionDSL.new(@config.create_input).instance_exec(&block)
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
def update(&block)
|
|
45
|
+
return unless block
|
|
46
|
+
|
|
47
|
+
MutationInputDefinitionDSL.new(@config.update_input).instance_exec(&block)
|
|
48
|
+
end
|
|
49
|
+
|
|
31
50
|
def configure(&block)
|
|
32
51
|
@config.extension_block = block
|
|
33
52
|
end
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module ActiveAdmin
|
|
4
|
+
module GraphQL
|
|
5
|
+
module Integration
|
|
6
|
+
module ResourceMethods
|
|
7
|
+
SERVER_OWNED_TIMESTAMP_COLUMNS = %w[created_at updated_at].freeze
|
|
8
|
+
|
|
9
|
+
def graphql_config
|
|
10
|
+
@graphql_config ||= ActiveAdmin::GraphQL::ResourceConfig.new
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def attributes_for_graphql
|
|
14
|
+
keys = resource_attributes.keys
|
|
15
|
+
cfg = graphql_config
|
|
16
|
+
if cfg.only_attributes
|
|
17
|
+
keys &= cfg.only_attributes
|
|
18
|
+
end
|
|
19
|
+
keys -= cfg.exclude_attributes
|
|
20
|
+
keys
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def graphql_assignable_attribute_names
|
|
24
|
+
names = attributes_for_graphql.map(&:to_s)
|
|
25
|
+
pk_cols = ActiveAdmin::PrimaryKey.columns(resource_class)
|
|
26
|
+
return names if pk_cols.size > 1
|
|
27
|
+
|
|
28
|
+
names - pk_cols
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def graphql_create_attribute_names
|
|
32
|
+
mutation_permit_params_names(
|
|
33
|
+
graphql_config.create_input.permit_params_attributes || graphql_config.permit_params_attributes
|
|
34
|
+
)
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
def graphql_update_attribute_names
|
|
38
|
+
mutation_permit_params_names(
|
|
39
|
+
graphql_config.update_input.permit_params_attributes || graphql_config.permit_params_attributes
|
|
40
|
+
)
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
private
|
|
44
|
+
|
|
45
|
+
def mutation_permit_params_names(permit_list)
|
|
46
|
+
names = graphql_assignable_attribute_names.map(&:to_s)
|
|
47
|
+
permit_list = graphql_config.html_permit_params_attributes if permit_list.nil?
|
|
48
|
+
return names - SERVER_OWNED_TIMESTAMP_COLUMNS if permit_list.nil?
|
|
49
|
+
|
|
50
|
+
names & permit_list.map(&:to_s)
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
end
|
|
55
|
+
end
|
|
@@ -27,6 +27,26 @@ module ActiveAdmin
|
|
|
27
27
|
def find_member(id)
|
|
28
28
|
extra = member_route_params_for_find(id)
|
|
29
29
|
controller_for("show", extra).send(:find_resource)
|
|
30
|
+
rescue ActiveRecord::RecordNotFound
|
|
31
|
+
nil
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def find_members(ids)
|
|
35
|
+
string_ids = Array(ids).map(&:to_s).uniq
|
|
36
|
+
return {} if string_ids.empty?
|
|
37
|
+
|
|
38
|
+
model = @aa_resource.resource_class
|
|
39
|
+
if ActiveAdmin::PrimaryKey.composite?(model)
|
|
40
|
+
return string_ids.index_with { |identifier| find_member(identifier) }
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
controller = controller_for("index")
|
|
44
|
+
relation = controller.send(:apply_authorization_scope, controller.send(:scoped_collection))
|
|
45
|
+
primary_key = model.primary_key.to_sym
|
|
46
|
+
indexed = relation.where(primary_key => string_ids).index_by do |record|
|
|
47
|
+
record.public_send(primary_key).to_s
|
|
48
|
+
end
|
|
49
|
+
string_ids.index_with { |identifier| indexed[identifier] }
|
|
30
50
|
end
|
|
31
51
|
|
|
32
52
|
def build_new(attributes)
|
|
@@ -21,7 +21,8 @@ module ActiveAdmin
|
|
|
21
21
|
field :body, ::GraphQL::Types::String, null: true,
|
|
22
22
|
description: "Response body text when the action rendered (e.g. JSON)."
|
|
23
23
|
|
|
24
|
-
|
|
24
|
+
# keyword_init required for Ruby 3.2 consumers; cop targets 3.4 default Struct behavior
|
|
25
|
+
Result = Struct.new(:ok, :status, :location, :body, keyword_init: true) # rubocop:disable Style/RedundantStructKeywordInit
|
|
25
26
|
end
|
|
26
27
|
end
|
|
27
28
|
end
|
|
@@ -28,9 +28,9 @@ module ActiveAdmin
|
|
|
28
28
|
h
|
|
29
29
|
end
|
|
30
30
|
|
|
31
|
-
def assignable_slice_from_input(aa_res, input)
|
|
31
|
+
def assignable_slice_from_input(aa_res, input, attribute_names: nil)
|
|
32
32
|
blob = input.to_h.stringify_keys
|
|
33
|
-
names = aa_res.graphql_assignable_attribute_names.map(&:to_s)
|
|
33
|
+
names = (attribute_names || aa_res.graphql_assignable_attribute_names).map(&:to_s)
|
|
34
34
|
if (btc = aa_res.belongs_to_config)
|
|
35
35
|
names -= [btc.to_param.to_s]
|
|
36
36
|
end
|
|
@@ -29,7 +29,11 @@ module ActiveAdmin
|
|
|
29
29
|
namespace: ns,
|
|
30
30
|
graph_params: sb.graph_params_from_input(aa_res, input)
|
|
31
31
|
)
|
|
32
|
-
attrs = sb.assignable_slice_from_input(
|
|
32
|
+
attrs = sb.assignable_slice_from_input(
|
|
33
|
+
aa_res,
|
|
34
|
+
input,
|
|
35
|
+
attribute_names: aa_res.graphql_create_attribute_names
|
|
36
|
+
)
|
|
33
37
|
record = if (hook = aa_res.graphql_config.resolve_create_proc)
|
|
34
38
|
hook.call(
|
|
35
39
|
proxy: proxy,
|
|
@@ -46,7 +50,7 @@ module ActiveAdmin
|
|
|
46
50
|
end
|
|
47
51
|
|
|
48
52
|
unless r.save
|
|
49
|
-
raise
|
|
53
|
+
raise MutationExecutionError.validation(r)
|
|
50
54
|
end
|
|
51
55
|
r
|
|
52
56
|
end
|
|
@@ -42,7 +42,11 @@ module ActiveAdmin
|
|
|
42
42
|
raise ::GraphQL::ExecutionError, "not authorized to update this record"
|
|
43
43
|
end
|
|
44
44
|
|
|
45
|
-
attrs = sb.assignable_slice_from_input(
|
|
45
|
+
attrs = sb.assignable_slice_from_input(
|
|
46
|
+
aa_res,
|
|
47
|
+
input,
|
|
48
|
+
attribute_names: aa_res.graphql_update_attribute_names
|
|
49
|
+
)
|
|
46
50
|
record = if (hook = aa_res.graphql_config.resolve_update_proc)
|
|
47
51
|
hook.call(
|
|
48
52
|
proxy: proxy,
|
|
@@ -54,9 +58,9 @@ module ActiveAdmin
|
|
|
54
58
|
aa_resource: aa_res
|
|
55
59
|
)
|
|
56
60
|
else
|
|
57
|
-
attrs = attrs.stringify_keys.slice(*aa_res.
|
|
61
|
+
attrs = attrs.stringify_keys.slice(*aa_res.graphql_update_attribute_names)
|
|
58
62
|
unless record.update(attrs)
|
|
59
|
-
raise
|
|
63
|
+
raise MutationExecutionError.validation(record)
|
|
60
64
|
end
|
|
61
65
|
record
|
|
62
66
|
end
|
|
@@ -66,17 +70,22 @@ module ActiveAdmin
|
|
|
66
70
|
end
|
|
67
71
|
|
|
68
72
|
def mutation_destroy_field(sb, ns, aa_res, model)
|
|
69
|
-
|
|
73
|
+
stem = aa_res.resource_name.route_key.singularize.tr("-", "_")
|
|
74
|
+
delete_name = "delete_#{stem}"
|
|
75
|
+
destroy_name = "destroy_#{stem}"
|
|
70
76
|
find_type = @find_input_types[model]
|
|
77
|
+
type_basename = sb.send(:graphql_type_name_for, aa_res)
|
|
71
78
|
|
|
72
79
|
proc do
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
80
|
+
[delete_name, destroy_name].each do |fname|
|
|
81
|
+
field fname.to_sym, ::GraphQL::Types::Boolean, null: false, camelize: false,
|
|
82
|
+
visibility: {kind: :mutation_delete, graphql_type_name: type_basename, resource: aa_res},
|
|
83
|
+
description: "Destroy #{model.name}" do
|
|
84
|
+
argument :where, find_type, required: true, camelize: false
|
|
85
|
+
end
|
|
77
86
|
end
|
|
78
87
|
|
|
79
|
-
define_method(
|
|
88
|
+
define_method(delete_name.to_sym) do |where:, **|
|
|
80
89
|
auth = context[:auth]
|
|
81
90
|
blob = where.to_h.stringify_keys
|
|
82
91
|
graph = sb.graph_params_from_find_blob(aa_res, blob)
|
|
@@ -112,6 +121,7 @@ module ActiveAdmin
|
|
|
112
121
|
end
|
|
113
122
|
true
|
|
114
123
|
end
|
|
124
|
+
alias_method destroy_name.to_sym, delete_name.to_sym
|
|
115
125
|
end
|
|
116
126
|
end
|
|
117
127
|
end
|
|
@@ -48,17 +48,24 @@ module ActiveAdmin
|
|
|
48
48
|
end
|
|
49
49
|
|
|
50
50
|
define_method(:activeadmin_policies) do
|
|
51
|
-
auth = context[:auth]
|
|
52
51
|
resources = builder.send(:active_resources).map do |aa_res|
|
|
53
52
|
{
|
|
54
53
|
type_name: builder.send(:graphql_type_name_for, aa_res),
|
|
55
|
-
activeadmin_policies:
|
|
54
|
+
activeadmin_policies: ActiveAdmin::GraphQL::PolicySetCache.fetch(
|
|
55
|
+
context,
|
|
56
|
+
subject_owner: aa_res,
|
|
57
|
+
subject: aa_res.resource_class
|
|
58
|
+
)
|
|
56
59
|
}
|
|
57
60
|
end
|
|
58
61
|
pages = ns.resources.select { |r| r.is_a?(ActiveAdmin::Page) }.map do |page|
|
|
59
62
|
{
|
|
60
63
|
name: page.name,
|
|
61
|
-
activeadmin_policies:
|
|
64
|
+
activeadmin_policies: ActiveAdmin::GraphQL::PolicySetCache.fetch(
|
|
65
|
+
context,
|
|
66
|
+
subject_owner: page,
|
|
67
|
+
subject: page
|
|
68
|
+
)
|
|
62
69
|
}
|
|
63
70
|
end
|
|
64
71
|
{resources: resources, pages: pages}
|
|
@@ -75,13 +82,18 @@ module ActiveAdmin
|
|
|
75
82
|
graph_params: KeyValuePairs.to_hash(path)
|
|
76
83
|
)
|
|
77
84
|
|
|
85
|
+
records_by_id = proxy.find_members(ids.map(&:to_s))
|
|
78
86
|
ids.map do |id|
|
|
79
|
-
record =
|
|
87
|
+
record = records_by_id[id.to_s]
|
|
80
88
|
raise ::GraphQL::ExecutionError, "not found" unless record
|
|
81
89
|
|
|
82
90
|
{
|
|
83
91
|
id: id.to_s,
|
|
84
|
-
activeadmin_policies:
|
|
92
|
+
activeadmin_policies: ActiveAdmin::GraphQL::PolicySetCache.fetch(
|
|
93
|
+
context,
|
|
94
|
+
subject_owner: aa_res,
|
|
95
|
+
subject: record
|
|
96
|
+
)
|
|
85
97
|
}
|
|
86
98
|
end
|
|
87
99
|
end
|
|
@@ -6,10 +6,16 @@ module ActiveAdmin
|
|
|
6
6
|
module TypesInputs
|
|
7
7
|
private
|
|
8
8
|
|
|
9
|
-
def
|
|
9
|
+
def mark_empty_input_object!(input_class)
|
|
10
|
+
return if input_class.any_arguments?
|
|
11
|
+
|
|
12
|
+
input_class.has_no_arguments(true)
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def define_input_assignable_arguments!(input_class, aa_res, required:, attribute_names:)
|
|
10
16
|
model = aa_res.resource_class
|
|
11
17
|
cols_by_name = model.columns.index_by(&:name)
|
|
12
|
-
gassign =
|
|
18
|
+
gassign = attribute_names.map(&:to_s)
|
|
13
19
|
if (btc = aa_res.belongs_to_config)
|
|
14
20
|
gassign -= [btc.to_param.to_s]
|
|
15
21
|
end
|
|
@@ -33,12 +39,19 @@ module ActiveAdmin
|
|
|
33
39
|
graphql_name "#{gname}CreateInput"
|
|
34
40
|
description "Attributes (and nested route params) for creating #{model.name}"
|
|
35
41
|
|
|
36
|
-
builder.send(
|
|
42
|
+
builder.send(
|
|
43
|
+
:define_input_assignable_arguments!,
|
|
44
|
+
self,
|
|
45
|
+
aa_res,
|
|
46
|
+
required: false,
|
|
47
|
+
attribute_names: aa_res.graphql_create_attribute_names
|
|
48
|
+
)
|
|
37
49
|
|
|
38
50
|
if btc
|
|
39
51
|
argument btc.to_param.to_sym, ::GraphQL::Types::ID, required: btc.required?, camelize: false
|
|
40
52
|
end
|
|
41
53
|
end
|
|
54
|
+
mark_empty_input_object!(klass)
|
|
42
55
|
attach_input_object_visibility!(klass, "#{gname}CreateInput", aa_res, :create_input)
|
|
43
56
|
klass
|
|
44
57
|
end
|
|
@@ -53,12 +66,19 @@ module ActiveAdmin
|
|
|
53
66
|
graphql_name "#{gname}UpdateInput"
|
|
54
67
|
description "Partial attributes (and nested route params) for updating #{model.name}"
|
|
55
68
|
|
|
56
|
-
builder.send(
|
|
69
|
+
builder.send(
|
|
70
|
+
:define_input_assignable_arguments!,
|
|
71
|
+
self,
|
|
72
|
+
aa_res,
|
|
73
|
+
required: false,
|
|
74
|
+
attribute_names: aa_res.graphql_update_attribute_names
|
|
75
|
+
)
|
|
57
76
|
|
|
58
77
|
if btc
|
|
59
78
|
argument btc.to_param.to_sym, ::GraphQL::Types::ID, required: false, camelize: false
|
|
60
79
|
end
|
|
61
80
|
end
|
|
81
|
+
mark_empty_input_object!(klass)
|
|
62
82
|
attach_input_object_visibility!(klass, "#{gname}UpdateInput", aa_res, :update_input)
|
|
63
83
|
klass
|
|
64
84
|
end
|
|
@@ -101,8 +101,11 @@ module ActiveAdmin
|
|
|
101
101
|
|
|
102
102
|
type_class.field :activeadmin_policies, policy_set_type, null: false, camelize: false, authorize: false
|
|
103
103
|
type_class.define_method(:activeadmin_policies) do
|
|
104
|
-
|
|
105
|
-
|
|
104
|
+
ActiveAdmin::GraphQL::PolicySetCache.fetch(
|
|
105
|
+
context,
|
|
106
|
+
subject_owner: aa_res,
|
|
107
|
+
subject: object
|
|
108
|
+
)
|
|
106
109
|
end
|
|
107
110
|
|
|
108
111
|
if (ext = aa_res.graphql_config.extension_block)
|
|
@@ -14,6 +14,7 @@ module ActiveAdmin
|
|
|
14
14
|
model.reflect_on_all_associations(:belongs_to).each do |ref|
|
|
15
15
|
next if ref.polymorphic?
|
|
16
16
|
target = ref.klass
|
|
17
|
+
target_aa_res = @aa_by_model[target]
|
|
17
18
|
next unless @object_types[target]
|
|
18
19
|
|
|
19
20
|
field_name = ref.name.to_sym
|
|
@@ -25,7 +26,16 @@ module ActiveAdmin
|
|
|
25
26
|
fk_val = object.public_send(fk)
|
|
26
27
|
next nil if fk_val.nil?
|
|
27
28
|
|
|
28
|
-
dataloader.with(ActiveAdmin::GraphQL::RecordSource, target).load(fk_val)
|
|
29
|
+
record = dataloader.with(ActiveAdmin::GraphQL::RecordSource, target).load(fk_val)
|
|
30
|
+
next nil unless record
|
|
31
|
+
|
|
32
|
+
auth = context[:auth]
|
|
33
|
+
if target_aa_res && auth &&
|
|
34
|
+
!auth.authorized?(target_aa_res, ActiveAdmin::Authorization::READ, record)
|
|
35
|
+
next nil
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
record
|
|
29
39
|
end
|
|
30
40
|
end
|
|
31
41
|
end
|
data/lib/active_admin/graphql.rb
CHANGED
|
@@ -14,6 +14,7 @@ module ActiveAdmin
|
|
|
14
14
|
#
|
|
15
15
|
module GraphQL
|
|
16
16
|
SCHEMA_CACHE = {}
|
|
17
|
+
SCHEMA_CACHE_MUTEX = Mutex.new
|
|
17
18
|
end
|
|
18
19
|
end
|
|
19
20
|
|
|
@@ -41,7 +42,12 @@ module ActiveAdmin
|
|
|
41
42
|
# when admin registrations change without a full unload.
|
|
42
43
|
def schema_for(namespace)
|
|
43
44
|
cache_key = namespace.name
|
|
44
|
-
SCHEMA_CACHE[cache_key]
|
|
45
|
+
cached = SCHEMA_CACHE[cache_key]
|
|
46
|
+
return cached if cached
|
|
47
|
+
|
|
48
|
+
SCHEMA_CACHE_MUTEX.synchronize do
|
|
49
|
+
SCHEMA_CACHE[cache_key] ||= SchemaBuilder.new(namespace).build
|
|
50
|
+
end
|
|
45
51
|
end
|
|
46
52
|
|
|
47
53
|
def clear_schema_cache!
|
|
@@ -70,6 +76,8 @@ module ActiveAdmin
|
|
|
70
76
|
graphql/run_action_mutation_config
|
|
71
77
|
graphql/run_action_mutation_dsl
|
|
72
78
|
graphql/key_value_pair_input
|
|
79
|
+
graphql/policy_set_cache
|
|
80
|
+
graphql/mutation_execution_error
|
|
73
81
|
graphql/schema_builder
|
|
74
82
|
].each { |path| require_relative path }
|
|
75
83
|
end
|