graphql_devise 0.14.3 → 0.17.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (53) hide show
  1. checksums.yaml +4 -4
  2. data/Appraisals +7 -0
  3. data/CHANGELOG.md +58 -0
  4. data/README.md +186 -82
  5. data/app/controllers/graphql_devise/concerns/additional_controller_methods.rb +72 -0
  6. data/app/controllers/graphql_devise/concerns/set_user_by_token.rb +5 -27
  7. data/app/helpers/graphql_devise/mailer_helper.rb +2 -2
  8. data/app/models/graphql_devise/concerns/additional_model_methods.rb +21 -0
  9. data/app/models/graphql_devise/concerns/model.rb +6 -9
  10. data/app/views/graphql_devise/mailer/confirmation_instructions.html.erb +7 -1
  11. data/lib/generators/graphql_devise/install_generator.rb +1 -1
  12. data/lib/graphql_devise.rb +20 -6
  13. data/lib/graphql_devise/concerns/controller_methods.rb +3 -3
  14. data/lib/graphql_devise/default_operations/mutations.rb +14 -8
  15. data/lib/graphql_devise/default_operations/resolvers.rb +2 -2
  16. data/lib/graphql_devise/model/with_email_updater.rb +34 -8
  17. data/lib/graphql_devise/mount_method/operation_preparer.rb +6 -6
  18. data/lib/graphql_devise/mount_method/operation_preparers/custom_operation_preparer.rb +6 -4
  19. data/lib/graphql_devise/mount_method/operation_preparers/default_operation_preparer.rb +7 -5
  20. data/lib/graphql_devise/mount_method/operation_preparers/{resource_name_setter.rb → resource_klass_setter.rb} +4 -4
  21. data/lib/graphql_devise/mount_method/operation_sanitizer.rb +13 -1
  22. data/lib/graphql_devise/mutations/confirm_registration_with_token.rb +30 -0
  23. data/lib/graphql_devise/mutations/login.rb +2 -0
  24. data/lib/graphql_devise/mutations/register.rb +60 -0
  25. data/lib/graphql_devise/mutations/resend_confirmation_with_token.rb +44 -0
  26. data/lib/graphql_devise/mutations/sign_up.rb +1 -1
  27. data/lib/graphql_devise/resolvers/confirm_account.rb +1 -1
  28. data/lib/graphql_devise/resource_loader.rb +26 -11
  29. data/lib/graphql_devise/schema_plugin.rb +20 -8
  30. data/lib/graphql_devise/version.rb +1 -1
  31. data/spec/dummy/app/controllers/api/v1/graphql_controller.rb +11 -0
  32. data/spec/dummy/app/graphql/dummy_schema.rb +4 -3
  33. data/spec/dummy/app/graphql/mutations/register.rb +14 -0
  34. data/spec/dummy/app/graphql/types/query_type.rb +5 -0
  35. data/spec/dummy/config/routes.rb +7 -5
  36. data/spec/dummy/db/migrate/20210516211417_add_vip_to_users.rb +5 -0
  37. data/spec/dummy/db/schema.rb +4 -3
  38. data/spec/generators/graphql_devise/install_generator_spec.rb +1 -1
  39. data/spec/graphql/user_queries_spec.rb +3 -1
  40. data/spec/graphql_devise/model/with_email_updater_spec.rb +97 -68
  41. data/spec/requests/graphql_controller_spec.rb +1 -1
  42. data/spec/requests/mutations/confirm_registration_with_token_spec.rb +117 -0
  43. data/spec/requests/mutations/register_spec.rb +166 -0
  44. data/spec/requests/mutations/resend_confirmation_with_token_spec.rb +137 -0
  45. data/spec/requests/user_controller_spec.rb +86 -25
  46. data/spec/services/mount_method/operation_preparer_spec.rb +5 -5
  47. data/spec/services/mount_method/operation_preparers/custom_operation_preparer_spec.rb +5 -5
  48. data/spec/services/mount_method/operation_preparers/default_operation_preparer_spec.rb +5 -5
  49. data/spec/services/mount_method/operation_preparers/{resource_name_setter_spec.rb → resource_klass_setter_spec.rb} +6 -6
  50. data/spec/services/mount_method/operation_sanitizer_spec.rb +3 -3
  51. data/spec/services/resource_loader_spec.rb +5 -5
  52. data/spec/support/contexts/graphql_request.rb +2 -2
  53. metadata +21 -6
