t56k
t56k

Reputation: 6981

Find and replace only matching first result

I've written a method to find and replace a string in a bigger string like so:

def user_gsubbed_text
  text.include?('##')
    var = text.match(/##\w+/).to_s.tr('##', '')
    text.gsub!(var, document.user.send(var.to_sym)).tr('##', '')
  else
    text
  end
end

So that if ##phone is in the string it will be replaced with the user's phone number. It works fine in the first sense, but given a string like this:

"Call me on ##phone or email me at ##email."

It replaces only the phone number and not the email address. What am I doing wrong?

Upvotes: 0

Views: 85

Answers (2)

Cary Swoveland
Cary Swoveland

Reputation: 110675

If I understand the question correctly, you could use String#gsub with a hash:

h = { "##phone"=>"123-456-7899", "##email"=>"[email protected]" } 

str = "Call me on ##phone or email me at ##email."

str.gsub(/\#\#\w+/, h)
  #=> "Call me on 123-456-7899 or email me at [email protected]." 

or:

h.default_proc = proc { |h,k| k }
str.gsub(/\S+/, h)
  #=> "Call me on 123-456-7899 or email me at [email protected]." 

The latter is a bit more flexible, should you want to add additional key-value pairs to the hash.

Upvotes: 2

Amadan
Amadan

Reputation: 198324

You don't have any kind of loop. Your code simply finds the first ##foo, then extracts the variable name, then replaces that variable globally. Other #bars are not touched at all.

The easy way is to use the block-form of gsub!:

def user_gsubbed_text(text)
  text.gsub!(/##(\w+)/) do |match|
    document.user.send($1.to_sym)
  end
end

Upvotes: 3

Related Questions