Today I Learned

6 posts by shahriyarnasir

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.

Decorator Pattern in Ruby with SimpleDelegator

The Decorator Pattern allows us to chain new behaviours to objects without modifying the underlying objects. It is an application of the Open/Closed Principle. This pattern is useful for example when we need to tack on logging, monitoring, and other non-functional requirements to objects.

In Java or C# this can be achieved using interfaces. In Ruby, we can use the SimpleDelegator class to achieve this:

require "delegate"

class FooDecorator < SimpleDelegator
  def bar
    "This is a decorated #{__getobj__.bar}"
  end
end

class Foo
  def bar
    "bar"
  end

  def fiz
    "Fiz"
  end
end

decorated = FooDecorator.new(Foo.new)
puts decorated.bar # outputs "This is a decorated bar"
puts decorated.fiz # outputs "Fiz"

double_decorated = FooDecorator.new(FooDecorator.new(Foo.new))
puts double_decorated.bar # outputs "This is a decorated This is a decorated bar"

Sources:

Why Git Uses (:<BRANCH>) to Delete Remote Branch

It would appear that the colon in git push origin :<branch-to-delete> is used exclusively to delete branches. But such is not the case.

The format for the refspec is*:

<source>:<destination>

This tells Git to push the source branch to the destination branch in remote. So if the source is blank, we get a leading colon. This has the effect of deleting the destination branch. Its like saying push null pointer to destination.

*You can learn more about the refspec in its entirety in this Stack Overflow

Reading Text File with Byte Order Mark Using Ruby

Ruby's File.read() can natively read a text file containing a byte order mark and strip it out:

text_without_bom = File.read("file.txt", encoding: "bom|utf-8")

Performance Metrics for Scripts Using Command Line

To quickly collect performance metrics for a script via command line:

  1. Start running the script. Make note of the process name that the script is running as (e.g. ruby)
  2. Create a script called profiler.sh with this content: ps aux | grep $1 | head -1 | awk '{print "CPU="$3 ", MEM="$4 ", RSS="$6}'
  3. Make the profiler executable: chmod +x profiler.sh
  4. Execute the profiler in a watch session every minute: watch -n 60 --no-title "./profiler.sh SCRIPT_IDENTIFIER | tee -a logfile". Where the script identifier is any text that we can use to grep for the process in the ps aux output.
  5. After your script is done running or you have enough data points, observe the output in logfile.

NOTE: RSS is resident set size

Expect to Receive and Call to Original

In integration specs, it is preferable to call the original method when setting up an expectation on an object to receive an invocation of that method. This way, the method isn't stubbed out but instead will still be invoked. Any downstream effects of calling that method won't be hidden.

class Calculator
  def self.add(x, y)
    x + y
  end
end

Should be tested like this:

require 'calculator'

RSpec.describe "and_call_original" do
  it "responds as it normally would" do
    expect(Calculator).to receive(:add).and_call_original
    expect(Calculator.add(2, 3)).to eq(5)  # any bugs inside of #add won't be hidden
  end
end

This code example is taken from: Relish - Calling the original implementation