@@ -0,0 +1,72 @@
1
+ # frozen_string_literal: true
2
+
3
+ module GraphqlDevise
4
+ module Concerns
5
+ module AdditionalControllerMethods
6
+ extend ActiveSupport::Concern
7
+
8
+ included do
9
+ attr_accessor :client_id, :token, :resource
10
+ end
11
+
12
+ def gql_devise_context(*models)
13
+ {
14
+ current_resource: authenticate_model(*models),
15
+ controller: self
16
+ }
17
+ end
18
+
19
+ def authenticate_model(*models)
20
+ models.each do |model|
21
+ set_resource_by_token(model)
22
+ return @resource if @resource.present?
23
+ end
24
+
25
+ nil
26
+ end
27
+
28
+ def resource_class(resource = nil)
29
+ # Return the resource class instead of looking for a Devise mapping if resource is already a resource class
30
+ return resource if resource.respond_to?(:find_by)
31
+
32
+ super
33
+ end
34
+
35
+ def full_url_without_params
36
+ request.base_url + request.path
37
+ end
38
+
39
+ def set_resource_by_token(resource)
40
+ set_user_by_token(resource)
41
+ end
42
+
43
+ def graphql_context(resource_name)
44
+ ActiveSupport::Deprecation.warn(<<-DEPRECATION.strip_heredoc, caller)
45
+ `graphql_context` is deprecated and will be removed in a future version of this gem.
46
+ Use `gql_devise_context(model)` instead.
47
+
48
+ EXAMPLE
49
+ include GraphqlDevise::Concerns::SetUserByToken
50
+
51
+ DummySchema.execute(params[:query], context: gql_devise_context(User))
52
+ DummySchema.execute(params[:query], context: gql_devise_context(User, Admin))
53
+ DEPRECATION
54
+
55
+ {
56
+ resource_name: resource_name,
57
+ controller: self
58
+ }
59
+ end
60
+
61
+ def build_redirect_headers(access_token, client, redirect_header_options = {})
62
+ {
63
+ DeviseTokenAuth.headers_names[:"access-token"] => access_token,
64
+ DeviseTokenAuth.headers_names[:client] => client,
65
+ :config => params[:config],
66
+ :client_id => client,
67
+ :token => access_token
68
+ }.merge(redirect_header_options)
69
+ end
70
+ end
71
+ end
72
+ end
@@ -2,34 +2,12 @@
2
2
 
3
3
  module GraphqlDevise
4
4
  module Concerns
5
- SetUserByToken = DeviseTokenAuth::Concerns::SetUserByToken
5
+ module SetUserByToken
6
+ extend ActiveSupport::Concern
6
7
 
7
- SetUserByToken.module_eval do
8
- attr_accessor :client_id, :token, :resource
9
-
10
- def full_url_without_params
11
- request.base_url + request.path
12
- end
13
-
14
- def set_resource_by_token(resource)
15
- set_user_by_token(resource)
16
- end
17
-
18
- def graphql_context(resource_name)
19
- {
20
- resource_name: resource_name,
21
- controller: self
22
- }
23
- end
24
-
25
- def build_redirect_headers(access_token, client, redirect_header_options = {})
26
- {
27
- DeviseTokenAuth.headers_names[:"access-token"] => access_token,
28
- DeviseTokenAuth.headers_names[:client] => client,
29
- :config => params[:config],
30
- :client_id => client,
31
- :token => access_token
32
- }.merge(redirect_header_options)
8
+ included do
9
+ include DeviseTokenAuth::Concerns::SetUserByToken
10
+ include GraphqlDevise::Concerns::AdditionalControllerMethods
33
11
  end
34
12
  end
35
13
  end
@@ -3,7 +3,7 @@
3
3
  module GraphqlDevise
4
4
  module MailerHelper
5
5
  def confirmation_query(resource_name:, token:, redirect_url:)
6
- name = "#{resource_name.underscore.tr('/', '_').camelize(:lower)}ConfirmAccount"
6
+ name = "#{GraphqlDevise.to_mapping_name(resource_name).camelize(:lower)}ConfirmAccount"
7
7
  raw = <<-GRAPHQL
