简体   繁体   中英

How can I have a default in case the substituted value for gsub is null?

I currently have this as one of many in a long string of gsubs:

gsub("{Company}", contact.company_name.clear_company.to_s).

But sometimes contact.company_name is null.

So I broke out from the long string something like this:

subject.gsub("{Company}", contact.company_name.clear_company.to_s) unless contact.company_name.blank?

But this looks ugly and cumbersome. Because here is what the entire string looks like, each one could be potentially nil which would throw an error:

12     sub_message =
 13       message.gsub("{FirstName}", contact.first_name).
 14            gsub("{LastName}", contact.last_name).
 15            gsub("{Title}", contact.title || "blank").
 16        #    gsub("{Company}", contact.company_name.clear_company).
 17            gsub("{Colleagues}", colleagues.to_sentence).
 18            gsub("{NextWeek}", next_week.strftime("%A, %B %d")).
 19            gsub("{FollowingWeek}", (Date.today + 14.days).strftime("%A, %B %d")).
 20            gsub("{UserFirstName}", contact.user.first_name).
 21            gsub("{UserLastName}", contact.user.last_name).
 22            gsub("{City}", contact.address.city.titleize || "default city").
 23            gsub("{State}", contact.address.state || "default state").
 24            gsub("{Zip}", contact.address.zip || "default zip" ).
 25            gsub("{Street1}", contact.address.street1.titleize || "default street").
 26            gsub("{Today}", (Date.today).strftime("%A, %B %d")).
 27            gsub("{CustomField1}", contact.custom_field_1.to_s).
 28            gsub("{PageBreak}", "p{page-break-after: always}. ")

I'd like to do something like this

gsub("{Company}", contact.company_name.clear_company.to_s || "").

But it doesn't seem to work. Ideas?

The cleanest way is to use the string templating feature of Ruby 1.9.2 and you can avoid the gsub altogether.

"%{company}" % {:company => contact.company_name.clear_company || ""}

The reason this doesn't work is because you are casting it to a String. Even if it is nil you are essentially then calling nil.to_s which will return "" (a blank string) and the || operator is rendered useless.

ruby-1.9.2-p136 :004 > "" || 1
 => "" 
ruby-1.9.2-p136 :005 > nil.to_s || 1
 => "" 

Now of course if your default substituted value does happen to be a blank string then this should work fine.

I would write a function to use as the second argument in your gsub call.

def d(s)
  s.blank? ? $DEFAULT : s
end

# Call it like this,
$DEFAULT = "default_sub"
gsub("{Company}", d contact.company_name.clear_company)

I'm retaining my other answer, because it's a straightforward answer for 1.9.2.

In your case, I'd separate the replacements from the replacement method, which you can put in a helper to keep your views clean.

The replacements can be set up in a hash:

replacements = {
  "{Company}" => contact.company_name.clear_company || "",
  "{FirstName}" => contact.first_name,
  "{LastName}" => contact.last_name,
  "{Title}" => contact.title || "blank",
}

Then the helper method would look something like this:

def replace(string, replacements = {})
  replacements.each do |k,v|
    string.gsub!(k,v)
  end
  string
end

And to use it you'd just do the following:

<%= replace("message", replacements) %>

Another advantage of this strategy is that when you upgrade to 1.9.2, the replacements are close to the form that can be used by the string templating feature.

If your needs are any more complex than what you've posted, I'd consider using the liquid templating engine to process your replacements.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM