What does the Ruby method 'to_sym' do? - ruby

What does the to_sym method do? What is it used for?

to_sym converts a string to a symbol. For example, "a".to_sym becomes :a.
It's not specific to Rails; vanilla Ruby has it as well.
It looks like in some versions of Ruby, a symbol could be converted to and from a Fixnum as well. But irb from Ruby 1.9.2-p0, from ruby-lang.org, doesn't allow that unless you add your own to_sym method to Fixnum. I'm not sure whether Rails does that, but it doesn't seem very useful in any case.

Expanding with useful details on the accepted answer by #cHao:
to_sym is used when the original string variable needs to be converted to a symbol.
In some cases, you can avoid to_sym, by creating the variable as symbol, not string in the first place. For example:
my_str1 = 'foo'
my_str2 = 'bar baz'
my_sym1 = my_str1.to_sym
my_sym2 = my_str2.to_sym
# Best:
my_sym1 = :foo
my_sym2 = :'bar baz'
or
array_of_strings = %w[foo bar baz]
array_of_symbols = array_of_strings.map(&:to_sym)
# Better:
array_of_symbols = %w[foo bar baz].map(&:to_sym)
# Best
array_of_symbols = %i[foo bar baz]
SEE ALSO:
When to use symbols instead of strings in Ruby?
When not to use to_sym in Ruby?
Best way to convert strings to symbols in hash
uppercase %I - Interpolated Array of symbols, separated by whitespace

Related

Add comment to line in multiline %w in ruby

I have a multiline string array via percent string like this:
array = %w(test
foo
bar)
I want to add a comment message to the foo entry, something like
array = %w(test
# TODO: Remove this line after fix #1
foo
bar)
Is there any way to do it without converting it to basic array like this?
array = ['test',
# TODO: Remove this line after fix #1
'foo',
'bar']
I think there is no way to make that work, because %w() evaluates every space delimited element inside it to string.
There's no way from inside the string to make Ruby evaluate that string.
The only and tricky way:
array = %W(test
##foo
bar).reject(&:empty?)
Note capital W and reject

How do I print a Ruby regex variable?

How do I print/display just the part of a regular expression that is between the slashes?
irb> re = /\Ahello\z/
irb> puts "re is /#{re}/"
The result is:
re is /(?-mix:\Ahello\z)/
Whereas I want:
re is /\Ahello\z/
...but not by doing this craziness:
puts "re is /#{re.to_s.gsub( /.*:(.*)\)/, '\1' )}/"
If you want to see the original pattern between the delimiters, use source:
IP_PATTERN = /(?:\d{1,3}\.){3}\d{1,3}/
IP_PATTERN # => /(?:\d{1,3}\.){3}\d{1,3}/
IP_PATTERN.inspect # => "/(?:\\d{1,3}\\.){3}\\d{1,3}/"
IP_PATTERN.to_s # => "(?-mix:(?:\\d{1,3}\\.){3}\\d{1,3})"
Here's what source shows:
IP_PATTERN.source # => "(?:\\d{1,3}\\.){3}\\d{1,3}"
From the documentation:
Returns the original string of the pattern.
/ab+c/ix.source #=> "ab+c"
Note that escape sequences are retained as is.
/\x20\+/.source #=> "\\x20\\+"
NOTE:
It's common to build a complex pattern from small patterns, and it's tempting to use interpolation to insert the simple ones, but that doesn't work as most people think it will. Consider this:
foo = /foo/
bar = /bar/imx
foo_bar = /#{ foo }_#{ bar }/
foo_bar # => /(?-mix:foo)_(?mix:bar)/
Notice that foo_bar has the pattern flags for each of the sub-patterns. Those can REALLY mess you up when trying to match things if you're not aware of their existence. Inside the (?-...) block the pattern can have totally different settings for i, m or x in relation to the outer pattern. Debugging that can make you nuts, worse than trying to debug a complex pattern normally would. How do I know this? I'm a veteran of that particular war.
This is why source is important. It injects the exact pattern, without the flags:
foo_bar = /#{ foo.source}_#{ bar.source}/
foo_bar # => /foo_bar/
Use .inspect instead of .to_s:
> puts "re is #{re.inspect}"
re is /\Ahello\z/

Ruby method help required

I am reading Metaprogramming Ruby book, and there is method, which I cant understant:
def to_alphanumeric(s)
s.gsub /[^\w\s]/, ''
end
I see there is Argument Variable (s), which is called lately and is converted to some weird expression?
What exactly can I do with this method, is he useful?
Following method works just fine:
def to_alphanumeric(s)
s.gsub %r([aeiou]), '<\1>'
end
p = to_alphanumeric("hello")
p p
>> "h<>ll<>"
But if I upgrade method to class, simply calling the method + argv to_alphanumeric, no longer work:
class String
def to_alphanumeric(s)
s.gsub %r([aeiou]), '<\1>'
end
end
p = to_alphanumeric("hello")
p p
undefined method `to_alphanumeric' for String:Class (NoMethodError)
Would it hurt to check the documentation?
http://www.ruby-doc.org/core-2.0/String.html#method-i-gsub
Returns a copy of str with the all occurrences of pattern substituted for the second argument.
The /[^\w\s]/ pattern means "everything that is not a word or whitespace"
Take a look at Rubular, the regular expression /[^\w\s]/ matches special characters like ^, /, or $ which are neither word characters (\w) or whitespace (\s). Therefore the function removes special characters like ^, / or $.
>> "^/$%hel1241lo".gsub /[^\w\s]/, ''
=> "hel1241lo"
call it simple like a function:
>> to_alphanumeric("U.S.A!")
=> "USA"

Concise way of prefixing string if prefix is not empty

Is there a shorter way of doing the following?
foo =
config.include?(:bar) ?
"#{bar}.baz" :
"baz"
I'm looking for a readable one-liner that appends a variable, plus a delimiter, if the variable exists (assuming it's a string).
config is a Hash.
You could do this:
foo = [bar, 'baz'].compact.join('.')
If bar is nil then compact will remove it from the array and delimiter won't be added.
foo = "#{"bar." if config.include?(:bar)}baz"

How does Ruby's replace work?

I'm looking at ruby's replace: http://www.ruby-doc.org/core/classes/String.html#M001144
It doesn't seem to make sense to me, you call replace and it replaces the entire string.
I was expecting:
replace(old_value, new_value)
Is what I am looking for gsub then?
replace seems to be different than in most other languages.
I agree that replace is generally used as some sort of pattern replace in other languages, but Ruby is different :)
Yes, you are thinking of gsub:
ruby-1.9.2-p136 :001 > "Hello World!".gsub("World", "Earth")
=> "Hello Earth!"
One thing to note is that String#replace may seem pointeless, however it does remove 'taintediness". You can read more up on tained objects here.
I suppose the reason you feel that replace does not make sense is because there is assigment operator = (not much relevant to gsub).
The important point is that String instances are mutable objects. By using replace, you can change the content of the string while retaining its identity as an object. Compare:
a = 'Hello' # => 'Hello'
a.object_id # => 84793190
a.replace('World') # => 'World'
a.object_id # => 84793190
a = 'World' # => 'World'
a.object_id # => 84768100
See that replace has not changed the string object's id, whereas simple assignment did change it. This difference has some consequences. For example, suppose you assigned some instance variables to the string instance. By replace, that information will be retained, but if you assign the same variable simply to a different string, all that information is gone.
Yes, it is gsub and it is taken from awk syntax. I guess replace stands for the internal representation of the string, since, according to documentation, tainted-ness is removed too.

Resources