I am trying to write a YAML dictionary for internationalisation of a Rails project. I am a little confused though, as in some files I see strings in double-quotes and in some without. A few points to consider:
example 1 - all strings use double quotes;
example 2 - no strings (except the last two) use quotes;
the YAML cookbook says: Enclosing strings in double quotes allows you to use escaping to represent ASCII and Unicode characters. Does this mean I need to use double quotes only when I want to escape some characters? If yes - why do they use double quotes everywhere in the first example - only for the sake of unity / stylistic reasons?
the last two lines of example 2 use ! - the non-specific tag, while the last two lines of the first example don't - and they both work.
My question is: what are the rules for using the different types of quotes in YAML?
Could it be said that:
in general, you don't need quotes;
if you want to escape characters use double quotes;
use ! with single quotes, when... ?!?
After a brief review of the YAML cookbook cited in the question and some testing, here's my interpretation:
In general, you don't need quotes.
Use quotes to force a string, e.g. if your key or value is 10 but you want it to return a String and not a Fixnum, write '10' or "10".
Use quotes if your value includes special characters, (e.g. :, {, }, [, ], ,, &, *, #, ?, |, -, <, >, =, !, %, #, \).
Single quotes let you put almost any character in your string, and won't try to parse escape codes. '\n' would be returned as the string \n.
Double quotes parse escape codes. "\n" would be returned as a line feed character.
The exclamation mark introduces a method, e.g. !ruby/sym to return a Ruby symbol.
Seems to me that the best approach would be to not use quotes unless you have to, and then to use single quotes unless you specifically want to process escape codes.
Update
"Yes" and "No" should be enclosed in quotes (single or double) or else they will be interpreted as TrueClass and FalseClass values:
en:
yesno:
'yes': 'Yes'
'no': 'No'
While Mark's answer nicely summarizes when the quotes are needed according to the YAML language rules, I think what many of the developers/administrators are asking themselves, when working with strings in YAML, is "what should be my rule of thumb for handling the strings?"
It may sound subjective, but the number of rules you have to remember, if you want to use the quotes only when they are really needed as per the language spec, is somewhat excessive for such a simple thing as specifying one of the most common datatypes. Don't get me wrong, you will eventually remember them when working with YAML regularly, but what if you use it occasionally, and you didn't develop automatism for writing YAML? Do you really want to spend time remembering all the rules just to specify the string correctly?
The whole point of the "rule of thumb" is to save the cognitive resource and to handle a common task without thinking about it. Our "CPU" time can arguably be used for something more useful than handling the strings correctly.
From this - pure practical - perspective, I think the best rule of thumb is to single quote the strings. The rationale behind it:
Single quoted strings work for all scenarios, except when you need to use escape sequences.
The only special character you have to handle within a single-quoted string is the single quote itself.
These are just 2 rules to remember for some occasional YAML user, minimizing the cognitive effort.
There have been some great answers to this question.
However, I would like to extend them and provide some context from the new official YAML v1.2.2 specification (released October 1st 2021) which is the "true source" to all things considering YAML.
There are three different styles that can be used to represent strings, each of them with their own (dis-)advantages:
YAML provides three flow scalar styles: double-quoted, single-quoted and plain (unquoted). Each provides a different trade-off between readability and expressive power.
Double-quoted style:
The double-quoted style is specified by surrounding " indicators. This is the only style capable of expressing arbitrary strings, by using \ escape sequences. This comes at the cost of having to escape the \ and " characters.
Single-quoted style:
The single-quoted style is specified by surrounding ' indicators. Therefore, within a single-quoted scalar, such characters need to be repeated. This is the only form of escaping performed in single-quoted scalars. In particular, the \ and " characters may be freely used. This restricts single-quoted scalars to printable characters. In addition, it is only possible to break a long single-quoted line where a space character is surrounded by non-spaces.
Plain (unquoted) style:
The plain (unquoted) style has no identifying indicators and provides no form of escaping. It is therefore the most readable, most limited and most context sensitive style. In addition to a restricted character set, a plain scalar must not be empty or contain leading or trailing white space characters. It is only possible to break a long plain line where a space character is surrounded by non-spaces.
Plain scalars must not begin with most indicators, as this would cause ambiguity with other YAML constructs. However, the :, ? and - indicators may be used as the first character if followed by a non-space “safe” character, as this causes no ambiguity.
TL;DR
With that being said, according to the official YAML specification one should:
Whenever applicable use the unquoted style since it is the most readable.
Use the single-quoted style (') if characters such as " and \ are being used inside the string to avoid escaping them and therefore improve readability.
Use the double-quoted style (") when the first two options aren't sufficient, i.e. in scenarios where more complex line breaks are required or non-printable characters are needed.
Strings in yaml only need quotation if (the beginning of) the value can be misinterpreted as a data type or the value contains a ":" (because it could get misinterpreted as key).
For example
foo: '{{ bar }}'
needs quotes, because it can be misinterpreted as datatype dict, but
foo: barbaz{{ bam }}
does not, since it does not begin with a critical char. Next,
foo: '123'
needs quotes, because it can be misinterpreted as datatype int, but
foo: bar1baz234
bar: 123baz
Does not, because it can not be misinterpreted as int
foo: 'yes'
needs quotes, because it can be misinterpreted as datatype bool
foo: "bar:baz:bam"
needs quotes, because the value can be misinterpreted as key.
These are just examples. Using yamllint helps avoiding to start values with a wrong token
foo#bar:/tmp$ yamllint test.yaml
test.yaml
3:4 error syntax error: found character '#' that cannot start any token (syntax)
and is a must, if working productively with yaml.
Quoting all strings as some suggest, is like using brackets in python. It is bad practice, harms readability and throws away the beautiful feature of not having to quote strings.
I had this concern when working on a Rails application with Docker.
My most preferred approach is to generally not use quotes. This includes not using quotes for:
variables like ${RAILS_ENV}
values separated by a colon (:) like postgres-log:/var/log/postgresql
other strings values
I, however, use double-quotes for integer values that need to be converted to strings like:
docker-compose version like version: "3.8"
port numbers like "8080:8080"
image "traefik:v2.2.1"
However, for special cases like booleans, floats, integers, and other cases, where using double-quotes for the entry values could be interpreted as strings, please do not use double-quotes.
Here's a sample docker-compose.yml file to explain this concept:
version: "3"
services:
traefik:
image: "traefik:v2.2.1"
command:
- --api.insecure=true # Don't do that in production
- --providers.docker=true
- --providers.docker.exposedbydefault=false
- --entrypoints.web.address=:80
ports:
- "80:80"
- "8080:8080"
volumes:
- /var/run/docker.sock:/var/run/docker.sock:ro
That's all.
I hope this helps
If you are trying to escape a string in pytest tavern, !raw could be helpful to avoid parsing of strings to yaml:
some: !raw "{test: 123}"
Check for more info:
https://tavern.readthedocs.io/en/latest/basics.html#type-conversions
Here's a small function (not optimized for performance) that quotes your strings with single quotes if needed and tests if the result could be unmarshalled into the original value: https://go.dev/play/p/AKBzDpVz9hk.
Instead of testing for the rules it simply uses the marshaller itself and checks if the marshalled and unmmarshalled value matches the original version.
func yamlQuote(value string) string {
input := fmt.Sprintf("key: %s", value)
var res struct {
Value string `yaml:"key"`
}
if err := yaml.Unmarshal([]byte(input), &res); err != nil || value != res.Value {
quoted := strings.ReplaceAll(value, `'`, `''`)
return fmt.Sprintf("'%s'", quoted)
}
return value
}
version: "3.9"
services:
seunggabi:
image: seunggabi:v1.0.0
command:
api:
insecure: true
ports:
- 80:80
- 8080:8080
volumes:
- /var/run/docker.sock:/var/run/docker.sock:ro
docker compoese up docker-compose.yaml
If you use docker compose v2, you don't need to use quotation for boolean.
Only the version needs quotations.
Related
I am working with https://github.com/prometheus-community/helm-charts and am running into some issues with a couple of regex queries are a part of our basic yaml deployments. The issue I'm having is specifically with the Node exporter part of the prometheus chart. I have configured this:
nodeExporter:
extraArgs: {
collector.filesystem.ignored-fs-types="^(devpts|devtmpfs|mqueue|proc|securityfs|binfmt_misc|debugfs|overlay|pstore|selinuxfs|tmpfs|hugetlbfs|nfsd|cgroup|configfs|rpc_pipefs|sysfs|autofs|rootfs)$",
collector.filesystem.ignored-mount-points="^/etc/.+$",
collector.netstat.fields="*",
collector.diskstats.ignored-devices="^(ram|loop|fd|(h|s|v|xv)d[a-z]|nvme\d+n\d+p|dm-)\d+$", # BROKEN
collector.netclass.ignored-devices=^(?:tun|kube|veth|dummy|docker).+$, # BROKEN
collector.nfs
}
tolerations:
- operator: Exists
As noted above, these two lines with regex are broken:
collector.diskstats.ignored-devices="^(ram|loop|fd|(h|s|v|xv)d[a-z]|nvme\d+n\d+p|dm-)\d+$", # BROKEN
collector.netclass.ignored-devices=^(?:tun|kube|veth|dummy|docker).+$, # BROKEN
There seems to be a problem with the | character right be fore "nvme" in the first one, and with the ?: in the second. I believe it's something to do with regex/yaml format, but I'm not sure how to correct this.
With {, you are beginning a YAML flow mapping. It typically contains comma-separated key-value pairs, though you can also, like in this example, give single values instead, which will make them a key with null value.
In YAML, as soon as you enter a flow-style collection, all special flow-indicators cannot be used in plain scalars anymore. Special flow indicators are {}[],. A plain scalar is a non-quoted textual value.
The first broken value is illegal because it contains [ and ]. The second broken value is actually legal according to the specification, but quite some YAML implementations choke on it because ? is also used as indicator for a mapping key.
You have several options:
Quote the scalars. since none of them contain single quotes, enclosing each with single quotes will do the trick. Generally you can also double-quote them, but then you need to escape all double-quote characters and all backslashes in there which does not help readability.
nodeExporter:
extraArgs: {
collector.filesystem.ignored-fs-types="^(devpts|devtmpfs|mqueue|proc|securityfs|binfmt_misc|debugfs|overlay|pstore|selinuxfs|tmpfs|hugetlbfs|nfsd|cgroup|configfs|rpc_pipefs|sysfs|autofs|rootfs)$",
collector.filesystem.ignored-mount-points="^/etc/.+$",
collector.netstat.fields="*",
'collector.diskstats.ignored-devices="^(ram|loop|fd|(h|s|v|xv)d[a-z]|nvme\d+n\d+p|dm-)\d+$"',
'collector.netclass.ignored-devices=^(?:tun|kube|veth|dummy|docker).+$',
collector.nfs
}
tolerations:
- operator: Exists
Use block scalars. Block scalars are generally the best way to enter scalars with lots of special characters because they are ended via indentation and therefore can contain any special character. Block scalars can only occur in other block structures, so you'd need to make extraArgs a block mapping:
nodeExporter:
extraArgs:
? collector.filesystem.ignored-fs-types="^(devpts|devtmpfs|mqueue|proc|securityfs|binfmt_misc|debugfs|overlay|pstore|selinuxfs|tmpfs|hugetlbfs|nfsd|cgroup|configfs|rpc_pipefs|sysfs|autofs|rootfs)$"
? collector.filesystem.ignored-mount-points="^/etc/.+$"
? collector.netstat.fields="*"
? |-
collector.diskstats.ignored-devices="^(ram|loop|fd|(h|s|v|xv)d[a-z]|nvme\d+n\d+p|dm-)\d+$"
? |-
collector.netclass.ignored-devices=^(?:tun|kube|veth|dummy|docker).+$
? collector.nfs
tolerations:
- operator: Exists
As you can see, this is now using the previously mentioned ? as key indicator.
Since it is a block sequence, you don't need the commas anymore.
|- starts a literal block scalar from which the final linebreak is stripped.
I am trying to write a YAML dictionary for internationalisation of a Rails project. I am a little confused though, as in some files I see strings in double-quotes and in some without. A few points to consider:
example 1 - all strings use double quotes;
example 2 - no strings (except the last two) use quotes;
the YAML cookbook says: Enclosing strings in double quotes allows you to use escaping to represent ASCII and Unicode characters. Does this mean I need to use double quotes only when I want to escape some characters? If yes - why do they use double quotes everywhere in the first example - only for the sake of unity / stylistic reasons?
the last two lines of example 2 use ! - the non-specific tag, while the last two lines of the first example don't - and they both work.
My question is: what are the rules for using the different types of quotes in YAML?
Could it be said that:
in general, you don't need quotes;
if you want to escape characters use double quotes;
use ! with single quotes, when... ?!?
After a brief review of the YAML cookbook cited in the question and some testing, here's my interpretation:
In general, you don't need quotes.
Use quotes to force a string, e.g. if your key or value is 10 but you want it to return a String and not a Fixnum, write '10' or "10".
Use quotes if your value includes special characters, (e.g. :, {, }, [, ], ,, &, *, #, ?, |, -, <, >, =, !, %, #, \).
Single quotes let you put almost any character in your string, and won't try to parse escape codes. '\n' would be returned as the string \n.
Double quotes parse escape codes. "\n" would be returned as a line feed character.
The exclamation mark introduces a method, e.g. !ruby/sym to return a Ruby symbol.
Seems to me that the best approach would be to not use quotes unless you have to, and then to use single quotes unless you specifically want to process escape codes.
Update
"Yes" and "No" should be enclosed in quotes (single or double) or else they will be interpreted as TrueClass and FalseClass values:
en:
yesno:
'yes': 'Yes'
'no': 'No'
While Mark's answer nicely summarizes when the quotes are needed according to the YAML language rules, I think what many of the developers/administrators are asking themselves, when working with strings in YAML, is "what should be my rule of thumb for handling the strings?"
It may sound subjective, but the number of rules you have to remember, if you want to use the quotes only when they are really needed as per the language spec, is somewhat excessive for such a simple thing as specifying one of the most common datatypes. Don't get me wrong, you will eventually remember them when working with YAML regularly, but what if you use it occasionally, and you didn't develop automatism for writing YAML? Do you really want to spend time remembering all the rules just to specify the string correctly?
The whole point of the "rule of thumb" is to save the cognitive resource and to handle a common task without thinking about it. Our "CPU" time can arguably be used for something more useful than handling the strings correctly.
From this - pure practical - perspective, I think the best rule of thumb is to single quote the strings. The rationale behind it:
Single quoted strings work for all scenarios, except when you need to use escape sequences.
The only special character you have to handle within a single-quoted string is the single quote itself.
These are just 2 rules to remember for some occasional YAML user, minimizing the cognitive effort.
There have been some great answers to this question.
However, I would like to extend them and provide some context from the new official YAML v1.2.2 specification (released October 1st 2021) which is the "true source" to all things considering YAML.
There are three different styles that can be used to represent strings, each of them with their own (dis-)advantages:
YAML provides three flow scalar styles: double-quoted, single-quoted and plain (unquoted). Each provides a different trade-off between readability and expressive power.
Double-quoted style:
The double-quoted style is specified by surrounding " indicators. This is the only style capable of expressing arbitrary strings, by using \ escape sequences. This comes at the cost of having to escape the \ and " characters.
Single-quoted style:
The single-quoted style is specified by surrounding ' indicators. Therefore, within a single-quoted scalar, such characters need to be repeated. This is the only form of escaping performed in single-quoted scalars. In particular, the \ and " characters may be freely used. This restricts single-quoted scalars to printable characters. In addition, it is only possible to break a long single-quoted line where a space character is surrounded by non-spaces.
Plain (unquoted) style:
The plain (unquoted) style has no identifying indicators and provides no form of escaping. It is therefore the most readable, most limited and most context sensitive style. In addition to a restricted character set, a plain scalar must not be empty or contain leading or trailing white space characters. It is only possible to break a long plain line where a space character is surrounded by non-spaces.
Plain scalars must not begin with most indicators, as this would cause ambiguity with other YAML constructs. However, the :, ? and - indicators may be used as the first character if followed by a non-space “safe” character, as this causes no ambiguity.
TL;DR
With that being said, according to the official YAML specification one should:
Whenever applicable use the unquoted style since it is the most readable.
Use the single-quoted style (') if characters such as " and \ are being used inside the string to avoid escaping them and therefore improve readability.
Use the double-quoted style (") when the first two options aren't sufficient, i.e. in scenarios where more complex line breaks are required or non-printable characters are needed.
Strings in yaml only need quotation if (the beginning of) the value can be misinterpreted as a data type or the value contains a ":" (because it could get misinterpreted as key).
For example
foo: '{{ bar }}'
needs quotes, because it can be misinterpreted as datatype dict, but
foo: barbaz{{ bam }}
does not, since it does not begin with a critical char. Next,
foo: '123'
needs quotes, because it can be misinterpreted as datatype int, but
foo: bar1baz234
bar: 123baz
Does not, because it can not be misinterpreted as int
foo: 'yes'
needs quotes, because it can be misinterpreted as datatype bool
foo: "bar:baz:bam"
needs quotes, because the value can be misinterpreted as key.
These are just examples. Using yamllint helps avoiding to start values with a wrong token
foo#bar:/tmp$ yamllint test.yaml
test.yaml
3:4 error syntax error: found character '#' that cannot start any token (syntax)
and is a must, if working productively with yaml.
Quoting all strings as some suggest, is like using brackets in python. It is bad practice, harms readability and throws away the beautiful feature of not having to quote strings.
I had this concern when working on a Rails application with Docker.
My most preferred approach is to generally not use quotes. This includes not using quotes for:
variables like ${RAILS_ENV}
values separated by a colon (:) like postgres-log:/var/log/postgresql
other strings values
I, however, use double-quotes for integer values that need to be converted to strings like:
docker-compose version like version: "3.8"
port numbers like "8080:8080"
image "traefik:v2.2.1"
However, for special cases like booleans, floats, integers, and other cases, where using double-quotes for the entry values could be interpreted as strings, please do not use double-quotes.
Here's a sample docker-compose.yml file to explain this concept:
version: "3"
services:
traefik:
image: "traefik:v2.2.1"
command:
- --api.insecure=true # Don't do that in production
- --providers.docker=true
- --providers.docker.exposedbydefault=false
- --entrypoints.web.address=:80
ports:
- "80:80"
- "8080:8080"
volumes:
- /var/run/docker.sock:/var/run/docker.sock:ro
That's all.
I hope this helps
If you are trying to escape a string in pytest tavern, !raw could be helpful to avoid parsing of strings to yaml:
some: !raw "{test: 123}"
Check for more info:
https://tavern.readthedocs.io/en/latest/basics.html#type-conversions
Here's a small function (not optimized for performance) that quotes your strings with single quotes if needed and tests if the result could be unmarshalled into the original value: https://go.dev/play/p/AKBzDpVz9hk.
Instead of testing for the rules it simply uses the marshaller itself and checks if the marshalled and unmmarshalled value matches the original version.
func yamlQuote(value string) string {
input := fmt.Sprintf("key: %s", value)
var res struct {
Value string `yaml:"key"`
}
if err := yaml.Unmarshal([]byte(input), &res); err != nil || value != res.Value {
quoted := strings.ReplaceAll(value, `'`, `''`)
return fmt.Sprintf("'%s'", quoted)
}
return value
}
version: "3.9"
services:
seunggabi:
image: seunggabi:v1.0.0
command:
api:
insecure: true
ports:
- 80:80
- 8080:8080
volumes:
- /var/run/docker.sock:/var/run/docker.sock:ro
docker compoese up docker-compose.yaml
If you use docker compose v2, you don't need to use quotation for boolean.
Only the version needs quotations.
I am using Tcl_StringCaseMatch function in C++ code for string pattern matching. Everything works fine until input pattern or string has [] bracket. For example, like:
str1 = pq[0]
pattern = pq[*]
Tcl_StringCaseMatch is not working i.e returning false for above inputs.
How to avoid [] in pattern matching?
The problem is [] are special characters in the pattern matching. You need to escape them using a backslash to have them treated like plain characters
pattern= "pq\\[*\\]"
I don't think this should affect the string as well. The reason for double slashing is you want to pass the backslash itself to the TCL engine.
For the casual reader:
[] have a special meaning in TCL in general, beyond the pattern matching role they take here - "run command" (like `` or $() in shells), but [number] will have no effect, and the brackets are treated normally - thus the string str1 does not need escaping here.
For extra confusion:
TCL will interpret ] with no preceding [ as a normal character by default. I feel that's getting too confusing, and would rather that TCL complains on unbalanced brackets. As OP mentions though, this allows you to forgo the final two backslashes and use "pq\\[*]". I dislike this, and rather make it obvious both are treated normally and not the usual TCL way, but to each her/is own.
I have some data to be used to generate SQL, therefore it is important which text delimiters are used (single quotes ' delimits string literal but double quotes " delimit identifiers, at least in Oracle db).
For load procedure generator I used this
someKey: !!str 'Some SQL text'
and expected that someKey would contain the whole string including single quotes: 'Some SQL text'.
However, js-yaml.safeLoad() interprets the data as Some SQL text which is not what I wanted.
The workaround is easy, I can put the literal into additional quotes:
someKey: "'Some SQL text'"
which gives the expected result. However, I am not quite sure why in that case do we need !!str tag in YAML if it does virtually nothing (it is useful only for explicit interpretation number literals, true, false and null) and it is actually almost the same as putting double quotes around the text.
I would prefer to post this into some YAML-spec-related forum but it seems there is none.
Apart from the standard workaround, is there any trick that would do what I originally wanted, i.e. interpret any content after object key as string (+trimming off any initial and trailing spaces) without dealing with double quotes?
In YAML tag !!str is a predifened denoting a string scalar. If you specify that then even things that without that tag (or without quotes) would not be considered a string scalar, like 123, True or null.
Some string scalars need quotes e.g. if they start with a quote or double quote, if special characters need backslash espacing, or if there is a : (colon, space) in the string (which could confuse the parser to intrepret the string scalar as a key-value pair.
However putting !!str before something doesn't make it quoted (which should be obvious as it doesn't define what kind of quoting and single quoted scalars have vastly different rules from double quoted scalars).
Your workaround is not a workaround, that is just one of the ways in YAML you can specify a string scalar that starts and ends with a single quote. Another way is:
someKey: |-
'Some SQL text'
Within literal block style scalars quotes (single or double) are interpreted as is even at the beginning of the scalar. The - makes sure you don't get an extra newline after the final '
Which style of Ruby string quoting do you favour? Up until now I've always used 'single quotes' unless the string contains certain escape sequences or interpolation, in which case I obviously have to use "double quotes".
However, is there really any reason not to just use double quoted strings everywhere?
Don't use double quotes if you have to escape them. And don't fall in "single vs double quotes" trap. Ruby has excellent support for arbitrary delimiters for string literals:
Mirror of Site - https://web.archive.org/web/20160310224440/http://rors.org/2008/10/26/dont-escape-in-strings
Original Site -
http://rors.org/2008/10/26/dont-escape-in-strings
I always use single quotes unless I need interpolation.
Why? It looks nicer. When you have a ton of stuff on the screen, lots of single quotes give you less "visual clutter" than lots of double quotes.
I'd like to note that this isn't something I deliberately decided to do, just something that I've 'evolved' over time in trying to achieve nicer looking code.
Occasionally I'll use %q or %Q if I need in-line quotes. I've only ever used heredocs maybe once or twice.
Like many programmers, I try to be as specific as is practical. This means that I try to make the compiler do as little work as possible by having my code as simple as possible. So for strings, I use the simplest method that suffices for my needs for that string.
<<END
For strings containing multiple newlines,
particularly when the string is going to
be output to the screen (and thus formatting
matters), I use heredocs.
END
%q[Because I strongly dislike backslash quoting when unnecessary, I use %Q or %q
for strings containing ' or " characters (usually with square braces, because they
happen to be the easiest to type and least likely to appear in the text inside).]
"For strings needing interpretation, I use %s."%['double quotes']
'For the most common case, needing none of the above, I use single quotes.'
My first simple test of the quality of syntax highlighting provided by a program is to see how well it handles all methods of quoting.
I use single quotes unless I need interpolation. The argument about it being troublesome to change later when you need interpolation swings in the other direction, too: You have to change from double to single when you found that there was a # or a \ in your string that caused an escape you didn't intend.
The advantage of defaulting to single quotes is that, in a codebase which adopts this convention, the quote type acts as a visual cue as to whether to expect interpolated expressions or not. This is even more pronounced when your editor or IDE highlights the two string types differently.
I use %{.....} syntax for multi-line strings.
I usually use double quotes unless I specifically need to disable escaping/interpolation.
I see arguments for both:
For using mostly double quotes:
The github ruby style guideline advocates always using double quotes:
It's easier to search for a string foobar by searching for "foobar" if you were consistent with quoting. However, I'm not. So I search for ['"]foobar['"] turning on regexps.
For using some combination of single double quotes:
Know if you need to look for string interpolation.
Might be slightly faster (although so slight it wasn't enough to affect the github style guide).
I used to use single quotes until I knew I needed interpolation. Then I found that I was wasting a lot of time when I'd go back and have to change some single-quotes to double-quotes. Performance testing showed no measurable speed impact of using double-quotes, so I advocate always using double-quotes.
The only exception is when using sub/gsub with back-references in the replacement string. Then you should use single quotes, since it's simpler.
mystring.gsub( /(fo+)bar/, '\1baz' )
mystring.gsub( /(fo+)bar/, "\\1baz" )
I use single quotes unless I need interpolation, or the string contains single quotes.
However, I just learned the arbitrary delimiter trick from Dejan's answer, and I think it's great. =)
Single quote preserve the characters inside them. But double quotes evaluate and parse them. See the following example:
"Welcome #{#user.name} to App!"
Results:
Welcome Bhojendra to App!
But,
'Welcome #{#user.name} to App!'
Results:
Welcome #{#user.name} to App!