Home > Software design >  Converting Ruby Hash into string with escapes
Converting Ruby Hash into string with escapes

Time:04-10

I have a Hash which needs to be converted in a String with escaped characters.

{name: "fakename"}

and should end up like this:

'name:\'fakename\'

I don't know how this type of string is called. Maybe there is an already existing method, which I simply don't know...

At the end I would do something like this:

name = {name: "fakename"}

metadata = {}
metadata['foo'] = 'bar'

"#{name} AND #{metadata}"

which ends up in that:

'name:\'fakename\' AND metadata[\'foo\']:\'bar\''

Context: This query a requirement to search Stripe API: https://stripe.com/docs/api/customers/search

CodePudding user response:

If possible I would use Stripe's gem.

In case you can't use it, this piece of code extracted from the gem should help you encode the query parameters.

require 'cgi'

# Copied from here: https://github.com/stripe/stripe-ruby/blob/a06b1477e7c28f299222de454fa387e53bfd2c66/lib/stripe/util.rb
class Util
  def self.flatten_params(params, parent_key = nil)
    result = []

    # do not sort the final output because arrays (and arrays of hashes
    # especially) can be order sensitive, but do sort incoming parameters
    params.each do |key, value|
      calculated_key = parent_key ? "#{parent_key}[#{key}]" : key.to_s
      if value.is_a?(Hash)
        result  = flatten_params(value, calculated_key)
      elsif value.is_a?(Array)
        result  = flatten_params_array(value, calculated_key)
      else
        result << [calculated_key, value]
      end
    end

    result
  end

  def self.flatten_params_array(value, calculated_key)
    result = []
    value.each_with_index do |elem, i|
      if elem.is_a?(Hash)
        result  = flatten_params(elem, "#{calculated_key}[#{i}]")
      elsif elem.is_a?(Array)
        result  = flatten_params_array(elem, calculated_key)
      else
        result << ["#{calculated_key}[#{i}]", elem]
      end
    end
    result
  end

  def self.url_encode(key)
    CGI.escape(key.to_s).
      # Don't use strict form encoding by changing the square bracket control
      # characters back to their literals. This is fine by the server, and
      # makes these parameter strings easier to read.
      gsub("[", "[").gsub("]", "]")
  end  
end

params = { name: 'fakename', metadata: { foo: 'bar' } }
Util.flatten_params(params).map { |k, v| "#{Util.url_encode(k)}=#{Util.url_encode(v)}" }.join("&")

CodePudding user response:

I use it now with that string, which works... Quite straigt forward:

"email:\'#{email}\'"


email = "[email protected]"
key = "foo"
value = "bar"
["email:\'#{email}\'", "metadata[\'#{key}\']:\'#{value}\'"].join(" AND ")
=> "email:'[email protected]' AND metadata['foo']:'bar'"

which is accepted by Stripe API

  • Related