ibrain-core 0.4.6 → 0.4.7

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 (86) hide show
  1. checksums.yaml +4 -4
  2. data/app/controllers/ibrain/base_controller.rb +14 -12
  3. data/app/controllers/ibrain/core/graphql_controller.rb +83 -79
  4. data/app/graphql/ibrain/base_schema.rb +52 -50
  5. data/app/graphql/ibrain/extentions/default_value.rb +11 -7
  6. data/app/graphql/ibrain/extentions/roles.rb +20 -15
  7. data/app/graphql/ibrain/extentions/session_required.rb +14 -10
  8. data/app/graphql/ibrain/lazy/base.rb +6 -2
  9. data/app/graphql/ibrain/loaders/association_loader.rb +55 -51
  10. data/app/graphql/ibrain/mutations/base_mutation.rb +56 -52
  11. data/app/graphql/ibrain/policies/base_policy.rb +47 -43
  12. data/app/graphql/ibrain/policies/graphql_policy.rb +6 -2
  13. data/app/graphql/ibrain/resolvers/base_aggregate.rb +10 -6
  14. data/app/graphql/ibrain/resolvers/base_resolver.rb +12 -8
  15. data/app/graphql/ibrain/types/aggregate_type.rb +8 -4
  16. data/app/graphql/ibrain/types/attribute_type.rb +5 -2
  17. data/app/graphql/ibrain/types/base_api_connection.rb +10 -6
  18. data/app/graphql/ibrain/types/base_api_edge.rb +8 -4
  19. data/app/graphql/ibrain/types/base_api_field.rb +11 -7
  20. data/app/graphql/ibrain/types/base_api_object.rb +10 -6
  21. data/app/graphql/ibrain/types/base_argument.rb +7 -3
  22. data/app/graphql/ibrain/types/base_connection.rb +11 -7
  23. data/app/graphql/ibrain/types/base_edge.rb +7 -3
  24. data/app/graphql/ibrain/types/base_enum.rb +5 -1
  25. data/app/graphql/ibrain/types/base_field.rb +10 -6
  26. data/app/graphql/ibrain/types/base_input_object.rb +10 -6
  27. data/app/graphql/ibrain/types/base_interface.rb +9 -5
  28. data/app/graphql/ibrain/types/base_object.rb +16 -12
  29. data/app/graphql/ibrain/types/base_scalar.rb +5 -1
  30. data/app/graphql/ibrain/types/base_type.rb +10 -4
  31. data/app/graphql/ibrain/types/base_union.rb +7 -3
  32. data/app/graphql/ibrain/types/filter_type.rb +5 -1
  33. data/app/graphql/ibrain/types/node_type.rb +8 -4
  34. data/app/graphql/ibrain/util/field_combiner.rb +9 -5
  35. data/app/graphql/ibrain/util/query_combiner.rb +8 -4
  36. data/app/models/concerns/ibrain/soft_deletable.rb +8 -6
  37. data/app/models/concerns/ibrain/user_api_authentication.rb +16 -14
  38. data/app/models/concerns/ibrain/user_methods.rb +13 -11
  39. data/app/models/ibrain/ability.rb +32 -31
  40. data/app/models/ibrain/aggregate.rb +7 -5
  41. data/app/models/ibrain/application_record.rb +4 -2
  42. data/app/models/ibrain/legacy_user.rb +13 -7
  43. data/app/models/ibrain/role.rb +8 -6
  44. data/app/models/ibrain/role_user.rb +10 -8
  45. data/app/repositories/ibrain/base_repository.rb +11 -9
  46. data/lib/generators/ibrain/core/model_generator.rb +21 -17
  47. data/lib/generators/ibrain/graphql/core.rb +59 -55
  48. data/lib/generators/ibrain/graphql/mutation_generator.rb +66 -58
  49. data/lib/generators/ibrain/graphql/object_generator.rb +70 -58
  50. data/lib/generators/ibrain/graphql/resolver_generator.rb +25 -17
  51. data/lib/generators/ibrain/graphql/resolvers_generator.rb +67 -59
  52. data/lib/generators/ibrain/graphql/templates/aggregate.erb +7 -5
  53. data/lib/generators/ibrain/graphql/templates/input.erb +9 -5
  54. data/lib/generators/ibrain/graphql/templates/mutation.erb +26 -24
  55. data/lib/generators/ibrain/graphql/templates/object.erb +10 -6
  56. data/lib/generators/ibrain/graphql/templates/resolver.erb +11 -9
  57. data/lib/generators/ibrain/graphql/templates/resolvers.erb +10 -8
  58. data/lib/generators/ibrain/graphql/type_generator.rb +88 -84
  59. data/lib/generators/ibrain/install/install_generator.rb +140 -137
  60. data/lib/generators/ibrain/install/templates/graphql/types/mutation_type.rb.tt +15 -13
  61. data/lib/generators/ibrain/install/templates/graphql/types/query_type.rb.tt +13 -11
  62. data/lib/generators/ibrain/install/templates/rubocop.yml.tt +30 -83
  63. data/lib/ibrain/app_configuration.rb +36 -34
  64. data/lib/ibrain/core/class_constantizer.rb +33 -30
  65. data/lib/ibrain/core/controller_helpers/auth.rb +59 -53
  66. data/lib/ibrain/core/controller_helpers/current_host.rb +11 -5
  67. data/lib/ibrain/core/controller_helpers/response.rb +49 -43
  68. data/lib/ibrain/core/controller_helpers/strong_parameters.rb +15 -9
  69. data/lib/ibrain/core/engine.rb +9 -5
  70. data/lib/ibrain/core/environment.rb +9 -5
  71. data/lib/ibrain/core/environment_extension.rb +17 -13
  72. data/lib/ibrain/core/role_configuration.rb +54 -52
  73. data/lib/ibrain/core/validators/email.rb +17 -15
  74. data/lib/ibrain/core/version.rb +2 -2
  75. data/lib/ibrain/core/versioned_value.rb +65 -61
  76. data/lib/ibrain/encryptor.rb +20 -18
  77. data/lib/ibrain/logger.rb +15 -13
  78. data/lib/ibrain/permission_sets/base.rb +26 -22
  79. data/lib/ibrain/permission_sets/super_user.rb +7 -3
  80. data/lib/ibrain/permitted_attributes.rb +20 -18
  81. data/lib/ibrain/preferences/configuration.rb +137 -135
  82. data/lib/ibrain/preferences/preferable.rb +162 -158
  83. data/lib/ibrain/preferences/preferable_class_methods.rb +114 -112
  84. data/lib/ibrain/user_class_handle.rb +24 -22
  85. data/lib/ibrain_core.rb +1 -7
  86. metadata +1 -1
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: bc329cadb1dbc83c7e0ea6e2a2e9f4eb6ef1ad3b74c8955e0f8ebb376ab329f2
4
- data.tar.gz: 7371a38a6e0b9f531851e4b5ddf046a8e245fcd540211e1b3d51ce3a3dabb1be
3
+ metadata.gz: '09278662f5dace559b2b93ed9a45f39ef9ca822643b31e0e50b44e923e1027dc'
4
+ data.tar.gz: 8f19875c9383f8235aaf53596978f7ab0fb568924a312d018e867fe5b4ae2957
5
5
  SHA512:
6
- metadata.gz: d69016d5aa23c6d5ea594298713db38c410087c56d3d7700302289ecd7e8bfa1d1db0eea2577cabf39036c37c9816f91a2e3f452cbb24161321d2f95f7af6be8
7
- data.tar.gz: 3b1a1bf408ee1ce1ba4d53fcbd0d41042dddd45fd45854cd9cefa93c5b2e6e8ff6317e8153309fbf94a0d3ef929b7424187593a8535cc05e12d42dbdab224a13
6
+ metadata.gz: b68fc74e862182d9295200edb26eced011eccd9f7e6b93b994a8392127a9ecb29e1a4e26405238ce4e450e76b1b86ccbf54a5c3f334752fdae6a04999dc708a2
7
+ data.tar.gz: 31d6e746ca29c99508950469e01e36b98279098cd7d6b97220a1a77de568c0e10da90fa9b0d877fa16375d48852e386f2b25db7f80b1aeb02b2bb60266402de7
@@ -1,18 +1,20 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- class Ibrain::BaseController < Ibrain::Config.parent_controller.constantize
4
- include ActionController::Helpers
5
- include Ibrain::Core::ControllerHelpers::Response
6
- include Ibrain::Core::ControllerHelpers::StrongParameters
7
- include Ibrain::Core::ControllerHelpers::CurrentHost
8
- include Ibrain::Core::ControllerHelpers::Auth
3
+ module Ibrain
4
+ class BaseController < Ibrain::Config.parent_controller.constantize
5
+ include ActionController::Helpers
6
+ include Ibrain::Core::ControllerHelpers::Response
7
+ include Ibrain::Core::ControllerHelpers::StrongParameters
8
+ include Ibrain::Core::ControllerHelpers::CurrentHost
9
+ include Ibrain::Core::ControllerHelpers::Auth
9
10
 
