Read more

Ruby: Referencing global variables with the built-in English library

Emanuel
June 19, 2020Software engineer at makandra GmbH

tl;dr

Don't forget require 'English' if you use a named global such as $LAST_MATCH_INFO. Otherwise this could result in an annoying bug.

With Ruby's build-in library English Show archive.org snapshot you can reference global variables with an english name. This makes you code easier to read and is also suggested by Rubocop's Style/GlobalVars Show archive.org snapshot cop.

Illustration online protection

Rails Long Term Support

Rails LTS provides security patches for old versions of Ruby on Rails (2.3, 3.2, 4.2 and 5.2)

  • Prevents you from data breaches and liability risks
  • Upgrade at your own pace
  • Works with modern Rubies
Read more Show archive.org snapshot

Example before:

if 'foo' =~ /foo/
  puts $~[1] # => foo
end

Example after:

if 'foo' =~ /foo/
  puts $LAST_MATCH_INFO[1] # => foo
end

Require pitfall in Rails

The English library is not loaded by default in Rails. So you or another library needs to require it. The chances are very high, that you application will fail in production without an explizit require e.g. when you use Rubocop or Capybara. These gems most often live in your development and/or test group of the Gemfile and require English for you.

Therefore to ensure that the library is loaded in all environments, add the following line to your config/application.rb or create an initializer like config/initializers/english.rb with the following content:

require 'English'

List of global aliases

$ERROR_INFO => $!
$ERROR_POSITION => $@
$FS => $;
$FIELD_SEPARATOR => $;
$OFS => $,
$OUTPUT_FIELD_SEPARATOR => $,
$RS => $/
$INPUT_RECORD_SEPARATOR => $/
$ORS => $\
$OUTPUT_RECORD_SEPARATOR => $\
$INPUT_LINE_NUMBER => $.
$NR => $.
$LAST_READ_LINE => $_
$DEFAULT_OUTPUT => $>
$DEFAULT_INPUT => $<
$PID => $$
$PROCESS_ID => $$
$CHILD_STATUS => $?
$LAST_MATCH_INFO => $~
$IGNORECASE => $=
$ARGV => $*
$MATCH => $&
$PREMATCH => $`
$POSTMATCH => $'
$LAST_PAREN_MATCH => $+

Rubocop - Style/SpecialGlobalVars

The code snippet of How to fix gsub on SafeBuffer objects was adjusted during a rubocop upgrade.

Rubocop tells you everything you need to know to fix the offense Style/SpecialGlobalVars:

Style/SpecialGlobalVars: Prefer $LAST_MATCH_INFO from the stdlib 'English' module (don't forget to require it) over $~.

In this scenario you should be very careful. If you forget to require 'English', your code may not work any longer as expected.

Emanuel
June 19, 2020Software engineer at makandra GmbH
Posted by Emanuel to makandra dev (2020-06-19 11:52)