Concise way of prefixing string if prefix is not empty - ruby

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"

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

Multiple Ruby chomp! statements

I'm writing a simple method to detect and strip tags from text strings. Given this input string:
{{foobar}}
The function has to return
foobar
I thought I could just chain multiple chomp! methods, like so:
"{{foobar}}".chomp!("{{").chomp!("}}")
but this won't work, because the first chomp! returns a NilClass. I can do it with regular chomp statements, but I'm really looking for a one-line solution.
The String class documentation says that chomp! returns a Str if modifications have been made - therefore, the second chomp! should work. It doesn't, however. I'm at a loss at what's happening here.
For the purposes of this question, you can assume that the input string is always a tag which begins and ends with double curly braces.
You can definitely chain multiple chomp statements (the non-bang version), still having a one-line solution as you wanted:
"{{foobar}}".chomp("{{").chomp("}}")
However, it will not work as expected because both chomp! and chomp removes the separator only from the end of the string, not from the beginning.
You can use sub
"{{foobar}}".sub(/{{(.+)}}/, '\1')
# => "foobar"
"alfa {{foobar}} beta".sub(/{{(.+)}}/, '\1')
# => "alfa foobar beta"
# more restrictive
"{{foobar}}".sub(/^{{(.+)}}$/, '\1')
# => "foobar"
Testing this out, it's clear that chomp! will return nil if the separator it's provided as an argument is not present at the end of the string.
So "{{text}}".chomp!("}}") returns a string, but "{{text}}".chomp!("{{") reurns nil.
See here for an answer of how to chomp at the beginning of a string. But recognize that chomp only looks at the end of the string. So you can call str.reverse.chomp!("{{").reverse to remove the opening brackets.
You could also use a regex:
string = "{{text}}"
puts [/^\{\{(.+)\}\}$/, 1]
# => "text"
Try tr:
'{{foobar}}'.tr('{{', '').tr('}}', '')
You can also use gsub or sub but if the replacement is not needed as pattern, then tr should be faster.
If there are always curly braces, then you can just slice the string:
'{{foobar}}'[2...-2]
If you plan to make a method which returns the string without curly braces then DO NOT use bang versions. Modifying the input parameter of a method will be suprising!
def strip(string)
string.tr!('{{', '').tr!('}}', '')
end
a = '{{foobar}}'
b = strip(a)
puts b #=> foobar
puts a #=> foobar

How do I print Arrays?

I have the array:
example = ['foo', 'bar', 'quux']
I want to iterate over it and print it so it comes out like: foo bar quux, not ['foo', 'bar', 'quux'] which would be the case if I used each or for.
Note: I can't just do: example[0];example[1], etc. because the length of the array is variable.
How do I do this?
Here:
puts array.join(' ') # The string contains one space
example.join(" ") #=> foo bar quux.
If you used each to print, it would work fine:
example.each {|item| print item; print " " } #=> foo bar quux
However, if what you want is a string with the items separated by spaces, that's what the join method is for:
example.join(' ') #=> "foo bar quux"
I suspect your problem is that you're confusing printing with iterating, as each just returns the original array — if you want things printed inside of it, you need to actually print like I did in the example above.
if they may be printed underneath each other just use
puts example
=>
foo
bar
quux
otherwise use the solutions from the other answers
puts example.join(" ")

What does the Ruby method 'to_sym' do?

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

Remove a character at an index position in Ruby

Basically what the question says. How can I delete a character at a given index position in a string? The String class doesn't seem to have any methods to do this.
If I have a string "HELLO" I want the output to be this
["ELLO", "HLLO", "HELO", "HELO", "HELL"]
I do that using
d = Array.new(c.length){|i| c.slice(0, i)+c.slice(i+1, c.length)}
I dont know if using slice! will work here, because it will modify the original string, right?
Won't Str.slice! do it? From ruby-doc.org:
str.slice!(fixnum) => fixnum or nil [...]
Deletes the specified portion from str, and returns the portion deleted.
If you're using Ruby 1.8, you can use delete_at (mixed in from Enumerable), otherwise in 1.9 you can use slice!.
Example:
mystring = "hello"
mystring.slice!(1) # mystring is now "hllo"
# now do something with mystring
$ cat m.rb
class String
def maulin! n
slice! n
self
end
def maulin n
dup.maulin! n
end
end
$ irb
>> require 'm'
=> true
>> s = 'hello'
=> "hello"
>> s.maulin(2)
=> "helo"
>> s
=> "hello"
>> s.maulin!(1)
=> "hllo"
>> s
=> "hllo"
To avoid needing to monkey patch String you can make use of tap:
"abc".tap {|s| s.slice!(2) }
=> "ab"
If you need to leave your original string unaltered, make use of dup, eg. abc.dup.tap.
I did something like this
c.slice(0, i)+c.slice(i+1, c.length)
Where c is the string and i is the index position I want to delete. Is there a better way?

Resources