10
- include IbrainErrors
11
- include IbrainHandler
11
+ include IbrainErrors
12
+ include IbrainHandler
12
13
 
13
- protected
14
+ protected
14
15
 
15
- def cryptor
16
- Ibrain::Encryptor.new
16
+ def cryptor
17
+ Ibrain::Encryptor.new
18
+ end
17
19
  end
18
- end
20
+ end
@@ -1,99 +1,103 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- class Ibrain::Core::GraphqlController < Ibrain::BaseController
4
- include Devise::Controllers::ScopedViews
5
-
6
- before_action :map_user_class_to_request
7
-
8
- helpers = %w(resource scope_name resource_name signed_in_resource
9
- resource_class resource_params devise_mapping)
10
- helper_method(*helpers)
11
-
12
- def execute
13
- query, variables, operation_name = normalize_entity
14
-
15
- result = schema.execute(
16
- query,
17
- variables: variables,
18
- context: {
19
- session: session,
20
- current_user: try_ibrain_current_user,
21
- controller: self,
22
- request: request
23
- },
24
- operation_name: operation_name,
25
- max_depth: max_depth(operation_name)
26
- )
27
-
28
- render_json_ok(result['data'], nil, result['errors'])
29
- end
3
+ module Ibrain
4
+ module Core
5
+ class GraphqlController < ::Ibrain::BaseController
6
+ include Devise::Controllers::ScopedViews
7
+
8
+ before_action :map_user_class_to_request
9
+
10
+ helpers = %w(resource scope_name resource_name signed_in_resource
11
+ resource_class resource_params devise_mapping)
12
+ helper_method(*helpers)
13
+
14
+ def execute
15
+ query, variables, operation_name = normalize_entity
16
+
17
+ result = schema.execute(
18
+ query,
19
+ variables: variables,
20
+ context: {
21
+ session: session,
22
+ current_user: try_ibrain_current_user,
23
+ controller: self,
24
+ request: request
25
+ },
26
+ operation_name: operation_name,
27
+ max_depth: max_depth(operation_name)
28
+ )
29
+
30
+ render_json_ok(result['data'], nil, result['errors'])
31
+ end
30
32
 
31
- protected
33
+ protected
32
34
 
33
- def normalize_entity
34
- return [params[:query], prepare_variables(params[:variables]), params[:operationName]] if params[:variables].present?
35
- return [params[:query], prepare_variables(params[:variables]), 'IntrospectionQuery'] if params[:query].try(:include?, 'IntrospectionQuery')
35
+ def normalize_entity
36
+ return [params[:query], prepare_variables(params[:variables]), params[:operationName]] if params[:variables].present?
37
+ return [params[:query], prepare_variables(params[:variables]), 'IntrospectionQuery'] if params[:query].try(:include?, 'IntrospectionQuery')
36
38
 
