22 Feb 2013, 18:20

Power

Finished a user athentication system today using BCrypt::Password.

There was an Aha! moment when I realized that they’ve defined the == operator to return true when the password matches, not when the strings are equal (as a novice like me might expect).

1.9.3p385 :002 > secret = BCrypt::Password.create("password")
 => "$2a$10$50UZDPv124TYHe4xwQLoBeuryd0lzcCkjVdepHQD41K9svNE7lXGe"

The hashed secret is saved in the database.  It’s later retrieved and checked against the user input using ==.

1.9.3p385 :005 > secret
 => "$2a$10$50UZDPv124TYHe4xwQLoBeuryd0lzcCkjVdepHQD41K9svNE7lXGe"
1.9.3p385 :006 > q = BCrypt::Password.new(secret)
 => "$2a$10$50UZDPv124TYHe4xwQLoBeuryd0lzcCkjVdepHQD41K9svNE7lXGe"
1.9.3p385 :007 > q == "password"
 => true

This also has the interesting side effect that == is not commutative.

1.9.3p385 :008 > "password" == q
 => false

My junior high math teacher would be disturbed by this.  Such is the power of Ruby.

20 Feb 2013, 10:58

The RubyMonk Tutorial

I’ve been working my way through the RubyMonk Tutorials. They are very well written and do an excellent job of guiding the user through progressively harder concepts.

Today I found a couple of careless coding errors in the section on using Array#inject (subscription required). The first is an illustration of inject to do a simple sum of array elements.

[4, 8, 15, 16, 23, 42].inject(0) do |accumulator, iterated|
  accumulator += iterated
  accumulator
end

In fact, the assignment statement here is superfluous, as the inject function assigns the return value of the block to the accumulator automatically. It would suffice to do:

[4, 8, 15, 16, 23, 42].inject(0) do |accumulator, iterated|
  accumulator + iterated
end

The second error is in an illustration of the behavior of inject. The function below is supposed to mimic the behavior of the one above.

def custom_inject(array, default = nil)
  accumulator = default || array[0]

  array.each do |element|
    accumulator = accumulator + element
  end

  accumulator
end

p custom_inject([4, 8, 15, 16, 23, 42], 0)

The custom_inject function, however, fails for the case where the default value is not given. It fails by counting the first array element twice.

Native inject begins iterating from the second array element, as the first element has already been used as the starting value.

18 Feb 2013, 17:18

Hi there.

Day one.

Got a new blog, and I’ve learned some Ruby basics on Rubymonk. Also got a helluva cold and pine for the bed.