soaspec 0.2.32 → 0.2.33

Sign up to get free protection for your applications and to get access to all the features.
Files changed (86) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +15 -15
  3. data/.gitlab-ci.yml +62 -62
  4. data/.rspec +3 -3
  5. data/.rubocop.yml +2 -2
  6. data/CODE_OF_CONDUCT.md +74 -74
  7. data/ChangeLog +632 -625
  8. data/Dockerfile +7 -7
  9. data/Gemfile +8 -8
  10. data/LICENSE.txt +21 -21
  11. data/README.md +231 -231
  12. data/Rakefile +52 -52
  13. data/Todo.md +16 -16
  14. data/exe/soaspec +138 -138
  15. data/exe/xml_to_yaml_file +43 -43
  16. data/lib/soaspec.rb +106 -105
  17. data/lib/soaspec/baseline.rb +23 -0
  18. data/lib/soaspec/core_ext/hash.rb +44 -44
  19. data/lib/soaspec/cucumber/generic_steps.rb +94 -94
  20. data/lib/soaspec/demo.rb +6 -6
  21. data/lib/soaspec/errors.rb +24 -22
  22. data/lib/soaspec/exchange/exchange.rb +129 -129
  23. data/lib/soaspec/exchange/exchange_extractor.rb +90 -90
  24. data/lib/soaspec/exchange/exchange_properties.rb +28 -28
  25. data/lib/soaspec/exchange/exchange_repeater.rb +21 -21
  26. data/lib/soaspec/exchange/request_builder.rb +70 -70
  27. data/lib/soaspec/exchange/variable_storer.rb +24 -24
  28. data/lib/soaspec/exchange_handlers/exchange_handler.rb +98 -98
  29. data/lib/soaspec/exchange_handlers/exchange_handler_defaults.rb +61 -61
  30. data/lib/soaspec/exchange_handlers/handler_accessors.rb +132 -132
  31. data/lib/soaspec/exchange_handlers/request/rest_request.rb +59 -51
  32. data/lib/soaspec/exchange_handlers/request/soap_request.rb +41 -41
  33. data/lib/soaspec/exchange_handlers/response_extractor.rb +84 -84
  34. data/lib/soaspec/exchange_handlers/rest_exchanger_factory.rb +111 -111
  35. data/lib/soaspec/exchange_handlers/rest_handler.rb +307 -298
  36. data/lib/soaspec/exchange_handlers/rest_methods.rb +65 -65
  37. data/lib/soaspec/exchange_handlers/rest_parameters.rb +112 -112
  38. data/lib/soaspec/exchange_handlers/rest_parameters_defaults.rb +42 -42
  39. data/lib/soaspec/exchange_handlers/soap_handler.rb +241 -241
  40. data/lib/soaspec/exe_helpers.rb +94 -94
  41. data/lib/soaspec/generate_server.rb +48 -48
  42. data/lib/soaspec/generator/.rspec.erb +5 -5
  43. data/lib/soaspec/generator/.travis.yml.erb +5 -5
  44. data/lib/soaspec/generator/Gemfile.erb +8 -8
  45. data/lib/soaspec/generator/README.md.erb +29 -29
  46. data/lib/soaspec/generator/Rakefile.erb +19 -19
  47. data/lib/soaspec/generator/config/data/default.yml.erb +2 -2
  48. data/lib/soaspec/generator/css/bootstrap.css +6833 -6833
  49. data/lib/soaspec/generator/features/support/env.rb.erb +3 -3
  50. data/lib/soaspec/generator/generate_exchange.html.erb +47 -47
  51. data/lib/soaspec/generator/lib/blz_service.rb.erb +26 -26
  52. data/lib/soaspec/generator/lib/dynamic_class_content.rb.erb +12 -12
  53. data/lib/soaspec/generator/lib/new_rest_service.rb.erb +56 -56
  54. data/lib/soaspec/generator/lib/new_soap_service.rb.erb +29 -29
  55. data/lib/soaspec/generator/lib/package_service.rb.erb +2 -2
  56. data/lib/soaspec/generator/lib/shared_example.rb.erb +8 -8
  57. data/lib/soaspec/generator/spec/dynamic_soap_spec.rb.erb +12 -12
  58. data/lib/soaspec/generator/spec/rest_spec.rb.erb +9 -9
  59. data/lib/soaspec/generator/spec/soap_spec.rb.erb +51 -51
  60. data/lib/soaspec/generator/spec/spec_helper.rb.erb +23 -23
  61. data/lib/soaspec/generator/template/soap_template.xml +6 -6
  62. data/lib/soaspec/indifferent_hash.rb +9 -9
  63. data/lib/soaspec/interpreter.rb +70 -70
  64. data/lib/soaspec/matchers.rb +140 -118
  65. data/lib/soaspec/o_auth2.rb +142 -142
  66. data/lib/soaspec/soaspec_shared_examples.rb +26 -26
  67. data/lib/soaspec/spec_logger.rb +143 -143
  68. data/lib/soaspec/template_reader.rb +30 -30
  69. data/lib/soaspec/test_server/bank.wsdl +90 -90
  70. data/lib/soaspec/test_server/get_bank.rb +166 -166
  71. data/lib/soaspec/test_server/id_manager.rb +41 -41
  72. data/lib/soaspec/test_server/invoices.rb +29 -29
  73. data/lib/soaspec/test_server/namespace.xml +14 -14
  74. data/lib/soaspec/test_server/note.xml +5 -5
  75. data/lib/soaspec/test_server/puppy_service.rb +21 -21
  76. data/lib/soaspec/test_server/test_attribute.rb +14 -14
  77. data/lib/soaspec/test_server/test_namespace.rb +14 -14
  78. data/lib/soaspec/version.rb +6 -6
  79. data/lib/soaspec/virtual_server.rb +190 -176
  80. data/lib/soaspec/wait.rb +43 -43
  81. data/lib/soaspec/wsdl_generator.rb +215 -215
  82. data/soaspec.gemspec +58 -58
  83. data/test.wsdl +116 -116
  84. data/test.xml +10 -10
  85. data/test_wsdl.rb +43 -43
  86. metadata +4 -3
@@ -1,28 +1,28 @@
1
- # frozen_string_literal: true
2
-
3
- module Soaspec
4
- # Convenience methods to set Exchange specific properties
5
- # Will be used when creating a subclass of Exchange
6
- module ExchangeProperties
7
- # Set default exchange handler for this exchange
8
- # This is helpful for when you need a new exchange handler created for each exchange
9
- # @param [Class] handler_class Class of ExchangeHandler to set Exchange to use
10
- # @param [String] name Name to call handler when it's instantiated (Defaults to class name)
11
- # @param [Hash] params Hash of parameters to set for instance of ExchangeHandler
12
- def default_handler(handler_class, name = handler_class.to_s, params = '')
13
- define_method('default_handler_used') do
14
- params_used = Hash[params.map do |k, param|
15
- [k, param.is_a?(String) ? ERB.new(param).result(binding) : param]
16
- end]
17
- handler_class.new name, params_used
18
- end
19
- end
20
-
21
- # Set retry_for_success to true, retrying response until a successful status code is returned
22
- # @param [Integer] retry_count Times to retry to get a positive response
23
- def expect_positive_status(retry_count: 3)
24
- define_method('retry_count') { retry_count }
25
- define_method('retry_for_success?') { true }
26
- end
27
- end
28
- end
1
+ # frozen_string_literal: true
2
+
3
+ module Soaspec
4
+ # Convenience methods to set Exchange specific properties
5
+ # Will be used when creating a subclass of Exchange
6
+ module ExchangeProperties
7
+ # Set default exchange handler for this exchange
8
+ # This is helpful for when you need a new exchange handler created for each exchange
9
+ # @param [Class] handler_class Class of ExchangeHandler to set Exchange to use
10
+ # @param [String] name Name to call handler when it's instantiated (Defaults to class name)
11
+ # @param [Hash] params Hash of parameters to set for instance of ExchangeHandler
12
+ def default_handler(handler_class, name = handler_class.to_s, params = '')
13
+ define_method('default_handler_used') do
14
+ params_used = Hash[params.map do |k, param|
15
+ [k, param.is_a?(String) ? ERB.new(param).result(binding) : param]
16
+ end]
17
+ handler_class.new name, params_used
18
+ end
19
+ end
20
+
21
+ # Set retry_for_success to true, retrying response until a successful status code is returned
22
+ # @param [Integer] retry_count Times to retry to get a positive response
23
+ def expect_positive_status(retry_count: 3)
24
+ define_method('retry_count') { retry_count }
25
+ define_method('retry_for_success?') { true }
26
+ end
27
+ end
28
+ end
@@ -1,21 +1,21 @@
1
- # frozen_string_literal: true
2
-
3
- module Soaspec
4
- # Ways of repeating an exchange to reach a desired outcome
5
- module ExchangeRepeater
6
- # Wait until the passed block returns true
7
- # @param [Hash] opts Options for this instance
8
- # @option opts [Numeric] :timeout (5) Seconds to wait before timing out.
9
- # @option opts [Numeric] :interval (0.2) Seconds to sleep between polls.
10
- # @option opts [String] :message Exception message if timed out.
11
- # @option opts [Array, Exception] :ignore Exceptions to ignore while polling (default: Error::NoSuchElementError)
12
- # @return [Exchange] Returns itself so operations can be done on the exchange after it's done waiting
13
- def until(opts = {}, &script)
14
- Soaspec::Wait.until(opts) do
15
- @response = nil # Reset response so it can be made repeatedly
16
- instance_eval(&script)
17
- end
18
- self
19
- end
20
- end
21
- end
1
+ # frozen_string_literal: true
2
+
3
+ module Soaspec
4
+ # Ways of repeating an exchange to reach a desired outcome
5
+ module ExchangeRepeater
6
+ # Wait until the passed block returns true
7
+ # @param [Hash] opts Options for this instance
8
+ # @option opts [Numeric] :timeout (5) Seconds to wait before timing out.
9
+ # @option opts [Numeric] :interval (0.2) Seconds to sleep between polls.
10
+ # @option opts [String] :message Exception message if timed out.
11
+ # @option opts [Array, Exception] :ignore Exceptions to ignore while polling (default: Error::NoSuchElementError)
12
+ # @return [Exchange] Returns itself so operations can be done on the exchange after it's done waiting
13
+ def until(opts = {}, &script)
14
+ Soaspec::Wait.until(opts) do
15
+ @response = nil # Reset response so it can be made repeatedly
16
+ instance_eval(&script)
17
+ end
18
+ self
19
+ end
20
+ end
21
+ end
@@ -1,70 +1,70 @@
1
- # frozen_string_literal: true
2
-
3
- module Soaspec
4
- # Methods to help build a Request
5
- module RequestBuilder
6
- # Specify a url to add onto the base_url of the ExchangeHandler used
7
- # @param [String] url Url to add onto the base_url of the ExchangeHandler used
8
- def suburl=(url)
9
- @override_parameters[:suburl] = url
10
- end
11
-
12
- # Specify HTTP method to use. Default is :post
13
- # @param [Symbol] method HTTP method. E.g, :get, :patch
14
- def method=(method)
15
- @override_parameters[:method] = method
16
- end
17
-
18
- # Set a parameter request in the request body.
19
- # Can be used to build a request over several steps (e.g Cucumber)
20
- # Will be used with FactoryBot
21
- #
22
- # @example
23
- # exchange['name'] = 'tester'
24
- # # Will set { name: tester } in the response, formatting as JSON or XML depending on REST / SOAP
25
- # @param [String, Symbol] key Name of request element to set
26
- # @param [String] value Value to set request element to
27
- def []=(key, value)
28
- @override_parameters[:body] ||= {}
29
- @override_parameters[:body][key] = value
30
- end
31
-
32
- # Implement undefined setter with []= for FactoryBot to use without needing to define params to set
33
- # @param [Object] method_name Name of method not defined
34
- # @param [Object] args Arguments passed to method
35
- # @param [Object] block Block passed to method
36
- def method_missing(method_name, *args, &block)
37
- set_value = args.first
38
- if method_name[-1] == '=' # A setter method
39
- getter_name = method_name[0..-2]
40
- if set_value.class < Exchange # This would be prerequisite exchange
41
- define_singleton_method(getter_name) { set_value }
42
- self[getter_name] = set_value.id if set_value.respond_to?(:id)
43
- else
44
- self[getter_name] = set_value
45
- end
46
- else
47
- super
48
- end
49
- end
50
-
51
- # Used for setters that are not defined
52
- # @param [String] method_name Name of method
53
- # @param [Array] args List of arguments to method
54
- def respond_to_missing?(method_name, *args)
55
- method_name[-1] == '=' || super
56
- end
57
-
58
- # Makes request, caching the response and returning self
59
- # Used by FactoryBot
60
- # @return [Self] Return itself so methods can be called on itself afterwards
61
- def save!
62
- @retry_for_success = @fail_factory ? false : true
63
- previous_setting = Soaspec.log_warnings
64
- Soaspec.log_warnings = false # Don't log this warning as result of call not being used
65
- call
66
- Soaspec.log_warnings = previous_setting
67
- self
68
- end
69
- end
70
- end
1
+ # frozen_string_literal: true
2
+
3
+ module Soaspec
4
+ # Methods to help build a Request
5
+ module RequestBuilder
6
+ # Specify a url to add onto the base_url of the ExchangeHandler used
7
+ # @param [String] url Url to add onto the base_url of the ExchangeHandler used
8
+ def suburl=(url)
9
+ @override_parameters[:suburl] = url
10
+ end
11
+
12
+ # Specify HTTP method to use. Default is :post
13
+ # @param [Symbol] method HTTP method. E.g, :get, :patch
14
+ def method=(method)
15
+ @override_parameters[:method] = method
16
+ end
17
+
18
+ # Set a parameter request in the request body.
19
+ # Can be used to build a request over several steps (e.g Cucumber)
20
+ # Will be used with FactoryBot
21
+ #
22
+ # @example
23
+ # exchange['name'] = 'tester'
24
+ # # Will set { name: tester } in the response, formatting as JSON or XML depending on REST / SOAP
25
+ # @param [String, Symbol] key Name of request element to set
26
+ # @param [String] value Value to set request element to
27
+ def []=(key, value)
28
+ @override_parameters[:body] ||= {}
29
+ @override_parameters[:body][key] = value
30
+ end
31
+
32
+ # Implement undefined setter with []= for FactoryBot to use without needing to define params to set
33
+ # @param [Object] method_name Name of method not defined
34
+ # @param [Object] args Arguments passed to method
35
+ # @param [Object] block Block passed to method
36
+ def method_missing(method_name, *args, &block)
37
+ set_value = args.first
38
+ if method_name[-1] == '=' # A setter method
39
+ getter_name = method_name[0..-2]
40
+ if set_value.class < Exchange # This would be prerequisite exchange
41
+ define_singleton_method(getter_name) { set_value }
42
+ self[getter_name] = set_value.id if set_value.respond_to?(:id)
43
+ else
44
+ self[getter_name] = set_value
45
+ end
46
+ else
47
+ super
48
+ end
49
+ end
50
+
51
+ # Used for setters that are not defined
52
+ # @param [String] method_name Name of method
53
+ # @param [Array] args List of arguments to method
54
+ def respond_to_missing?(method_name, *args)
55
+ method_name[-1] == '=' || super
56
+ end
57
+
58
+ # Makes request, caching the response and returning self
59
+ # Used by FactoryBot
60
+ # @return [Self] Return itself so methods can be called on itself afterwards
61
+ def save!
62
+ @retry_for_success = @fail_factory ? false : true
63
+ previous_setting = Soaspec.log_warnings
64
+ Soaspec.log_warnings = false # Don't log this warning as result of call not being used
65
+ call
66
+ Soaspec.log_warnings = previous_setting
67
+ self
68
+ end
69
+ end
70
+ end
@@ -1,24 +1,24 @@
1
- # frozen_string_literal: true
2
-
3
- module Soaspec
4
- # Enables Exchange to store and retrieve variables so that one
5
- # exchange can make assertions based on a previous one
6
- module VariableStorer
7
- # Stores a value in the api handler that can be accessed by the provided name
8
- # @param [Symbol] name Name of method to use to access this value within handler
9
- # @param [String] value Path to value to store
10
- def store(name, value)
11
- exchange_handler.store(name, self[value])
12
- end
13
-
14
- # Retrieve the stored value from the Api Handler
15
- # @param [String, Symbol] name Name of value to retrieve
16
- # @return [Object] value from the Api Handler stored previously
17
- def retrieve(name)
18
- method = '__stored_val__' + name.to_s
19
- raise ArgumentError('Value not stored at ') unless exchange_handler.respond_to? method
20
-
21
- exchange_handler.send(method)
22
- end
23
- end
24
- end
1
+ # frozen_string_literal: true
2
+
3
+ module Soaspec
4
+ # Enables Exchange to store and retrieve variables so that one
5
+ # exchange can make assertions based on a previous one
6
+ module VariableStorer
7
+ # Stores a value in the api handler that can be accessed by the provided name
8
+ # @param [Symbol] name Name of method to use to access this value within handler
9
+ # @param [String] value Path to value to store
10
+ def store(name, value)
11
+ exchange_handler.store(name, self[value])
12
+ end
13
+
14
+ # Retrieve the stored value from the Api Handler
15
+ # @param [String, Symbol] name Name of value to retrieve
16
+ # @return [Object] value from the Api Handler stored previously
17
+ def retrieve(name)
18
+ method = '__stored_val__' + name.to_s
19
+ raise ArgumentError('Value not stored at ') unless exchange_handler.respond_to? method
20
+
21
+ exchange_handler.send(method)
22
+ end
23
+ end
24
+ end
@@ -1,98 +1,98 @@
1
- # frozen_string_literal: true
2
-
3
- require_relative 'handler_accessors'
4
- require_relative 'exchange_handler_defaults'
5
-
6
- module Soaspec
7
- # Inherit this for a class describing how to implement a particular exchange.
8
- # Has methods common to Soaspec framework for working with Exchange/Handler pair
9
- class ExchangeHandler
10
- extend Soaspec::HandlerAccessors
11
- include ExchangeHandlerDefaults
12
-
13
- # @return [Exception] Exception if raised
14
- attr_accessor :exception
15
-
16
- # Use an instance of this ExchangeHandler in any further Exchange's
17
- # This is a convenience method as it creates an ExchangeHandler behind the scenes
18
- # @return [ExchangeHandler] Exchange handler instance created
19
- def self.use
20
- new.use
21
- end
22
-
23
- # @return [String] Name of the template file to be used in the API request
24
- attr_reader :template_name
25
-
26
- # Explicitly defined elements for which a path has been predefined
27
- def elements
28
- public_methods.select { |i| i[/__custom_path_.+/] }
29
- end
30
-
31
- # Set instance variable name
32
- # @param [String, Symbol] name Name used when describing API test
33
- # @param [Hash] _options Parameters defining handler. Used in descendants
34
- def initialize(name = self.class.to_s, _options = {})
35
- use
36
- @request_option = :hash
37
- raise ArgumentError, 'Cannot define both template_name and default_hash' if respond_to?(:template_name_value) && respond_to?(:default_hash_value)
38
-
39
- @template_name = respond_to?(:template_name_value) ? template_name_value : ''
40
- @default_hash = respond_to?(:default_hash_value) ? default_hash_value : {}
41
- @name = name
42
- end
43
-
44
- # Set Api handler used by Exchange class to this handler
45
- # @return [Self]
46
- def use
47
- Soaspec.api_handler = self
48
- self
49
- end
50
-
51
- # Sets api handler variable globally. This is used in 'Exchange' class
52
- # @return [String] Name set upon initialisation
53
- def to_s
54
- use
55
- @name.to_s
56
- end
57
-
58
- # Set the default hash representing data to be used in making a request
59
- # This will set the @request_option instance variable too
60
- # @param [Hash] hash Hash to send in request body by default
61
- def default_hash=(hash)
62
- @request_option = :hash
63
- @default_hash = Soaspec.always_use_keys? ? hash.transform_keys_to_symbols : hash
64
- end
65
-
66
- # Set the request option type and the template name
67
- # Erb is used to parse the template file, executing Ruby code in `<%= %>` blocks to work out the final request
68
- # @param [String] name Name of file inside 'template' folder excluding extension
69
- def template_name=(name)
70
- @request_option = :template
71
- @template_name = name
72
- end
73
-
74
- # Stores a value in a method that can be accessed by the provided name
75
- # @param [Symbol] name Name of method to use to access this value within handler
76
- # @param [String] value Value to store
77
- def store(name, value)
78
- define_singleton_method('__stored_val__' + name.to_s) { value }
79
- end
80
-
81
- # Set instance variable for each key in hash remove it from Hash
82
- # @param [Hash] hash with items to remove from
83
- # @param [Array] keys List of keys to remove from hash, setting each one
84
- def set_remove_keys(hash, keys)
85
- keys.each { |key| set_remove_key(hash, key) }
86
- end
87
-
88
- # Set instance variable and remove it from Hash
89
- # @param [Hash] hash Hash to remove/retrieve keys from
90
- # @param [String,Symbol] key Key to remove and to set instance variable for
91
- def set_remove_key(hash, key)
92
- return unless hash.key? key
93
-
94
- __send__("#{key}=", hash[key])
95
- hash.delete key
96
- end
97
- end
98
- end
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'handler_accessors'
4
+ require_relative 'exchange_handler_defaults'
5
+
6
+ module Soaspec
7
+ # Inherit this for a class describing how to implement a particular exchange.
8
+ # Has methods common to Soaspec framework for working with Exchange/Handler pair
9
+ class ExchangeHandler
10
+ extend Soaspec::HandlerAccessors
11
+ include ExchangeHandlerDefaults
12
+
13
+ # @return [Exception] Exception if raised
14
+ attr_accessor :exception
15
+
16
+ # Use an instance of this ExchangeHandler in any further Exchange's
17
+ # This is a convenience method as it creates an ExchangeHandler behind the scenes
18
+ # @return [ExchangeHandler] Exchange handler instance created
19
+ def self.use
20
+ new.use
21
+ end
22
+
23
+ # @return [String] Name of the template file to be used in the API request
24
+ attr_reader :template_name
25
+
26
+ # Explicitly defined elements for which a path has been predefined
27
+ def elements
28
+ public_methods.select { |i| i[/__custom_path_.+/] }
29
+ end
30
+
31
+ # Set instance variable name
32
+ # @param [String, Symbol] name Name used when describing API test
33
+ # @param [Hash] _options Parameters defining handler. Used in descendants
34
+ def initialize(name = self.class.to_s, _options = {})
35
+ use
36
+ @request_option = :hash
37
+ raise ArgumentError, 'Cannot define both template_name and default_hash' if respond_to?(:template_name_value) && respond_to?(:default_hash_value)
38
+
39
+ @template_name = respond_to?(:template_name_value) ? template_name_value : ''
40
+ @default_hash = respond_to?(:default_hash_value) ? default_hash_value : {}
41
+ @name = name
42
+ end
43
+
44
+ # Set Api handler used by Exchange class to this handler
45
+ # @return [Self]
46
+ def use
47
+ Soaspec.api_handler = self
48
+ self
49
+ end
50
+
51
+ # Sets api handler variable globally. This is used in 'Exchange' class
52
+ # @return [String] Name set upon initialisation
53
+ def to_s
54
+ use
55
+ @name.to_s
56
+ end
57
+
58
+ # Set the default hash representing data to be used in making a request
59
+ # This will set the @request_option instance variable too
60
+ # @param [Hash] hash Hash to send in request body by default
61
+ def default_hash=(hash)
62
+ @request_option = :hash
63
+ @default_hash = Soaspec.always_use_keys? ? hash.transform_keys_to_symbols : hash
64
+ end
65
+
66
+ # Set the request option type and the template name
67
+ # Erb is used to parse the template file, executing Ruby code in `<%= %>` blocks to work out the final request
68
+ # @param [String] name Name of file inside 'template' folder excluding extension
69
+ def template_name=(name)
70
+ @request_option = :template
71
+ @template_name = name
72
+ end
73
+
74
+ # Stores a value in a method that can be accessed by the provided name
75
+ # @param [Symbol] name Name of method to use to access this value within handler
76
+ # @param [String] value Value to store
77
+ def store(name, value)
78
+ define_singleton_method('__stored_val__' + name.to_s) { value }
79
+ end
80
+
81
+ # Set instance variable for each key in hash remove it from Hash
82
+ # @param [Hash] hash with items to remove from
83
+ # @param [Array] keys List of keys to remove from hash, setting each one
84
+ def set_remove_keys(hash, keys)
85
+ keys.each { |key| set_remove_key(hash, key) }
86
+ end
87
+
88
+ # Set instance variable and remove it from Hash
89
+ # @param [Hash] hash Hash to remove/retrieve keys from
90
+ # @param [String,Symbol] key Key to remove and to set instance variable for
91
+ def set_remove_key(hash, key)
92
+ return unless hash.key? key
93
+
94
+ __send__("#{key}=", hash[key])
95
+ hash.delete key
96
+ end
97
+ end
98
+ end