37
- operations = prepare_variables(params[:operations])
38
- query = operations['query'] || params[:query]
39
- variables = operations['variables'] || params[:variables]
40
- operation_name = operations['operationName'] || params[:operationName]
39
+ operations = prepare_variables(params[:operations])
40
+ query = operations['query'] || params[:query]
41
+ variables = operations['variables'] || params[:variables]
42
+ operation_name = operations['operationName'] || params[:operationName]
41
43
 
42
- if params[:map].present?
43
- JSON.parse(params[:map]).each do |k, arguments|
44
- argument_name = arguments.try(:first).try(:split, '.').try(:second)
45
- next if argument_name.blank?
44
+ if params[:map].present?
45
+ JSON.parse(params[:map]).each do |k, arguments|
46
+ argument_name = arguments.try(:first).try(:split, '.').try(:second)
47
+ next if argument_name.blank?
46
48
 
47
- file = params[k]
49
+ file = params[k]
48
50
 
49
- if variables[argument_name].blank?
50
- variables[argument_name] = variables[argument_name].is_a?(Array) ? [file] : file
51
+ if variables[argument_name].blank?
52
+ variables[argument_name] = variables[argument_name].is_a?(Array) ? [file] : file
51
53
 
52
- next
53
- end
54
+ next
55
+ end
56
+
57
+ unless variables[argument_name].is_a?(Array)
58
+ variables[argument_name] = [variables[argument_name]]
59
+ end
54
60
 
55
- unless variables[argument_name].is_a?(Array)
56
- variables[argument_name] = [variables[argument_name]]
61
+ variables[argument_name] = variables[argument_name].concat([file]).compact
62
+ end
57
63
  end
58
64
 
59
- variables[argument_name] = variables[argument_name].concat([file]).compact
65
+ [query, variables, operation_name]
60
66
  end
61
- end
62
-
63
- [query, variables, operation_name]
64
- end
65
67
 
66
- # Handle variables in form data, JSON body, or a blank value
67
- def prepare_variables(variables_param)
68
- case variables_param
69
- when String
70
- if variables_param.present?
71
- JSON.parse(variables_param) || {}
72
- else
73
- {}
68
+ # Handle variables in form data, JSON body, or a blank value
69
+ def prepare_variables(variables_param)
70
+ case variables_param
71
+ when String
72
+ if variables_param.present?
73
+ JSON.parse(variables_param) || {}
74
+ else
75
+ {}
76
+ end
77
+ when Hash
78
+ variables_param
79
+ when ActionController::Parameters
80
+ variables_param.to_unsafe_hash # GraphQLRuby will validate name and type of incoming variables.
81
+ when nil
82
+ {}
83
+ else
84
+ raise ArgumentError, "Unexpected parameter: #{variables_param}"
85
+ end
74
86
  end
75
- when Hash
76
- variables_param
77
- when ActionController::Parameters
78
- variables_param.to_unsafe_hash # GraphQLRuby will validate name and type of incoming variables.
79
- when nil
80
- {}
81
- else
82
- raise ArgumentError, "Unexpected parameter: #{variables_param}"
83
- end
84
- end
85
87
 
86
- def schema
87
- Ibrain::Config.graphql_schema.safe_constantize
88
- end
88
+ def schema
89
+ Ibrain::Config.graphql_schema.safe_constantize
90
+ end
89
91
 
90
- def map_user_class_to_request
91
- return if request.env['devise.mapping'].present?
92
+ def map_user_class_to_request
93
+ return if request.env['devise.mapping'].present?
92
94
 
93
- request.env['devise.mapping'] = Ibrain.user_class
94
- end
95
+ request.env['devise.mapping'] = Ibrain.user_class
96
+ end
95
97
 
