Today I Learned

Def keyword can also be used as a begin statement

In Ruby, the begin keyword for exception handling (ie, begin...rescue...ensure, traditionally try...catch...finally in other languages) is optional. You can have a method that only declares a rescue or an ensure statement without begin. That's because the def statement in the method can serve the same purpose as begin. This means that this method:

def edit
  begin
    @user = find(params[:id])
    ...
  rescue ActiveRecord::RecordNotFound
    redirect_to :back
  end
end

Can legally be shortened to:

def edit
  @user = find(params[:id])
  ...
rescue ActiveRecord::RecordNotFound
  redirect_to :back
end

Safe Navigation Operator

If you have worked in a Rails project, you have probably came across the try and try! methods. try saves us from checking conditions before drilling-down through a message chain. try! is more restrictive; it raises when the receiver does not respond to the method:

require "active_support"
require "active_support/core_ext/object/try"

User = Struct.new(:name)

users = [User.new("Jason")]

users.first.try(:name)
# "Jason"

users.first.try(:unknown_method)
# nil

users.first.try!(:unknown_method)
# NoMethodError: undefined method `unknown_method' for #<struct User name="Jason">

Note these methods are provided by ActiveSupport. As of Ruby 2.3, this behaviour is now available in the language, called the safe navigation operator &.:

users = [User.new(name: "Jason")]
users.first&.name
# "Jason"

users = []
users.first&.name
# nil

Gotchas

When an object does not respond to a method, &. behaves like try!; it raises an error. However, nil seems to break this pattern:

# behaviour like try!
user&.unknown_method
# NoMethodError: undefined method `unknown_method' for #<struct User name="Jason">

# given that
nil.nil?
# true

# this is confusing
nil&.nil?
# nil

The last example has a simple explanation: &. checks the receiver. Since the receiver is nil, &. immediately returns nil. It does not matter that nil responds to the message.

Block Kwargs

Ruby 2.0 introduced keyword arguments. Ruby 2.1 further added required keyword arguments. It is common to see methods using kwargs:

def some_method(keyword_arg: "Hello", required_arg:)
  puts "#{keyword_arg} #{required_arg}"
end

some_method(required_arg: "world")
# Hello world

However, these changes also apply to block arguments:

define_method :prints_block_arguments do |default_arg: "hello", required_arg:, **others|
  puts "default_arg: #{default_arg}"
  puts "required_arg: #{required_arg}"

  others.each_pair do |key, value|
    puts "other arg: #{key} => #{value}"
  end
end

prints_block_arguments(required_arg: "world")
# default_arg: hello
# required_arg: world

prints_block_arguments(default_arg: "ciao", required_arg: "mondo", something: "else")
# default_arg: ciao
# required_arg: mondo
# other arg: something => else

prints_block_agruments()
# ArgumentError: missing keyword: required_arg

Git Shortlog

There are many ways to customize your git log output. However, the structure still the same: commit by commit.

A new variation I recently discovered was git shortlog. It displays commits by author, rather than most recently committed order. It is intended to help producing release notes.

This lets you find out who your largest contributors are, especially with the --summary option.

Try this:

$ git shortlog --summary | sort -r

Default Value for Deconstructed Object Parameter

In ES6, you can deconstruct a function's object parameter to have its properties assigned to local named variables:

function MyComponent({
  item: { foo, bar }
}) { ... }

Also in ES6, the properties of the object parameter can have a default value set:

function MyComponent({
  item = "LOL"
}) { ... }

TIL: The object parameter can have both destructuring and default values applied to it!

function MyComponent({
  item: { foo, bar } = { foo: 1, bar: 2 }
}) { ... }

Debug Arrow Functions With Comma Operator

Use the Comma Operator to execute many JavaScript expressions in one 'location', but only return the value from the last expression.

This is commonly used in classic for loops, but has an interesting use case to quickly debug a single-line arrow function. For example, suppose you wanted to throw a console.log() into this function:

const myFunc = value => doCrazyOperation(value.foo);

Without the comma operator, this function would have to be expanded into a multi-line block function with a return statement, which is relatively quite longer:

const myFunc = (value) {
  console.log("value", value);
  return doCrazyOperation(value.foo);
};

With the Comma Operator, this debugging is much easier to write and maintain:

const myFunc = value => (console.log("value", value), doCrazyOperation(value.foo));

Using module_function instead of extend self

It's a common pattern to use extend self inside ruby module to make all methods available in a static context/declared as class methods.