8
8
  query($token:String!,$redirectUrl:String!){
9
9
  #{name}(confirmationToken:$token,redirectUrl:$redirectUrl){
@@ -19,7 +19,7 @@ module GraphqlDevise
19
19
  end
20
20
 
21
21
  def password_reset_query(token:, redirect_url:, resource_name:)
22
- name = "#{resource_name.underscore.tr('/', '_').camelize(:lower)}CheckPasswordToken"
22
+ name = "#{GraphqlDevise.to_mapping_name(resource_name).camelize(:lower)}CheckPasswordToken"
23
23
  raw = <<-GRAPHQL
24
24
  query($token:String!,$redirectUrl:String!){
25
25
  #{name}(resetPasswordToken:$token,redirectUrl:$redirectUrl){
@@ -0,0 +1,21 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'graphql_devise/model/with_email_updater'
4
+
5
+ module GraphqlDevise
6
+ module Concerns
7
+ module AdditionalModelMethods
8
+ extend ActiveSupport::Concern
9
+
10
+ class_methods do
11
+ def reconfirmable
12
+ devise_modules.include?(:confirmable) && column_names.include?('unconfirmed_email')
13
+ end
14
+ end
15
+
16
+ def update_with_email(attributes = {})
17
+ GraphqlDevise::Model::WithEmailUpdater.new(self, attributes).call
18
+ end
19
+ end
20
+ end
21
+ end
@@ -4,17 +4,14 @@ require 'graphql_devise/model/with_email_updater'
4
4
 
5
5
  module GraphqlDevise
6
6
  module Concerns
7
- Model = DeviseTokenAuth::Concerns::User
7
+ module Model
8
+ extend ActiveSupport::Concern
8
9
 
9
- Model.module_eval do
10
- class_methods do
11
- def reconfirmable
12
- devise_modules.include?(:confirmable) && column_names.include?('unconfirmed_email')
13
- end
14
- end
10
+ included do
11
+ include DeviseTokenAuth::Concerns::User
12
+ include GraphqlDevise::Concerns::AdditionalModelMethods
15
13
 
16
- def update_with_email(attributes = {})
17
- GraphqlDevise::Model::WithEmailUpdater.new(self, attributes).call
14
+ GraphqlDevise.configure_warden_serializer_for_model(self)
18
15
  end
19
16
  end
20
17
  end
@@ -2,4 +2,10 @@
2
2
 
3
3
  <p><%= t('.confirm_link_msg') %></p>
4
4
 
5
- <p><%= link_to t('.confirm_account_link'), "#{message['schema_url']}?#{confirmation_query(resource_name: @resource.class.to_s, redirect_url: message['redirect-url'], token: @token).to_query}" %></p>
5
+ <p>
6
+ <% if message['schema_url'].present? %>
7
+ <%= link_to t('.confirm_account_link'), "#{message['schema_url']}?#{confirmation_query(resource_name: @resource.class.to_s, redirect_url: message['redirect-url'], token: @token).to_query}" %>
8
+ <% else %>
9
+ <%= link_to t('.confirm_account_link'), "#{CGI.escape(message['redirect-url'].to_s)}?#{{ confirmationToken: @token }.to_query}" %>
10
+ <% end %>
11
+ </p>
@@ -83,7 +83,7 @@ module GraphqlDevise
83
83
  query: Types::QueryType,
84
84
  mutation: Types::MutationType,
85
85
  resource_loaders: [
86
- GraphqlDevise::ResourceLoader.new('#{user_class}'),
86
+ GraphqlDevise::ResourceLoader.new(#{user_class})
87
87
  ]
88
88
  )
89
89
  RUBY
@@ -20,22 +20,36 @@ module GraphqlDevise
20
20
  @schema_loaded = true
21
21
  end
22
22
 
23
- def self.resource_mounted?(mapping_name)
24
- @mounted_resources.include?(mapping_name)
23
+ def self.resource_mounted?(model)
24
+ @mounted_resources.include?(model)
25
25
  end
26
26
 
27
- def self.mount_resource(mapping_name)
28
- @mounted_resources << mapping_name
27
+ def self.mount_resource(model)
28
+ @mounted_resources << model
29
29
  end
30
30
 
31
31
  def self.add_mapping(mapping_name, resource)
32
- return if Devise.mappings.key?(mapping_name)
32
+ return if Devise.mappings.key?(mapping_name.to_sym)
33
33
 
34
34
  Devise.add_mapping(
35
35
  mapping_name.to_s.pluralize.to_sym,
36
- module: :devise, class_name: resource
36
+ module: :devise, class_name: resource.to_s
37
37
  )
38
38
  end
39
+
40
+ def self.to_mapping_name(resource)
41
+ resource.to_s.underscore.tr('/', '_')
42
+ end
43
+
44
+ def self.configure_warden_serializer_for_model(model)
45
+ Devise.warden_config.serialize_into_session(to_mapping_name(model)) do |record|
46
+ model.serialize_into_session(record)
47
+ end
48
+
49
+ Devise.warden_config.serialize_from_session(to_mapping_name(model)) do |args|
50
+ model.serialize_from_session(*args)
51
+ end
52
+ end
39
53
  end
40
54
 
41
55
  require 'graphql_devise/engine'
@@ -40,11 +40,11 @@ module GraphqlDevise
40
40
  end
41
41
 
42
42
  def resource_name
43
- self.class.instance_variable_get(:@resource_name)
43
+ GraphqlDevise.to_mapping_name(resource_class)
44
44
  end
45
45
 
46
46
  def resource_class
47
- controller.send(:resource_class, resource_name)
47
+ self.class.instance_variable_get(:@resource_klass)
48
48
  end
49
49
 
50
50
  def recoverable_enabled?
@@ -60,7 +60,7 @@ module GraphqlDevise
60
60
  end
61
61
 
62
62
  def current_resource
63
- @current_resource ||= controller.send(:set_user_by_token, resource_name)
63
+ @current_resource ||= controller.send(:set_resource_by_token, resource_class)
64
64
  end
65
65
 
66
66
  def client
@@ -4,23 +4,29 @@ require 'graphql_devise/mutations/base'
4
4
  require 'graphql_devise/mutations/login'
5
5
  require 'graphql_devise/mutations/logout'
6
6
  require 'graphql_devise/mutations/resend_confirmation'
7
+ require 'graphql_devise/mutations/resend_confirmation_with_token'
7
8
  require 'graphql_devise/mutations/send_password_reset'
8
9
  require 'graphql_devise/mutations/send_password_reset_with_token'
9
10
  require 'graphql_devise/mutations/sign_up'
11
+ require 'graphql_devise/mutations/register'
10
12
  require 'graphql_devise/mutations/update_password'
11
13
  require 'graphql_devise/mutations/update_password_with_token'
14
+ require 'graphql_devise/mutations/confirm_registration_with_token'
12
15
 
13
16
  module GraphqlDevise
14
17
  module DefaultOperations
15
18
  MUTATIONS = {
16
- login: { klass: GraphqlDevise::Mutations::Login, authenticatable: true },
17
- logout: { klass: GraphqlDevise::Mutations::Logout, authenticatable: true },
18
- sign_up: { klass: GraphqlDevise::Mutations::SignUp, authenticatable: true },
19
- update_password: { klass: GraphqlDevise::Mutations::UpdatePassword, authenticatable: true },
20
- update_password_with_token: { klass: GraphqlDevise::Mutations::UpdatePasswordWithToken, authenticatable: true },
21
- send_password_reset: { klass: GraphqlDevise::Mutations::SendPasswordReset, authenticatable: false },
22
- send_password_reset_with_token: { klass: GraphqlDevise::Mutations::SendPasswordResetWithToken, authenticatable: false },
23
- resend_confirmation: { klass: GraphqlDevise::Mutations::ResendConfirmation, authenticatable: false }
19
+ login: { klass: GraphqlDevise::Mutations::Login, authenticatable: true },
20
+ logout: { klass: GraphqlDevise::Mutations::Logout, authenticatable: true },
21
+ sign_up: { klass: GraphqlDevise::Mutations::SignUp, authenticatable: true, deprecation_reason: 'use register instead' },
22
+ register: { klass: GraphqlDevise::Mutations::Register, authenticatable: true },
23
+ update_password: { klass: GraphqlDevise::Mutations::UpdatePassword, authenticatable: true, deprecation_reason: 'use update_password_with_token instead' },
24
+ update_password_with_token: { klass: GraphqlDevise::Mutations::UpdatePasswordWithToken, authenticatable: true },
25
+ send_password_reset: { klass: GraphqlDevise::Mutations::SendPasswordReset, authenticatable: false, deprecation_reason: 'use send_password_reset_with_token instead' },
26
+ send_password_reset_with_token: { klass: GraphqlDevise::Mutations::SendPasswordResetWithToken, authenticatable: false },
27
+ resend_confirmation: { klass: GraphqlDevise::Mutations::ResendConfirmation, authenticatable: false, deprecation_reason: 'use resend_confirmation_with_token instead' },
28
+ resend_confirmation_with_token: { klass: GraphqlDevise::Mutations::ResendConfirmationWithToken, authenticatable: false },
29
+ confirm_registration_with_token: { klass: GraphqlDevise::Mutations::ConfirmRegistrationWithToken, authenticatable: true }
24
30
  }.freeze
25
31
  end
26
32
  end
@@ -7,8 +7,8 @@ require 'graphql_devise/resolvers/confirm_account'
7
7
  module GraphqlDevise
8
8
  module DefaultOperations
9
9
  QUERIES = {
10
- confirm_account: { klass: GraphqlDevise::Resolvers::ConfirmAccount },
11
- check_password_token: { klass: GraphqlDevise::Resolvers::CheckPasswordToken }
10
+ confirm_account: { klass: GraphqlDevise::Resolvers::ConfirmAccount, deprecation_reason: 'use the new confirmation flow as it does not require this query anymore' },
11
+ check_password_token: { klass: GraphqlDevise::Resolvers::CheckPasswordToken, deprecation_reason: 'use the new password reset flow as it does not require this query anymore' }
12
12
  }.freeze
13
13
  end
14
14
  end
@@ -4,12 +4,14 @@ module GraphqlDevise
4
4
  module Model
5
5
  class WithEmailUpdater
6
6
  def initialize(resource, attributes)
7
- @attributes = attributes
7
+ @attributes = attributes.with_indifferent_access
8
8
  @resource = resource
9
9
  end
10
10
 
11
11
  def call
12
- resource_attributes = @attributes.except(:schema_url, :confirmation_success_url)
12
+ check_deprecated_attributes
13
+
14
+ resource_attributes = @attributes.except(:schema_url, :confirmation_success_url, :confirmation_url)
13
15
  return @resource.update(resource_attributes) unless requires_reconfirmation?(resource_attributes)
14
16
 
15
17
  @resource.assign_attributes(resource_attributes)
@@ -27,16 +29,31 @@ module GraphqlDevise
27
29
  else
28
30
  raise(
29
31
  GraphqlDevise::Error,
30
- 'Method `update_with_email` requires attributes `confirmation_success_url` and `schema_url` for email reconfirmation to work'
32
+ 'Method `update_with_email` requires attribute `confirmation_url` for email reconfirmation to work'
31
33
  )
32
34
  end
33
35
  end
34
36
 
35
37
  private
36
38
 
39
+ def check_deprecated_attributes
40
+ if [@attributes[:schema_url], @attributes[:confirmation_success_url]].any?(&:present?)
41
+ ActiveSupport::Deprecation.warn(<<-DEPRECATION.strip_heredoc, caller)
42
+ Providing `schema_url` and `confirmation_success_url` to `update_with_email` is deprecated and will be
43
+ removed in a future version of this gem.
44
+
45
+ Now you must only provide `confirmation_url` and the email will contain the new format of the confirmation
46
+ url that needs to be used with the new `confirmRegistrationWithToken` on the client application.
47
+ DEPRECATION
48
+ end
49
+ end
50
+
37
51
  def required_reconfirm_attributes?
38
- @attributes[:schema_url].present? &&
39
- (@attributes[:confirmation_success_url].present? || DeviseTokenAuth.default_confirm_success_url.present?)
52
+ if @attributes[:schema_url].present?
53
+ [@attributes[:confirmation_success_url], DeviseTokenAuth.default_confirm_success_url].any?(&:present?)
54
+ else
55
+ [@attributes[:confirmation_url], DeviseTokenAuth.default_confirm_success_url].any?(&:present?)
56
+ end
40
57
  end
41
58
 
42
59
  def requires_reconfirmation?(resource_attributes)
@@ -60,13 +77,22 @@ module GraphqlDevise
60
77
  end
61
78
  end
62
79
 
80
+ def confirmation_method_params
81
+ if @attributes[:schema_url].present?
82
+ {
83
+ redirect_url: @attributes[:confirmation_success_url] || DeviseTokenAuth.default_confirm_success_url,
84
+ schema_url: @attributes[:schema_url]
85
+ }
86
+ else
87
+ { redirect_url: @attributes[:confirmation_url] || DeviseTokenAuth.default_confirm_success_url }
88
+ end
89
+ end
90
+
63
91
  def send_confirmation_instructions(saved)
64
92
  return unless saved
65
93
 
66
94
  @resource.send_confirmation_instructions(
67
- redirect_url: @attributes[:confirmation_success_url] || DeviseTokenAuth.default_confirm_success_url,
68
- template_path: ['graphql_devise/mailer'],
69
- schema_url: @attributes[:schema_url]
95
+ confirmation_method_params.merge(template_path: ['graphql_devise/mailer'])
70
96
  )
71
97
  end
72
98
  end
@@ -3,17 +3,17 @@
3
3
  require_relative 'operation_preparers/gql_name_setter'
4
4
  require_relative 'operation_preparers/mutation_field_setter'
5
5
  require_relative 'operation_preparers/resolver_type_setter'
6
- require_relative 'operation_preparers/resource_name_setter'
6
+ require_relative 'operation_preparers/resource_klass_setter'
7
7
  require_relative 'operation_preparers/default_operation_preparer'
8
8
  require_relative 'operation_preparers/custom_operation_preparer'
9
9
 
10
10
  module GraphqlDevise
11
11
  module MountMethod
12
12
  class OperationPreparer
13
- def initialize(mapping_name:, selected_operations:, preparer:, custom:, additional_operations:)
13
+ def initialize(model:, selected_operations:, preparer:, custom:, additional_operations:)
14
14
  @selected_operations = selected_operations
15
15
  @preparer = preparer
16
- @mapping_name = mapping_name
16
+ @model = model
17
17
  @custom = custom
18
18
  @additional_operations = additional_operations
19
19
  end
@@ -22,18 +22,18 @@ module GraphqlDevise
22
22
  default_operations = OperationPreparers::DefaultOperationPreparer.new(
23
23
  selected_operations: @selected_operations,
24
24
  custom_keys: @custom.keys,
25
- mapping_name: @mapping_name,
25
+ model: @model,
26
26
  preparer: @preparer
27
27
  ).call
28
28
 
29
29
  custom_operations = OperationPreparers::CustomOperationPreparer.new(
30
30
  selected_keys: @selected_operations.keys,
31
31
  custom_operations: @custom,
32
- mapping_name: @mapping_name
32
+ model: @model
33
33
  ).call
34
34
 
35
35
  additional_operations = @additional_operations.each_with_object({}) do |(action, operation), result|
36
- result[action] = OperationPreparers::ResourceNameSetter.new(@mapping_name).call(operation)
36
+ result[action] = OperationPreparers::ResourceKlassSetter.new(@model).call(operation)
37
37
  end
38
38
 
39
39
  default_operations.merge(custom_operations).merge(additional_operations)
@@ -4,19 +4,21 @@ module GraphqlDevise
4
4
  module MountMethod
5
5
  module OperationPreparers
6
6
  class CustomOperationPreparer
7
- def initialize(selected_keys:, custom_operations:, mapping_name:)
7
+ def initialize(selected_keys:, custom_operations:, model:)
8
8
  @selected_keys = selected_keys
9
9
  @custom_operations = custom_operations
10
- @mapping_name = mapping_name
10
+ @model = model
11
11
  end
12
12
 
13
13
  def call
14
+ mapping_name = GraphqlDevise.to_mapping_name(@model)
15
+
14
16
  @custom_operations.slice(*@selected_keys).each_with_object({}) do |(action, operation), result|
15
- mapped_action = "#{@mapping_name}_#{action}"
17
+ mapped_action = "#{mapping_name}_#{action}"
16
18
 
17
19
  result[mapped_action.to_sym] = [
18
20
  OperationPreparers::GqlNameSetter.new(mapped_action),
19
- OperationPreparers::ResourceNameSetter.new(@mapping_name)
21
+ OperationPreparers::ResourceKlassSetter.new(@model)
20
22
  ].reduce(operation) { |prepared_operation, preparer| preparer.call(prepared_operation) }
21
23
  end
22
24
  end