96
- def max_depth(operation_name)
97
- operation_name == 'IntrospectionQuery' ? nil : Ibrain::Config.graphql_max_depth
98
+ def max_depth(operation_name)
99
+ operation_name == 'IntrospectionQuery' ? nil : Ibrain::Config.graphql_max_depth
100
+ end
101
+ end
98
102
  end
99
- end
103
+ end
@@ -1,53 +1,55 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- class Ibrain::BaseSchema < GraphQL::Schema
4
- use GraphQL::Batch
5
-
6
- max_depth Ibrain::Config.graphql_max_depth
7
- query_analyzer(Ibrain::LogQueryDepth)
8
-
9
- # use GraphQL::Guard.new(
10
- # policy_object: ::Ibrain::Config.graphql_policy.safe_constantize,
11
- # not_authorized: ->(type, field) { raise IbrainErrors::PermissionError.new("You not have permission to access #{type}.#{field}") }
12
- # )
13
-
14
- # Union and Interface Resolution
15
- def self.resolve_type(_abstract_type, _obj, _ctx)
16
- # TODO: Implement this function
17
- # to return the correct object type for `obj`
18
- raise(GraphQL::RequiredImplementationMissingError)
3
+ module Ibrain
4
+ class BaseSchema < ::GraphQL::Schema
5
+ use GraphQL::Batch
6
+
7
+ max_depth Ibrain::Config.graphql_max_depth
8
+ query_analyzer(Ibrain::LogQueryDepth)
9
+
10
+ # use GraphQL::Guard.new(
11
+ # policy_object: ::Ibrain::Config.graphql_policy.safe_constantize,
12
+ # not_authorized: ->(type, field) { raise IbrainErrors::PermissionError.new("You not have permission to access #{type}.#{field}") }
13
+ # )
14
+
15
+ # Union and Interface Resolution
16
+ def self.resolve_type(_abstract_type, _obj, _ctx)
17
+ # TODO: Implement this function
18
+ # to return the correct object type for `obj`
19
+ raise(GraphQL::RequiredImplementationMissingError)
20
+ end
21
+
22
+ # Relay-style Object Identification:
23
+
24
+ # Return a string UUID for `object`
25
+ def self.id_from_object(object, type_definition, query_ctx)
26
+ # Here's a simple implementation which:
27
+ # - joins the type name & object.id
28
+ # - encodes it with base64:
29
+ # GraphQL::Schema::UniqueWithinType.encode(type_definition.name, object.id)
30
+ end
31
+
32
+ # Given a string UUID, find the object
33
+ def self.object_from_id(id, query_ctx)
34
+ # For example, to decode the UUIDs generated above:
35
+ # type_name, item_id = GraphQL::Schema::UniqueWithinType.decode(id)
36
+ #
37
+ # Then, based on `type_name` and `id`
38
+ # find an object in your application
39
+ # ...
40
+ end
41
+
42
+ def self.field(*args, camelize: false, **kwargs, &block)
43
+ # if camelize == false
44
+ # # Also make a camelized field:
45
+ # field(*args, camelize: false, **kwargs, &block)
46
+ # end
47
+ super
48
+ end
49
+
50
+ rescue_from(ActiveRecord::RecordNotFound) do |_err, _obj, _args, _ctx, field|
51
+ # Raise a graphql-friendly error with a custom message
52
+ raise GraphQL::ExecutionError, "#{field.type.unwrap.graphql_name} not found"
53
+ end
19
54
  end
