What are percent strings?
Ruby is known for providing multiple ways to accomplish the same thing, for instance, creating strings. We can create a new instance of the String class.
string_instance = String.new("largesse")
=> "largesse"
Largesse refers to the act of generously giving money or to the money given. It can also mean "generosity."
-Merriam-Webster.com
Or, more likely, we would use the string literal syntax.
string_literal = "nascent"
=> "nascent"
Nascent means "coming or having recently come into existence."
-Merriam-Webster.com
They are both instances of the String class.
string_instance.is_a? String
=> true
string_literal.class
=> String
There's another way...
Do you know about Ruby "Percent Strings"? As the name implies, they use a percent sign.
percent_string = %(elucidate)
=> "elucidate"
Elucidate means "to make something that is hard to understand clear or easy to understand.
-Mirriam-Webster.com
Cool! But why would we need this? Hopefully I can elucidate with a practical example. Even if your Ruby skills are in nascent state, you can still take full advantage of the various ways to make Strings. Thanks, Ruby, for your largesse in this area.
The percent operator in Ruby has several uses. Here's one I find helpful: %w[]
.
Typing a long list of strings into an array can be tedious because of all the quotation marks and commas. We don't have to type them! Let's let Ruby do it for us, using the percent string array notation.
cool_words = %w[nascent largesse elucidate]
=> ["nascent", "largesse", "elucidate"]
I don't know what "w" stands for. If you do, maybe you can leave a comment. I consider it to mean "words". That's how I remember it. Here's a few more.
%s[checkout these symbols]
=> [:checkout, :these, :symbols]
Using %W
with an uppercase 'W' allows for interpolation.
my_favorite_color = "teal"
cool_colors = %W[lapis\ lazuli smaragdine mikado xanadu #{my_favorite_color}]
=> ["lapis lazuli", "smaragdine", "mikado", "xanadu", "teal"]
A Practical Example with the #include? Method
This is really helpful.
You have a collection of objects that you want to filter based on data in the form a string. Checkout this array of accounts.
# lot's of them!
accounts.size
=> 36671
# they have a status attribute
accounts.first.status
=> 'Disabled'
accounts.last.status
=> 'Canceled'
accounts[2838].status
=> 'Active'
Now, you need to add a Boolean attribute to the Account class called @do_not_display
that depends on the status. Since you want to set this dynamically, you add a private method to your class called get_do_not_display
which checks the status and returns true if the account matches a list of statuses.
# hmm... how should we do this?
# Oh! I know!
class Account
attr_accessor :status, :do_not_display
def initialize status
@status = status
@do_not_display = get_do_not_display
end
private
def get_do_not_display
return true if @status == "Disabled" || "Canceled"
false
end
end
That works, but what if your list of strings to filter by is growing and changing based on the needs of the application? Here's a better way that uses the percent string array.
def get_do_not_display
return true if %w[DISABLED CANCELED FORGOTTEN ABANDONED DESTROYED BROKEN HACKED DELINQUENT OTHER].include? @status.upcase.strip
return false
end
Finally, here's how you might use this attribute in your template.
#accounts.html.erb
<ul>
<% Account.each do |account| %>
<li>
<%= account.id unless account.do_not_display %>
</li>
<% end %>
</ul>
Top comments (0)