0

If I do

template_string = "class=btn submit-button %<additional_classes>"
format(template_string, additional_classes: 'some-class')

it works. However, if I do

template_string = "class='btn submit-button %<additional_classes>'"
format(template_string, additional_classes: 'some-class')

it fails, giving

ArgumentError:
  malformed format string - %'

(Notice the quotation marks surrounding the classes in the second template_string - this is the only difference between the two blocks of Ruby code). How do I make it work? In other words, how do I produce the following?

class='btn submit-button some-class'

I don't believe that I can just use interpolation, because sometimes I need to pass in other variables. In other words, I can't do

additional_classes = 'some-class'
"class='btn submit-button #{additional_classes}'"

because sometimes I want to reuse the same string "template" but pass in other variables, to produce strings such as the following:

class='btn submit-button some-other-class'

or

class='btn submit-button some-third-class'

2 Answers 2

2

From the fine manual:

format(format_string [, arguments...] ) → string
[...]
For more complex formatting, Ruby supports a reference by name. %<name>s style uses format style, but %{name} style doesn't.

The documentation isn't as clear as it could be but when you use the %<...> form, it is expecting to see %<name>s where name is the hash key and s is the format type: s for string, d for number, ... If you say:

%<additional_classes>'

then format will try to interpret ' as a type when there is no such type specifier so you get an ArgumentError because the format string is malformed.

You probably want to use the %{...} form instead:

template_string = "class='btn submit-button %{additional_classes}'"
#--------------------------------------------^------------------^
Sign up to request clarification or add additional context in comments.

Comments

2

Your format string is missing the field type specifier. The field type specifier is mandatory in a format string.

It is not clear to me why the first example does not raise an error, since the mandatory field type specifier is missing. It could be a bug, or I am completely misreading the documentation.

However, it is not clear to me why you consider this example to work:

template_string = "class=btn submit-button %<additional_classes>"
format(template_string, additional_classes: 'some-class')
#=> 'class=btn submit-button %'
#                            ↑

As you can see, the % is not interpreted as the part of a format string but as a literal %. I would consider this a bug, it should raise an error, just like the second example does.

In the second example, you can clearly see the problem:

ArgumentError: malformed format string - %'
                                          ↑

Since a format string must have a field type specifier, and the only character after the % (except the field name) is ', this is interpreted as the field type specifier. And since ' is not a legal field type, format raises an error in which it explicitly tells you that it interpreted the ' as part of the format string.

Since you want to format strings, you should use the s (string) field type specifier:

template_string = "class=btn 'submit-button %<additional_classes>s'"
#                                                                ↑

format(template_string, additional_classes: 'some-class')
#=> "class=btn 'submit-button some-class'"
#                             ↑↑↑↑↑↑↑↑↑↑↑

Alternatively, you can use the %{} form:

template_string = "class=btn 'submit-button %{additional_classes}'"
#                                            ↑                  ↑

format(template_string, additional_classes: 'some-class')
#=> "class=btn 'submit-button some-class'"
#                             ↑↑↑↑↑↑↑↑↑↑↑

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.