Module: Line::Bot::V2::Utils
- Defined in:
- lib/line/bot/v2/utils.rb
Constant Summary collapse
- NO_CAMELIZE_PARENT_KEYS =
NOTE: Although it should be set in the request class side,
it can only be set here because requests in Hash are also permitted. If there is a mix of camelize and non-camelize cases even with the same key name, breaking change that does not allow Hash requests will be necessary. %w(substitution).freeze
- PATH_TRAVERSAL =
Matches a path that contains a “.” or “..” segment (literal or percent-encoded), so a path parameter cannot escape its endpoint. See square/retrofit’s RequestBuilder for the same idea.
%r{\A(?:.*/)?(?:\.|%2e|%2E){1,2}(?:/.*)?\z}.freeze
Class Method Summary collapse
-
.build_path(path_template, params) ⇒ Object
NOTE: line-bot-sdk-ruby users should not use this.
-
.camelize(str) ⇒ Object
NOTE: line-bot-sdk-ruby users should not use this.
-
.deep_camelize(object) ⇒ Object
NOTE: line-bot-sdk-ruby users should not use this.
-
.deep_compact(object) ⇒ Object
NOTE: line-bot-sdk-ruby users should not use this.
-
.deep_convert_reserved_words(object) ⇒ Object
NOTE: line-bot-sdk-ruby users should not use this.
-
.deep_symbolize(object) ⇒ Object
NOTE: line-bot-sdk-ruby users should not use this.
-
.deep_to_hash(object) ⇒ Object
NOTE: line-bot-sdk-ruby users should not use this.
-
.deep_underscore(hash) ⇒ Object
NOTE: line-bot-sdk-ruby users should not use this.
-
.hash_to_struct(hash) ⇒ Object
NOTE: line-bot-sdk-ruby users should not use this.
Class Method Details
.build_path(path_template, params) ⇒ Object
NOTE: line-bot-sdk-ruby users should not use this. Breaking changes may occur, so use at your own risk.
Substitutes path parameters into a path template and rejects any result that would let a parameter perform path traversal.
21 22 23 24 25 26 27 28 29 30 31 32 33 34 |
# File 'lib/line/bot/v2/utils.rb', line 21 def self.build_path(path_template, params) path = path_template params.each do |name, value| raise ArgumentError, "#{name} is required" if value.nil? path = path.gsub("{#{name}}", URI.encode_uri_component(value.to_s)) end if PATH_TRAVERSAL.match?(path) raise ArgumentError, "Path parameters shouldn't perform path traversal ('.' or '..'): #{path}" end path end |
.camelize(str) ⇒ Object
NOTE: line-bot-sdk-ruby users should not use this. Breaking changes may occur, so use at your own risk.
162 163 164 |
# File 'lib/line/bot/v2/utils.rb', line 162 def self.camelize(str) str.to_s.split('_').inject { |memo, word| memo + word.capitalize } end |
.deep_camelize(object) ⇒ Object
NOTE: line-bot-sdk-ruby users should not use this. Breaking changes may occur, so use at your own risk.
98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 |
# File 'lib/line/bot/v2/utils.rb', line 98 def self.deep_camelize(object) case object when Array object.map { |item| deep_camelize(item) } when Hash object.each_with_object({}) do |(k, v), new_object| # steep:ignore UnannotatedEmptyCollection if NO_CAMELIZE_PARENT_KEYS.include?(k.to_s) new_object[k.to_sym] = if v.is_a?(Hash) v.transform_keys(&:to_sym).transform_values { deep_camelize(_1) } else v end else camel_key = camelize(k)&.to_sym new_object[camel_key] = v.is_a?(Array) || v.is_a?(Hash) ? deep_camelize(v) : v if camel_key end end else object end end |
.deep_compact(object) ⇒ Object
NOTE: line-bot-sdk-ruby users should not use this. Breaking changes may occur, so use at your own risk.
121 122 123 124 125 126 127 128 129 130 131 132 133 |
# File 'lib/line/bot/v2/utils.rb', line 121 def self.deep_compact(object) case object when Hash object.each_with_object({}) do |(k, v), new_hash| # steep:ignore UnannotatedEmptyCollection new_value = deep_compact(v) new_hash[k] = new_value unless new_value.nil? || (new_value.is_a?(Hash) && new_value.empty?) end when Array object.map { |item| deep_compact(item) }.compact else object end end |
.deep_convert_reserved_words(object) ⇒ Object
NOTE: line-bot-sdk-ruby users should not use this. Breaking changes may occur, so use at your own risk.
136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 |
# File 'lib/line/bot/v2/utils.rb', line 136 def self.deep_convert_reserved_words(object) case object when Hash object.each_with_object({}) do |(key, value), new_hash| # steep:ignore UnannotatedEmptyCollection new_key = if Line::Bot::V2::RESERVED_WORDS.include?(key.to_sym) "_#{key}" else key end new_hash[new_key] = deep_convert_reserved_words(value) end when Array object.map { |element| deep_convert_reserved_words(element) } else object end end |
.deep_symbolize(object) ⇒ Object
NOTE: line-bot-sdk-ruby users should not use this. Breaking changes may occur, so use at your own risk.
53 54 55 56 57 58 59 60 61 62 63 64 65 |
# File 'lib/line/bot/v2/utils.rb', line 53 def self.deep_symbolize(object) case object when Hash object.each_with_object({}) do |(key, value), new_hash| # steep:ignore UnannotatedEmptyCollection sym_key = key.is_a?(String) ? key.to_sym : key new_hash[sym_key] = deep_symbolize(value) end when Array object.map { |element| deep_symbolize(element) } else object end end |
.deep_to_hash(object) ⇒ Object
NOTE: line-bot-sdk-ruby users should not use this. Breaking changes may occur, so use at your own risk.
68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 |
# File 'lib/line/bot/v2/utils.rb', line 68 def self.deep_to_hash(object) if object.is_a?(Array) object.map { |item| deep_to_hash(item) } elsif object.is_a?(Hash) result = object.transform_keys do |k| if k.to_s.start_with?('_') && Line::Bot::V2::RESERVED_WORDS.include?(k.to_s.delete_prefix('_').to_sym) k.to_s.delete_prefix('_').to_sym else k.to_sym end end result.transform_values { |v| deep_to_hash(v) } elsif object.instance_variables.empty? object else object.instance_variables.each_with_object({}) do |var, hash| # steep:ignore UnannotatedEmptyCollection value = object.instance_variable_get(var) key = var.to_s.delete('@') if key.start_with?('_') && Line::Bot::V2::RESERVED_WORDS.include?(key.delete_prefix('_').to_sym) key = key.delete_prefix('_') end key = key.to_sym hash[key] = deep_to_hash(value) end end end |
.deep_underscore(hash) ⇒ Object
NOTE: line-bot-sdk-ruby users should not use this. Breaking changes may occur, so use at your own risk.
37 38 39 40 41 42 43 44 45 46 47 48 49 50 |
# File 'lib/line/bot/v2/utils.rb', line 37 def self.deep_underscore(hash) hash.each_with_object({}) do |(key, value), result| # steep:ignore UnannotatedEmptyCollection # Convert key to string if it's a symbol, then apply the regex new_key = key.to_s.gsub(/([A-Z\d]+)([A-Z][a-z])|([a-z\d])([A-Z])/, '\1\3_\2\4').downcase.to_sym new_value = if value.is_a?(Hash) deep_underscore(value) elsif value.is_a?(Array) value.map { |v| v.is_a?(Hash) ? deep_underscore(v) : v } else value end result[new_key] = new_value end end |
.hash_to_struct(hash) ⇒ Object
NOTE: line-bot-sdk-ruby users should not use this. Breaking changes may occur, so use at your own risk.
155 156 157 158 159 |
# File 'lib/line/bot/v2/utils.rb', line 155 def self.hash_to_struct(hash) struct_klass = Struct.new(*hash.keys.map(&:to_sym)) struct_values = hash.map { |_k, v| v.is_a?(Hash) ? hash_to_struct(v) : v } struct_klass.new(*struct_values) end |