20
-
21
- # Relay-style Object Identification:
22
-
23
- # Return a string UUID for `object`
24
- def self.id_from_object(object, type_definition, query_ctx)
25
- # Here's a simple implementation which:
26
- # - joins the type name & object.id
27
- # - encodes it with base64:
28
- # GraphQL::Schema::UniqueWithinType.encode(type_definition.name, object.id)
29
- end
30
-
31
- # Given a string UUID, find the object
32
- def self.object_from_id(id, query_ctx)
33
- # For example, to decode the UUIDs generated above:
34
- # type_name, item_id = GraphQL::Schema::UniqueWithinType.decode(id)
35
- #
36
- # Then, based on `type_name` and `id`
37
- # find an object in your application
38
- # ...
39
- end
40
-
41
- def self.field(*args, camelize: false, **kwargs, &block)
42
- # if camelize == false
43
- # # Also make a camelized field:
44
- # field(*args, camelize: false, **kwargs, &block)
45
- # end
46
- super
47
- end
48
-
49
- rescue_from(ActiveRecord::RecordNotFound) do |_err, _obj, _args, _ctx, field|
50
- # Raise a graphql-friendly error with a custom message
51
- raise GraphQL::ExecutionError, "#{field.type.unwrap.graphql_name} not found"
52
- end
53
- end
55
+ end
@@ -1,11 +1,15 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- class Ibrain::Extentions::DefaultValue < GraphQL::Schema::FieldExtension
4
- def after_resolve(value:, **_rest)
5
- if value.nil?
6
- options[:default_value]
7
- else
8
- value
3
+ module Ibrain
4
+ module Extentions
5
+ class DefaultValue < GraphQL::Schema::FieldExtension
6
+ def after_resolve(value:, **_rest)
7
+ if value.nil?
8
+ options[:default_value]
9
+ else
10
+ value
11
+ end
12
+ end
9
13
  end
10
14
  end
11
- end
15
+ end
@@ -1,22 +1,27 @@
1
1
  # frozen_string_literal: true
2
- class Ibrain::Extentions::Roles < GraphQL::Schema::FieldExtension
3
- def after_resolve(object:, value:, **_rest)
4
- raise IbrainErrors::PermissionError.new("You not have permission to access #{field&.name}") if is_invalid_role(object)
5
2
 
6
- value
7
- end
3
+ module Ibrain
4
+ module Extentions
5
+ class Roles < GraphQL::Schema::FieldExtension
6
+ def after_resolve(object:, value:, **_rest)
7
+ raise IbrainErrors::PermissionError.new("You not have permission to access #{field&.name}") if is_invalid_role(object)
8
+
9
+ value
10
+ end
8
11
 
9
- private
12
+ private
10
13
 
11
- def is_invalid_role(object)
12
- roles = options.try(:fetch, :roles, [])
13
- current_user = object.try(:context).try(:fetch, :current_user, nil)
14
- role = current_user.try(:role) || current_user.try(:graphql_role)
14
+ def is_invalid_role(object)
15
+ roles = options.try(:fetch, :roles, [])
16
+ current_user = object.try(:context).try(:fetch, :current_user, nil)
17
+ role = current_user.try(:role) || current_user.try(:graphql_role)
15
18
 
16
- return if roles.blank?
17
- return true if current_user.blank?
18
- return false if roles.include?(role)
19
+ return if roles.blank?
20
+ return true if current_user.blank?
21
+ return false if roles.include?(role)
19
22
 
20
- true
23
+ true
24
+ end
25
+ end
21
26
  end
22
- end
27
+ end
@@ -1,16 +1,20 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- class Ibrain::Extentions::SessionRequired < GraphQL::Schema::FieldExtension
4
- def resolve(object:, arguments:, **rest)
5
- raise ActionController::InvalidAuthenticityToken, I18n.t('ibrain.errors.session.invalid_session') if is_invalid_session(object)
3
+ module Ibrain
4
+ module Extentions
5
+ class SessionRequired < GraphQL::Schema::FieldExtension
6
+ def resolve(object:, arguments:, **rest)
7
+ raise ActionController::InvalidAuthenticityToken, I18n.t('ibrain.errors.session.invalid_session') if is_invalid_session(object)
6
8
 
7
- # yield the current time as `memo`
8
- yield(object, arguments, rest)
9
- end
9
+ # yield the current time as `memo`
10
+ yield(object, arguments, rest)
11
+ end
10
12
 
