Ruby Syntax, using numbers in symbols? - ruby

I'm new to ruby and Chef and am running to an issue with syntax when defining attributes in my cookbook. Below is relevant code:
default[:my_cookbook][:stuff] = {
:foo_bar => {
:grok => ['Hi'],
:2grok => ['Bye'],
...
It appears I can't use a number to begin 2grok.. Is there a way to escape this, or what would be the proper syntax to use '2grok'?

If you want to start a symbol with a digit, you need to enclose it in quotes:
:'2grok' => ['Hi']
If you use double quotes, ruby interpolates string inside:
:"#{1 + 1}grok"
Also, you can use percent-notation:
%s{2grok}
Finally, you can get the symbol by calling to_sym method on a String:
'2grok'.to_sym => ['Hi']

Mladen's answer is correct in term of Ruby. You can use a number at the beginning of symbol's name only using quotes. Keep in mind that you will have to use them to access the value from hash too. However you shouldn't use symbols for defining attributes in your cookbooks. Chef Style Guide recommends using strings instead.

Related

Freemarker ruby script template issue

So I am trying to run a ruby script and I have string expansion sections that are being mistaken for freemarker expressions, for example:
puts "Foo bar baz quux #{#awesome}"
In ruby the #{} is valid ruby, and I need Freemarker to ignore it. According to the documentation, I can escape lie this:
#\{#awesome}
But that leaves the backslash in the final output. I tried to do this:
#{r"#{#awesome"}}
But I get an exception saying that a number was expected... According to the docs, this should produce a literal '#{#awesome}'
What gives? Am I doing something wrong?
This will work:
${r"#{#awesome"}}
Your attempt gives error because FreeMarker's #{...} only accepts numbers.

Using the `$` character in `ruby_block` in chef

I want to use the following code in my recipe for ruby_block, but it's not working because of the '$'. The code cannot find $NAME, but it can find NAME. Can you give me a solution?
file.search_file_replace_line("DEFAULT=/etc/default/$NAME","DEFAULT=/etc/default/tomcat7")
search_file_replace_line expects regex as the first argument. And dollar sign is a special symbol within the regular expressions, it means end of the line, basically. So you have to properly escape it if you really want to replace it with something.
This will do the job:
file.search_file_replace_line("DEFAULT=/etc/default/\\$NAME","DEFAULT=/etc/default/tomcat7")

Convert array to arguments for shell command

I'm trying to do something like:
list = Dir["*.mp4"]
`zip "test.zip" "#{list}"`
But #{list} is coming out as an array, how do I fix that?
You should use Shellwords from the standard library, which is designed to do exactly this—and does proper escaping no matter how weird your filenames are:
require 'shellwords'
list = Dir["*.mp4"]
puts [ "zip", "test.zip", *list ].shelljoin
# => zip test.zip foo.mp4 filename\ with\ spaces.mp4 etc.mp4
Doesn't look like you're storing the result anywhere so you should use the multi-argument form of system and bypass the shell entirely:
system('zip', 'test.zip', *list)
Since no shell is invoked, you don't have to worry about quoting or parsing or any of that nonsense, just build a list of strings and splat it.
If you do need to capture the output, then use one of the Open3 methods. Backticks are almost always the wrong approach, there are too many sharp edges (just browse the CERT reports for Ruby and you'll see how often backticks and the single argument form of system cause problems).
http://www.ruby-doc.org/core-2.1.2/Array.html#method-i-join
You are looking for the join method
["a","b","c"].join(" ") => "a b c"
["a","b","c"].join("-|-") => "a-|-b-|-c"

Using variable substitution in replace.gsub

How do I include a variable in the 'replace' portion of gsub?
replace.gsub(/#{year}","1/, '#{year}","b')
This outputs:
=> #{year}","b
Let's say year = 2013. I want it to output:
=> 2013","b
Adding on to Blender's answer, you can use an alternate way of writing strings to avoid having to escape quotes:
replace.gsub(/#{year}","1/, %{#{year}","b})
where %{} is another way to write a string literal that you can do string interpolation in.

String substitution in Puppet?

Is it possible to do a string substitution/transformation in Puppet using a regular expression?
If $hostname is "web1", I want $hostname_without_number to be "web". The following isn't valid Puppet syntax, but I think I need something like this:
$hostname_without_number = $hostname.gsub(/\d+$/, '')
Yes, it is possible.
Check the puppet function reference: http://docs.puppetlabs.com/references/2.7.3/function.html
There's a regular expression substitution function built in. It probably calls the same underlying gsub function.
$hostname_without_number = regsubst($hostname, '\d+$', '')
Or if you prefer to actually call out to Ruby, you can use an inline ERB template:
$hostname_without_number = inline_template('<%= hostname.gsub(/\d+$/, "") %>')
In this page:
https://blog.kumina.nl/2010/03/puppet-tipstricks-testing-your-regsubst-replacings-2/comment-page-1/
it is quite well explained and there is a fantastic trick for testing your regular expressions with irb.
Whith this link and the answer of freiheit I could resolve my problem with substitution of '\' for '/'.
$programfiles_sinbackslash = regsubst($env_programfiles,'\','/','G')

Resources