Instead of this, you can use module_function instead which will do the same as extend self but also have the added benefit of making those method private instance methods when they are included in another file.

module UserNameFormatter
  module_function

  def format_name(user)
    "#{user.name}"
  end
end

class User
  include UserNameFormatter

  def something
    format_name(self)
  end
end

Searching Through Gems

Sometimes you need to peak at the source of a class or method of a gem from your Gemfile. Since gems are managed by bundler, it has a command-line option that can help.

bundle show --paths will list the paths of all the gems from your Gemfile. You can grep through these directories to search.

I'm currently using ripgrep for searching at the command line, so can pass the paths there.

Here’s it all together in a simple Bash function:

function bundle-search() {
    rg $1 `bundle show --paths`
}

Enumerable Predicate Methods Have a New Argument

Enumerable#grep accepts an argument that returns elements that are true using case equality (===). These elements can then be passed to its block for further proccessing:

fruits = %w(apples orange grapes)
fruits.grep(/s$/) # => ["apples", "grapes"]
fruits.grep(/s$/) { |e| e.start_with?("a") } # => [true, false]

In Ruby 2.5, this parameter argument was added to the Enumerable predicate methods all?, none?, one?, and any?.

fruits = %w(apples orange grapes)
fruit.any?(/s$/) # => true

# === works with more than Regexes!
[1, 3.14, 2ri].all?(Numeric) # => true
[0, 1, 2, 3].all?(1..10) # => false
[0, 5].one?(1..3) # => false
[0, 5].none?(1..3) # => true

More Expressive Regular Expressions with Ruby

I came across some parsing code that contained this regular expression:

# the first capture is the left quote
# the second capture is the string content
# the third capture is the right quote
METHOD_CAPTURE = /Module\.method\(\s*(['"])(.+?)(['"])\s*\)/

This regexp is matching the string contents of a particular method call. It captures three pieces of information, mentioned in the comments.

This code is not self-documenting. We have three comments explaining the captures, and a regexp we must parse in wetware.

Furthermore, numerical indexes are difficult to track and modify in complicated regexps. PCRE supports named captures; denoted in Ruby by (?<name>pattern).

To make the comments superfluous, let's refactor using the following:

  1. Use named capture groups
  2. Use interpolation to give descriptive names to common components
  3. Don't capture needlessly (in our case, the captured quote characters are not used)
  4. Prefer [] over escaping (personal preference)
quote_character = %q|['"]|
optional_whitespace = "\s*"

METHOD_CAPTURE = /Module[.]method[(]#{optional_whitespace}#{quote_character}(?<string_contents>.+?)#{quote_character}#{optional_whitespace}[)]/

# #match returns an object or nil
matches = 'Module.method("some string")'.match(METHOD_CAPTURE)

# if an object, access captures by name:
matches[:string_contents] # "some string"

You can tailor how many named expressions/variables to use based on the complexity of the regexp.

Copy current file path relative to project root

I already knew about copying the current file path to the clipboard by using Shift+Cmd+C . The problem with this approach is that it copies the absolute path, for example, /Users/arturo/src/cool_project/lib/module/my_file.rb. This is not ideal if you are planning on sending this path to someone else or for some document you are writing.

A better option is to use RubyMine's Action Copy Reference which by default is bound to Shift+Alt+Cmd+C. This copies the current file path relative to the project, for example, lib/module/my_file.rb

To summarize:

Copy Paths Action

  • Default shortcut: Shift+Cmd+C
  • Example text to clipboard: /Users/arturo/src/cool_project/lib/module/my_file.rb

Copy Reference Action

  • Default shortcut: Shift+Alt+Cmd+C
  • Example text to clipboard: lib/module/my_file.rb

Thanks to Jordan N. for the tip!

Force push safely using --force-with-lease

We periodically force push feature branches when we rebase them.

To do this safely, I first check manually to see if my pair has pushed any commits I don't yet have in my local branch.

But there's an easier and safer way to do this. The --force-with-lease option will fail if there are upstream changes not yet merged.

It will work smoothly for standard rebasing situations, but protect against any inadvertent destructive force pushes.

Thanks to Jason K for sharing this tip with me!

Finding Where a Method is Defined

One great thing about Ruby is how flexible it is. Although sometimes it can be hard to determine where a method definition comes from.

One useful technique to pull out in just this circumstance is the source_location method.

For example, suppose you see a call to the quantity method in a spec and you wonder where its definition comes from. Do some puts debugging by adding this line:

puts method(:quantity).source_location

Lambda argument passing shorthand

Suppose that I have a Ruby lambda like so:

greeting = -> name { "Hello #{name}" }

The conventional way of calling this lambda is like so:

greeting.call("Ned") # "Hello Ned"

However, for those of you dreading having to type in call (hello, JavaScript developers), you can use this syntactic sugar instead:

greeting["Ned"]
greeting.("Ned")

Source: https://stackoverflow.com/questions/18774139/how-works-with-lambdas

UPDATE

I am now a sad panda to learn that this shorthand syntax is not recommended in the ruby-style-guide: https://github.com/bbatsov/ruby-style-guide/issues/205 https://github.com/bbatsov/ruby-style-guide/blob/master/README.md#proc-call

It's still a cool learning for me to know that this syntax exists in the first place, though.

FactoryGirl identifiers as symbols not strings

Why is FactoryGirl.create(:my_object) better than FactoryGirl.create("my_object")?

Symbols are immutable objects that are stored by the Ruby interpreter as a numeric ID (an implementation detail, the design of Ruby is flexible for different storage mechanisms).

Strings, on the other hand, take up a memory footprint as large as the number of characters in the string. Using symbols will thus take up less memory and potentially be faster because the same address in memory will be used.

If you have n instances of the same string in your code, Ruby will use O(n) memory to store all those strings, however, if you have n instances of the same symbol in your code, Ruby will use O(1) memory to do the same lookup.

Further reading: https://bugs.ruby-lang.org/issues/7792#note-58

This TIL came courtesy of a discussion with Evan and later on Arturo about best practices in writing test code, but shared here because it's broadly applicable and the FactoryGirl example is just one use case.

Z-Index Equivalent in SVG

To mimic the z-index CSS property in SVG, add the SVG elements to the page in the reverse order that you expect their z-positioning to be set. The subsequent elements added are placed on top of previous elements.

For example, if I were using the React SVG charting library Victory and I wanted my chart lines to be stacked on top of my chart area shading, I will add them to my component like so:

<VictoryChart>
  <VictoryArea ... />
  <VictoryLine ... />
</VictoryChart>

Combine all ES6 generator values into an array

The ES6 spread operator can be applied to an iterable to combine all its results into one single array. A trivial use case for this is to merge extra elements into an existing array (ie, [...existingArray, 2, 3]).

This usage of the spread can be applied to a Generator to combine all the results of the calls to next() into one array. This serves as syntactic sugar to replace needing to use a for-of loop to do the same operation. Here's an example (illustrative purposes only, ignore that this is not the best way to solve this problem):

function* evenNumbersGenerator(maxNum) {
  for (let i = 0; i <= maxNum; i += 1) {
    if (i % 2 == 0) {
      yield i;
    }
  }
}

...

const evenNumbersTo100 = [...evenNumbersGenerator(100)];

Side Learning: Generator functions cannot be declared as an arrow function, because they have to be declared as a non-method function.

Surround <g> around array of React SVG components

It is a typical practice when writing a React component that renders a list/array of components to surround these components around a <div> tag. This is because React does not directly support rendering arrays of components.

This practice will not work if the React components will deep-render SVG elements instead of HTML markup. The solution instead will be to wrap the array of SVG-based child components around <g> tags (which stands for group in SVG).

https://www.smashingmagazine.com/2015/12/generating-svg-with-react/

Exclusion using File Masks

When using Find in Path.. functionality to find a word across multiple files, file masks can be used to match certain types of files. For example, using *.rb will only look through Ruby files. On the other hand, if you want to exclude Ruby files instead, you can add an ! at the front (i.e. !*.rb).

Here are other useful examples/combinations:

all files excluding spec tests: !*spec.rb

all Ruby files excluding spec tests: *.rb,!*spec.rb

Add have_selector() matcher to RSpec Request Specs

If you are used to writing controller specs, you are probably comfortable with the `have_selector matcher. However, in request specs this matcher is not available. By default, you can only do text search inside the request body which leads to brittle assertions.

You can add the have_selector matcher by updating your RSpec config to include the Capybara matchers on request specs as well.

RSpec.configure do |config|

config.include Capybara::RSpecMatchers, type: :request

end

Then you can write more confident Request specs by using assertions like expect(response.body).to have_selector('ul li', text: 'List content here!')

Stop a docker-compose container without removal

Suppose you need to stop your docker-compose container but you don't want to remove the container. For example, this container runs your database, so removing the container would mean that you would also lose all your data.

Don't use docker-compose down. This will remove your container and you will have rebuild your database from scratch. Sad panda.

Instead, use docker-compose stop. You can then restart the container and have all the data back that you had before.

Resources:

Search DOM by selector in Chrome Inspector

Problem

I want to select a DOM element by CSS selector on my React-generated web page for debugging purposes. In this case, I am trying to test out CSS selectors to be used in my Capybara acceptance test.

Solution

Use jQuery NO, DON'T DO THAT!

A neat feature of the Chrome Web Inspector is that I can search an entire page by CSS Selector, without needing to litter my code with debugger statements. Just open up the Elements tab and then press CMD-F (on Mac) to open up a search bar. I can now type whatever CSS Selector that I want and view the results that match. I can quickly test different selectors out, so that I can verify that I am writing my Capybara test accurately.

Source

An Improvement to the Behaviour of the Git Pager

First, capture your current git pager settings (in case you want to go back):

git config --list | grep core.pager

Second, configure your new and improved git pager settings:

git config --global core.pager "less $LESS --tabs=2 -RFX"
--tabs=2: Is just right for displaying Ruby diffs

-R: Repaint the screen, discarding any buffered input
-F: Causes less to exit if a file is less than one screens worth of data
-X: Leave file contents on screen when less exits.

If you want to get even fancier consider diff-so-fancy.

Bulk Upsert through PostgreSQL 9.5+

Warning: This only works for PostgreSQL 9.5+


Given the following:

  1. a users table:

    • id
    • name
    • created_at
    • updated_at
  2. users table only has 1 user with values:

    • id: 1
    • name: Alejandro
    • created_at: '2010-10-10 10:00:00.000000'
    • updated_at: '2010-10-10 10:00:00.000000'

You can upsert using the following SQL query:

INSERT INTO
  users(id, name, created_at, updated_at)
VALUES
  (1, 'Alexander', NOW(), NOW()),
  (2, 'Belle', NOW(), NOW())
ON CONFLICT (id)
  DO UPDATE SET
    name=EXCLUDED.name,
    updated_at=NOW()
;

Results:

  1. User(id=1) will be renamed from Alejandro to Alexander. The updated_at value will be set to current time.
  2. User(id=2) will be inserted to users table with name = Belle, and both created_at and updated_at will be set to current time.

Chrome: Inspecting DOM elements that require focus

Using Chrome Dev Tools, I occasionally want to inspect an element that requires focus - for example, inspecting a selected date in a date selector.

Problem

As soon as I click the dev tools window, the element loses focus and I can no longer inspect in with the desired state.

Undesirable solution

On occasion when I've run into this scenario, I've placed a breakpoint or debugger statement in the JavaScript function that would be called when focus is lost. The problem with this is that it takes time and I need to locate the appropriate place in code.

Better solution

When in the desired state - for example, with the current date selected - pressing F8 will pause JavaScript execution. I can then inspect the DOM in the desired state.

Diff CSVs With Ease

We're all familiar with diff tools like RubyMine, vimdiff, or the good old diff command. These work well for source code but are not optimal for CSVs files, which may have many columns and rows.

I found myself wanting to write CSV-specific diff tool, but I fought that Not Invented Here impulse and Googled first. I found a good Python library called csvdiff.

Imagine we have the following CSV file:

id,name
1,Alan Turing
2,John McCarthy
3,Edger Djikstra

We want to compare it to another file:

id,name
1,Alan Turing
3,Edsger Dijkstra
4,John Von Neumann

We've removed, edited, and added a row. The summary option confirms our changes:

$ csvdiff --style=summary id one.csv two.csv
1 rows removed (33.3%)
1 rows added (33.3%)
1 rows changed (33.3%)

The detailed view gives us all the gory details:

$ csvdiff --style=pretty id one.csv two.csv
{
  "_index": [
    "id"
  ],
  "added": [
    {
      "id": "4",
      "name": "Jon Von Neumann"
    }
  ],
  "changed": [
    {
      "fields": {
        "name": {
          "from": "Edger Djikstra",
          "to": "Edsger Dijkstra"
        }
      },
      "key": [
        "3"
      ]
    }
  ],
  "removed": [
    {
      "id": "2",
      "name": "John McCarthy"
    }
  ]
}

Range prefix to VIM command (from current line)

When I want to execute a command in VIM over a range of lines (for example, search-replace with :s) starting from the current line, I could execute a command like so:

:.,.+10s/foo/bar/g

This reads as search-replace from the current line (.) until 10 lines after. While useful functionality, it does require quite a bit of typing to execute.

Thankfully, there is a neat little shortcut that can be used to reduce some of this type. Simply enter the number of lines that you want to change from the current line and VIM will fill in the rest in the command prompt.

For example, I need to type 11: and VIM will insert :.,.+10 into the command prompt. You can now finish off this command like needed. Do note that the line count includes the current line itself (think of this count as current line plus number of lines after).

Squish Those Strings

While reading some Rails code, I came across a deprecation warning:

ActiveSupport::Deprecation.warn(<<-MESSAGE.squish)
  `redirect_to :back` is deprecated and will be removed from Rails 5.1.
  Please use `redirect_back(fallback_location: fallback_location)` where
  `fallback_location` represents the location to use if the request has
  no HTTP referer information.
MESSAGE

What caught my eye was the squish method on the heredoc. It's common to see methods after heredocs to clean up formatting, but squish is a great method name.

squish removes all leading and trailing whitespace, then replaces all consecutive whitespace with a single space. One application has been cleaning up long string messages that use the line continuation operator. The community style guide says to only use line continuations for concatenating strings, but I think squish is cleaner:

long_string = "a long string " \
              "spanning " \
              "three lines"
# => "a long string spanning three lines"

better_long_string = "a long string
                      squished to a single line
                      without extra spaces or backslashes".squish
# => "a long string squished to a single line without extra spaces or backslashes"

An all-too-common caveat: squish is an extenstion method from active_support.

Using Trigram Indexes to Speed Up LIKE Queries

Queries containing ILIKE '%anything%' result in table scans since they have a leading wildcard. Typical btree indexes can not help improve performance in this case.

Trigrams are 3-character slices of words:

SELECT show_trgm('Ruby');
-- {"  r"," ru","by ",rub,uby}

They are useful as indexes since they can speed up LIKE, ILIKE, ~, and ~* clauses.

Let's query a table of 14K email addresses:

CREATE TABLE emails (email TEXT);

\copy emails FROM 'emails.csv' DELIMITER ',' CSV;

EXPLAIN ANALYZE SELECT * FROM emails WHERE email ILIKE '%ion%';

The query plan shows a table scan:

Seq Scan on emails
  Filter: (email ~~* '%ion%'::text)
  Rows Removed by Filter: 14040

with an average execution time of 15ms. Let's create a trigram index and try again:

-- postgres 9.2+
CREATE EXTENSION IF NOT EXISTS pg_trgm;

CREATE INDEX emails_search_email_idx ON emails USING GIN (email gin_trgm_ops);

EXPLAIN ANALYZE SELECT * FROM emails WHERE email ILIKE '%ion%';

The improved query plan is:

Bitmap Heap Scan on emails
  Recheck Cond: (email ~~* '%ion%'::text)
  Heap Blocks: exact=98
    -> Bitmap Index Scan on emails_search_email_idx
       Index Cond: (email ~~* '%ion%'::text)

and averages 0.8ms. A 19X improvement without updating any SQL queries! YMMV

bundle update --conservative

Let's say you want to update the gem foo. After running bundle update foo you look at your gemfile.lock and find that not only was foo updated, but so were many of its dependencies. You also notice that many of these dependency updates weren't necessary, as the previously installed versions were compatible with the new version of foo.

The default bundle update foo behaviour will unlock and update all dependencies of foo.

If you don't want to update these dependencies unnecessarily, one solution is to add the current versions to your gemfile.lock.

However, an easier way to prevent the updating of shared dependencies is to use bundler's new --conservative flag.

All the different ways to lock your Mac computer

  • Using the keyboard: CTRL-SHIFT-eject
  • Using Alfred: execute the lock command
  • Using a taskbar icon from Keychain:
    • Open the app Keychain Access
    • Preferences --> Enable the option Show keychain status in menu bar
    • A lock-shaped icon will appear in the taskbar, with the option Lock Screen
  • Use Hot Corners:
    • System Preferences --> Desktop & Screen Saver --> Hot Corners button
    • Set one of the corners as Put Display to Sleep
    • Mouse into the direction of that corner (on the monitor closest to that side, for multi-monitor setups)
  • If all else fails, just hold the Power button on your keyboard for a second to put your computer to sleep

async/await Keywords of ES7 for Simpler Promises

ES7 introduces the async/await keywords. They are mostly syntactic sugar on top of Promises. You can write cleaner more readable asynchronous tasks code.

NOTE: They are available in Node 7.6.0 also.

Example:

Here is some code for programmatically creating a coding exercise for a developer candidate that has applied to us. We've improved the readability of it using async/await.

This hard to read test which uses Promises:

it('returns any errors that may have occurred', () => {
  return automator
    .getRepo()
    .then(repo => !repo ? automator.createExercise() : Promise.resolve())
    .then(() => this.room.user.say('alice', `hubot create coding exercise repo for ${candidateEmail}`))
    .then(() => {
      expect(lastBotMessage()).to.contain(`Error creating coding exercise for *${candidateEmail}*:`)
    });
});

Becomes this:

it('returns any errors that may have occurred', async() => {
  let repo = await automator.getRepo();
  if (!repo) {
    await automator.createExercise();
  }

  await this.room.user.say('alice', `hubot create coding exercise repo for ${candidateEmail}`);

  expect(lastBotMessage()).to.contain(`Error creating coding exercise for *${candidateEmail}*:`)
});

Which reads more like an Arrange/Act/Assert style test.

Use PostgreSQL table as queue skipping locked rows

This command only works in PG 9.5

First, are you sure you shouldn't be using some in-memory queue? Or some message broker? Or Redis?

If you are really convinced that you want this sort of behaviour on top of the goo'old PostgreSQL you can achieve a queue-like access pattern by locking and skipping locked rows.

One way to ensure that only one database client can modify a set of rows is to select the rows for update as in

BEGIN;
SELECT * FROM queue ORDER BY priority DESC LIMIT 1 FOR UPDATE;
...

This will block any other UPDATE or SELECT .. FOR UPDATE until the above transaction is finished. Now if you want concurrent database clients to fetch the next row available in the priority list just use:

BEGIN;
SELECT * FROM queue ORDER BY priority DESC LIMIT 1 FOR UPDATE SKIP LOCKED;
...

The above command could be interpreted as select the next row from queue that nobody has yet locked.

Ignore whitespace-only changes in Gitlab MRs

Problem

You are reviewing a Gitlab Merge Request (MR). It involes changes where a Ruby file is moved into or out of particular modules. This means that one or more module ... end constructs are either added or removed around the entire class, resulting in a tabbing-width change on almost every line of the file. This makes reviewing the file in the MR quite difficult, as the reviewer will need to sift through the code diff and separate out actual logic changes from whitespace-only changes.

Solution

By appending ?w=1 to the end of the URL of the MR, Gitlab will ignore all lines that only feature a whitespace change in the code diff. This means that the only changes visible will be ones with a non-whitespace change, thus allowing the reviewer to focus in on actual logic changes and not waste time reading whitespace changes.

Time to poke Gitlab EE support on this issue: https://gitlab.com/gitlab-org/gitlab-ce/issues/1393

Assignment on associations will bypass validation

Important gotcha that assignment to has_many associations will cause an immediate save even if callback validation fails.

u = User.last

u.accounts = []

u.save # returns false because this user cannot have blank accounts

u.reload.accounts # returns empty array

The gotcha here is that save is a no-op really. As soon as u.accounts=[] is called, the data is saved immediately, bypassing validation.

Fixing ZDT Deploys with Monitoring-Driven Develop.

We were debugging a bug in our zero downtime deploy script. We tested the deploy using Chef, Kitchen and Vagrant. The bug was causing an error page to show for less than 3 seconds at the very end of the deploy.

We used Monitoring Driven Development to consistently reproduce the bug (the red phase), and to validate our fix (the green phase). Here were the steps:

Preparation:

  1. kitchen login # ssh to the vagrant box
  2. sudo tail -fn100 /var/log/nginx/go.access.log # to see the response codes from the server. If all responses show 200 code during the deploy, the deploy is working.
  3. Open other terminal window
  4. kitchen login # ssh to the vagrant box
  5. watch -n 1 "curl localhost" # make a request every 1 second

Then we followed this feedback loop

On the host computer:

  1. Make changes to the deploy recipe
  2. kitchen converge # this will run our deploy
  3. Check the output of the logs to see the result of the changes
  4. Repeat the loop until bug is fixed

Replacing num.times.map with Array.new(num)

Problem

I want to create an array containing objects created with an incrementing integer index parameter. For example, an array of hashes containing strings built off of the incrementing number.

Standard Solution

my_array = num.times.map do |index|
  build_hash(index)
end

BUT...rubocop didn't like this:

... C: Performance/TimesMap: Use Array.new with a block instead of .times.map

Improved Solution

The improved solution allows us to build the same array with less chained methods, thus improving readability:

my_array = Array.new(num) do |index|
  build_hash(index)
end