Home > Enterprise >  How to have ruby conditionally check if variables exist in a string?
How to have ruby conditionally check if variables exist in a string?

Time:10-14

So I have a string from a rendered template that looks like

"Dear {{user_name}},\r\n\r\nThank you for your purchase. If you have any questions, we are happy to help.\r\n\r\n\r\n{{company_name}}\r\n{{company_phone_number}}\r\n"

All those variables like {{user_name}} are optional and do not need to be included but I want to check that if they are, they have {{ in front of the variable name. I am using liquid to parse and render the template and couldn't get it to catch if the user only uses 1 (or no) opening brackets. I was only able to catch the proper number of closing brackets. So I wrote a method to check that if these variables exist, they have the correct opening brackets. It only works, however, if all those variables are found.

here is my method:

  def validate_opening_brackets?(template)
    text = %w(user_name company_name company_phone_number)
    text.all? do |variable|
      next unless template.include? variable
      template.include? "{{#{variable}"
    end
  end

It works, but only if all variables are present. If, for example, the template created by the user does not include user_name, then it will return false. I've also done this loop using each, and creating a variable outside of the block that I assign false if the conditions are not met. I would really, however, like to get this to work using the all? method, as I can just return a boolean and it's cleaner.

CodePudding user response:

If the question is about how to rewrite the all? block to make it return true if all present variable names have two brackets before them and false otherwise then you could use something like this:

def validate_opening_brackets?(template)
  variables = %w(user_name company_name company_phone_number)
  variables.all? do |variable|
    !template.include?(variable) || template.include?("{{#{variable}")
  end
end

CodePudding user response:

TL;DR

There are multiple ways to do this, but the easiest way I can think of is to simply prefix/postfix a regular expression with the escaped characters used by Mustache/Liquid, and using alternation to check for each of your variable names within the template variable characters (e.g. double curly braces). You can then use String#scan and then return a Boolean from Enumerable#any? based on the contents of the Array returned by from #scan.

This works with your posted example, but there may certainly be other use cases where you need a more complex solution. YMMV.

Example Code

This solution escapes the leading and trailing { and } characters to avoid having them treated as special characters, and then interpolates the variable names with | for alternation. It returns a Boolean depending on whether templated variables are found.

def template_string_has_interpolations? str
  var_names = %w[user_name company_name company_phone_number]
  regexp = /\{\{#{var_names.join ?|}\}\}/
  str.scan(regexp).any?
end

Tested Examples

template_string_has_interpolations? "Dear {{user_name}},\r\n\r\nThank you for your purchase. If you have any questions, we are happy to help.\r\n\r\n\r\n{{company_name}}\r\n{{company_phone_number}}\r\n"
#=> true
template_string_has_interpolations? "Dear Customer,\r\n\r\nThank you for your purchase. If you have any questions, we are happy to help.\r\n\r\n\r\nCompany, Inc.\r\n(555) 555-5555\r\n"
#=> false 
  • Related