7

I am trying to iterate through elements of a struct, look for strings that include the format {...}, and replace them with a corresponding string from a hash. This is the data I'm using:

Request = Struct.new(:method, :url, :user, :password)
request = Request.new
request.user = "{user} {name}"
request.password = "{password}"
parameters = {"user" => "first", "name" => "last", "password" => "secret"}

This is attempt 1:

request.each do |value|
  value.gsub!(/{(.+?)}/, parameters["\1"])
end

In this attempt, parameters["\1"] == nil.

Attempt 2:

request.each do |value|
  value.scan(/{(.+?)}/) do |match|
    value.gsub!(/{(.+?)}/, parameters[match[0]])
  end
end

This results in request.user == "first first". Trying parameters[match] results in nil.

Can anyone assist solving this?

2 Answers 2

5

Neither of your attempt will work because arguments of gsub! are evaluated prior to the call of gsub!. parameters[...] will be evaluated prior to replacement, so it has no way to reflect the match. In addition, "\1" will not be replaced by the first capture even if that string was the direct argument of gsub!. You need to escape the escape character like "\\1". To make it work, you need to give a block to gsub!.

But instead of doing that, try to use what already is there. You should use string format %{} and use symbols for the hash.

request.user = "%{user} %{name}"
request.password = "%{password}"
parameters = {user: "first", name: "last", password: "secret"}
request.each do |value|
  value.replace(value % parameters)
end
Sign up to request clarification or add additional context in comments.

1 Comment

Hi @sawa, your answer is great, but can you please explain the magic behind value % parameters. I have not seen the % operator used in this way before.
1

You can use gsub with a block.

request.each do |e|
  e.gsub!(/{.+?}/) { |m| parameters[m[1...-1]] } if e
end

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.