11
- private
13
+ private
12
14
 
13
- def is_invalid_session(object)
14
- object.try(:context).try(:fetch, :current_user, nil).blank? && options.try(:fetch, :session_required, false)
15
+ def is_invalid_session(object)
16
+ object.try(:context).try(:fetch, :current_user, nil).blank? && options.try(:fetch, :session_required, false)
17
+ end
18
+ end
15
19
  end
16
- end
20
+ end
@@ -1,4 +1,8 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- class Ibrain::Lazy::Base < GraphQL::Schema::Resolver
4
- end
3
+ module Ibrain
4
+ module Lazy
5
+ class Base < GraphQL::Schema::Resolver
6
+ end
7
+ end
8
+ end
@@ -2,56 +2,60 @@
2
2
 
3
3
  # ref: https://zenn.dev/necocoa/articles/setup-graphql-batch
4
4
 
5
- class Ibrain::Loaders::AssociationLoader < GraphQL::Batch::Loader
6
- def self.validate(model, association_name)
7
- new(model, association_name)
8
- nil
9
- end
10
-
11
- def initialize(model, association_name)
12
- super()
13
- @model = model
14
- @association_name = association_name
15
- validate
16
- end
17
-
18
- def load(record)
19
- unless record.is_a?(@model)
20
- raise TypeError,
21
- "#{@model} loader can't load association for #{record.class}"
5
+ module Ibrain
6
+ module Loaders
7
+ class AssociationLoader < GraphQL::Batch::Loader
8
+ def self.validate(model, association_name)
9
+ new(model, association_name)
10
+ nil
11
+ end
12
+
13
+ def initialize(model, association_name)
14
+ super()
15
+ @model = model
16
+ @association_name = association_name
17
+ validate
18
+ end
19
+
20
+ def load(record)
21
+ unless record.is_a?(@model)
22
+ raise TypeError,
23
+ "#{@model} loader can't load association for #{record.class}"
24
+ end
25
+ return Promise.resolve(read_association(record)) if association_loaded?(record)
26
+
27
+ super
28
+ end
29
+
30
+ # We want to load the associations on all records, even if they have the same id
31
+ def cache_key(record)
32
+ record.object_id
33
+ end
34
+
35
+ def perform(records)
36
+ preload_association(records)
37
+ records.each { |record| fulfill(record, read_association(record)) }
38
+ end
39
+
40
+ private
41
+
42
+ def validate
43
+ return if @model.reflect_on_association(@association_name)
44
+
45
+ raise ArgumentError, "No association #{@association_name} on #{@model}"
46
+ end
47
+
48
+ def preload_association(records)
49
+ ::ActiveRecord::Associations::Preloader.new.preload(records, @association_name)
50
+ end
51
+
52
+ def read_association(record)
53
+ record.public_send(@association_name)
54
+ end
55
+
56
+ def association_loaded?(record)
57
+ record.association(@association_name).loaded?
58
+ end
22
59
  end
23
- return Promise.resolve(read_association(record)) if association_loaded?(record)
24
-
25
- super
26
- end
27
-
28
- # We want to load the associations on all records, even if they have the same id
29
- def cache_key(record)
30
- record.object_id
31
- end
32
-
33
- def perform(records)
34
- preload_association(records)
35
- records.each { |record| fulfill(record, read_association(record)) }
36
- end
37
-
38
- private
39
-
40
- def validate
41
- return if @model.reflect_on_association(@association_name)
42
-
43
- raise ArgumentError, "No association #{@association_name} on #{@model}"
44
- end
45
-
46
- def preload_association(records)
47
- ::ActiveRecord::Associations::Preloader.new.preload(records, @association_name)
48
- end
49
-
50
- def read_association(record)
51
- record.public_send(@association_name)
52
- end
53
-
54
- def association_loaded?(record)
55
- record.association(@association_name).loaded?
56
60
  end
57
- end
61
+ end