Today I Learned

A Hashrocket project

127 posts about #ruby

Rails/PG Statement Timeout 🐘⏰

By default, Rails does not set a timeout on database statements. For example, this will run for a full day, even if your ruby process goes away.

ActiveRecord::Base.connection.execute(<<~SQL)
  select pg_sleep(86400);
SQL

The good news is that Rails provides a way to prevent this from happening from the database.yml with the statement_timeout variable.

default: &default
  adapter: postgresql
  ...
  variables:
    statement_timeout: 5000

I'm starting to think that this should always be set low. And then explicitly set higher on a per-query basis, when one is expecting something to take a long time.

Update a specific gem with bundler

bundle update <gemname> does not update the gem specified.

instead

bundle update --source <gemname> will update only the gem specified.

Chaining Multiple RSpec Change Matchers

It can be handy to use RSpec's change matchers to determine if some method or process creates a new record.

expect{ Registration.create(attrs) }.to change{ User.count }.by(1)

But what if we are testing a method that creates a couple different records in the system?

RSpec allows us to chain together change matchers with and. Consider this additional contrived example.

expect {
  Project.generate(attrs)
}.to change{ Project.count }.by(1).and \
     change{ User.count }.by(1)

In addition to keeping our tests tight and concise, this approach gives some pretty nice output on failure.

If we were just beginning our implementation with a failing test, we'd see a multi-part failure like the following.

Failure/Error:
  expect {
    Project.generate(attrs)
  }.to change{ Project.count }.by(1).and \
       change{ User.count }.by(1)

     expected result to have changed by 1, but was changed by 0

  ...and:

     expected result to have changed by 1, but was changed by 0

Rails on ruby 2.4: Silence Fixnum/Bignum warnings

Wanna use the latest ruby, but don't really need to be perpetually reminded that rails hasn't caught up with this latest ruby design change? Change the top of your config/application.rb thusly:

require_relative 'boot'

verbose = $VERBOSE
$VERBOSE = nil
require 'rails/all'
require 'active_support/core_ext/numeric/conversions'
require 'active_job/arguments'
$VERBOSE = verbose
Bundler.require(*Rails.groups)

module MyApp
  class Application < Rails::Application
  end
end

Yes, this will also suppress any other ruby warnings from the loading of rails code. ¯\_(ツ)_/¯

Rerun Only Failures With RSpec

After running a big test suite, I may have a bunch of output on the screen including the results of a couple test failures. I like to bring the context of the test failures front and center and make sure they are consistent test failures (not flickering failures). Instead of copying and pasting each failure, I can rerun rspec in a way that executes only the test cases that failed.

$ rspec --only-failures

This feature requires that you set a file for RSpec to persist some state between runs. Do this in the spec/spec_helper.rb file. For example:

RSpec.configure do |config|
  config.example_status_persistence_file_path = "spec/examples.txt"
end

See more details here.

h/t Brian Dunn

Appended Pathnames

Check this out:

[1] pry(main)> Rails.root.join("app", "assets") == Rails.root/"app"/"assets"
true

The right hand side of the double equals works because / is aliased to + in Ruby's Pathname class. It's valid syntax for building a pathname.

Confuse your friends!

h/t Brian Dunn

Documentation

Use A Case Statement As A Cond Statement

Many languages come with a feature that usually takes the name cond statement. It is essentially another way of writing an if-elsif-else statement. The first conditional in the cond statement to evaluate to true will then have its block evaluated.

Ruby doesn't have a cond statement, but it does have a case statement. By using a case statement with no arguments, we get a cond statement. If we exclude arguments and then put arbitrary conditional statements after the when keywords, we get a construct that acts like a cond statement. Check out the following example:

some_string = "What"

case
when some_string.downcase == some_string
  puts "The string is all lowercase."
when some_string.upcase == some_string
  puts "The string is all uppercase."
else
  puts "The string is mixed case."
end

#=> The string is mixed case.

source

where am i @?

When using the pry gem, @ is an alias for whereami

Ruby Arguments Can Reference Other Arguments

I love the dark corners of Ruby. Today we discovered this one by basically guessing that it might work:

def foos(foo, bar = foo.upcase + "!")
  puts foo
  puts bar
end
2.3.1 :001 > foos('foo')
foo
FOO!
 => nil

That's right; bar references another argument, foo. And we can also call a method on it. And concatenate it with a string, because, why not? The 'principle of least surprise' strikes again.

h/t Brian Dunn

Ruby $!

This week I enjoyed using Ruby's built-in global variables, including $!. $! refers to the last error that was raised, and is useful in lots of different contexts such as Rake tasks.

Here it is in action:

:001 > begin; raise NameError; rescue; puts "The error we raised was #$!."; end
The error we raised was NameError.

And a list of these global variables:

https://github.com/ruby/ruby/blob/trunk/lib/English.rb

For a slightly less bare-metal implementation, require this library and utitlize the friendly names:

:001 > require 'english'
 => true
:002 > begin; raise NameError; rescue; puts "The error we raised was #$ERROR_INFO."; end
The error we raised was NameError.

Create an infinite sequence in Ruby

seq = (0..Float::INFINITY).each is a one-liner that creates an infinite sequence.

irb(main):001:0> seq = (0..Float::INFINITY).each
=> #<Enumerator: 0..Infinity:each>
irb(main):002:0> seq.next
=> 0
irb(main):003:0> seq.next
=> 1
irb(main):004:0> seq.next
=> 2
irb(main):005:0> seq.next
=> 3

The case of meridian in Ruby's strftime

When formatting dates using strftime, you can include AM/PM with %p:

puts Time.now.strftime("%H:%M:%S %p")
# 20:40:52 PM

I didn't want PM capitalized, so I did this:

puts Time.now.strftime("%H:%M:%S %p").downcase
# 20:40:52 pm

But I found that you can also just use %P:

puts Time.now.strftime("%H:%M:%S %P")
# 20:40:52 pm

Yes that's right, when you want lowercase AM/PM, use uppercase P. When you want upppercase, use lower. It couldn't be more straightforward folks.

How to define a hash object in GraphQL

If your model has a json field or a serialized hash that you want to expose as a ObjectType, just specify the hash_key for each field:

UserPreferenceType = GraphQL::ObjectType.define do
  field :name, types.String, hash_key: 'name'
  field :value, types.String, hash_key: 'value'
end

Using Ruby Hash in `gsub`

Ruby String#gsub method also accepts a hash as second argument. This is perfect for some situations like mapping a phone-word to phone number:

phonewords = {
  'a' => 2, 'b' => 2, 'c' => 2,
  'd' => 3, 'e' => 3, 'f' => 3,
  'g' => 4, 'h' => 4, 'i' => 4,
  'j' => 5, 'k' => 5, 'l' => 5,
  'm' => 6, 'n' => 6, 'o' => 6,
  'p' => 7, 'q' => 7, 'r' => 7, 's' => 7,
  't' => 8, 'u' => 8, 'v' => 8,
  'w' => 9, 'x' => 9, 'y' => 9, 'z' => 9,
}
phone = "1-800-map-gsub"
puts phone.gsub(/[a-z]/, phonewords)
# => 1-800-627-4782

h/t @joshuadavey

Expecting change with RSpec #rails #testing #rspec

Usually when I try to test if a value has changed after a method has been called I will assert the initial value as one expectation followed by the action that changes it, and finally assert the value has changed.

For example this test will check if a user's bad login attempts are incremented when the user.record_bad_login! method is called:

describe '#record_bad_login!' do
  let(:user) { FactoryGirl.create(:user) }

  it 'increments the bad login attempts count' do
    expect(user.failed_login_attempts).to eq(0)
    user.record_bad_login!
    expect(user.failed_login_attempts).to eq(1)
  end
end

RSpec provides us with a more straight forward way to oneline this type of test while making it more declarative:

describe '#record_bad_login!' do
  let(:user) { FactoryGirl.create(:user) }

  it 'increments the bad login attempts count' do
    expect { user.record_bad_login! }.to change { user.failed_login_attempts }.from(0).to(1)
  end
end

Read more here: https://www.relishapp.com/rspec/rspec-expectations/v/2-0/docs/matchers/expect-change

Or Operator Precedence

What's the difference between || and or in Ruby?

Let's look at an example to find out. First, let's start with some boolean variables:

> a, b = false, true
=> [false, true]

Now, let's try the different or operators:

> a || b
=> true
> a or b
=> true

Cool, they seem to work as expected.

Finally, let's capture the result in a variable:

> c = a or b
=> true
> c
=> false

But why is c false and not true? Operator precedence. The assignment operator (=) takes precedence over the or operator causing c to be assigned to the value of a (false) before or'd with b.

source

Ruby's `gsub` with Block

Today I learned that Ruby's gsub method accepts a block. This seems useful for complex replacements.

2.1.0 :001 > "look at those potatoes".gsub(/p.*s/) do |match|
2.1.0 :002 >     match.upcase + '!!!'
2.1.0 :003?>   end
 => "look at those POTATOES!!!"

Documentation

Ruby XOR operator

The ^ acts is a boolean XOR operator in Ruby when the arguments are boolean. It wants only one true value in an expression in order to be considered true:

true ^ false ^ false
# => true

true ^ false ^ true
# => false

Let's look at 5 trues:

true ^ true ^ true ^ true ^ true 
# => true

How is this true? Each ^ is evaluated one at a time. Since true ^ true is not exclusive, it is false. So after the first evaluation, we have:

false ^ true ^ true ^ true

# false ^ true is true

true ^ true ^ true

#true and true is false
false ^ true
# true

Using this same logic we can see why true ^ true ^ true ^ true is false.

Dealing with exit signals on Ruby

When working on CLIs it's useful to treat if the application exists. Image you have a long application and even if the user hits a <Ctrl+c> to kill the process you still want to display the results so far.

There is a Ruby Kernel method at_exit that runs the block passed to it if the current process exists. Here is an example:

# print_at_exit.rb
at_exit { puts "Come back later!" }
puts "sleeping for 5 secs"
sleep 5

If you run this file and wait it until it finishes you'll get:

ruby print_at_exit.rb                                                                                                                {130}
#=> sleeping for 5 secs
#=> 
#=> Come back later!

But now, if you run it and hit <Ctrl+c> for finishing the process earlier you'll get:

ruby print_at_exit.rb
#=> sleeping for 5 secs
^C
#=> Come back later!
#=> print_at_exit.rb:6:in `sleep': Interrupt
#=>         from print_at_exit.rb:6:in `<main>'

h/t @nikkypx

Compare semantic versions in Ruby

Gem::Version.new('1.0.1') > Gem::Version.new('1.0')

Return `MatchData` with `$~`

Check out this Ruby regex:

2.1.0 :001 > "totally gourmet" =~ /totally/
 => 0

There's a match at index zero. But what is the thing that actually matched? Enter $~:

 2.1.0 :002 > $~
  => #<MatchData "totally">

$~ stores the result of the last regex, and can be called later on. This is equivalent to the match method:

2.1.0 :003 > /totally/.match('totally gourmet')
 => #<MatchData "totally">

h/t Brian Dunn

Ruby defined? method evaluation

Today I learned that Ruby Object method defined? evaluates if the argument is anything recognizable, not just if the variable are set. Here are some examples:

undefined_foo #=> NameError: undefined local variable or method `undefined_foo'
defined? undefined_foo #=> nil

defined? nil #=> "nil"

defined? "foo" #=> "expression"
defined? [] #=> "expression"
defined? def x; end #=> "expression"
defined? class Foo; end #=> "expression"

defined? @foo = :bar #=> "assignment"

@foo = :bar
defined? @foo #=> "instance-variable"

foo = :bar
defined? foo #=> "local-variable"

def foo; end
defined? foo() #=> "method"

class Foo; end
defined? Foo #=> "constant"

h/t @VidalEkechukwu

Filter Your Seed-Fu Seeds

Seed-Fu accepts two options that are really useful for narrowing the impact (and speed) of your database seeding.

You can seed only from a certain file or directory:

$ rake db:seed_fu FIXTURE_PATH=path/to/fixtures

Or, filter seeds based on matching filenames:

$ rake db:seed_fu FILTER=users,articles

h/t Brian Dunn & Josh Davey

Ruby try shortcut - Safe Navigation Operator

Today I learned that ruby (2.3.0) has an operator called Safe Navigation &. and this is like a short cut for that Rails try method:

foo = nil
foo.bar
# NoMethodError: undefined method `bar` for nil:NilClass
#   from (irb):18
foo&.bar
# => nil

class Foo
  def bar
    :barzzz
  end
end
foo = Foo.new

foo.bar
# => :barzzz
foo&.bar
# => :barzzz

h/t @mattpolito

How to get memory used by a Ruby object

Today I learned how to get the spaced used by a ruby object using ObjectSpace.memsize_of:

require 'objspace'
ObjectSpace.memsize_of('@')
# => 40
ObjectSpace.memsize_of('@'*23)
# => 40
ObjectSpace.memsize_of('@'*24)
# => 65
ObjectSpace.memsize_of('@'*25)
# => 66

The memory your Ruby process is taking

Today I learned how to get the memory taken by a Ruby process from inside a Ruby code:

def mem
  `ps ax -o pid,rss | grep -E "^[[:space:]]*#{$$}"`.strip.split[1] + ' KB'
end
mem
# => "61772 KB"

By the way in Ruby $$ is the same as Process.pid.

Ruby's `__LINE__`

Debugging a tough problem, with terse, unhelpful error messages? Sometimes puts driven development can only take you so far.

A corner of Ruby I sometimes forget about are the double-underscore methods on Object. Today I learned a new one: __LINE__.

Here it is in the console:

2.1.0 :001 > puts __LINE__
1
 => nil
2.1.0 :002 > puts __LINE__
2
 => nil
2.1.0 :003 > puts __LINE__
3
 => nil

Try putting this above and below code you think might be causing an issue.

A new tool for my debugging toolbox. 🔨

Documentation

h/t Brian Dunn

Bundle in parallel using full CPU powa!!! #rails

Don't you wish there was a faster way to install your bundled gems for a project? Especially when cloning an existing Rails application from Github?

more powa

It turns out that since Bundler v1.5, Bundler supports Parallel Install.

To run bundler with parallel install use the --jobs option or -j for short.

Assuming your computer has 4 cores you can try

$ bundle install --jobs 4
$ # or
$ bundle install -j4

Finally if you want to set bundler to always use parallel install you can run this command:

bundle config --global jobs 4

The bundler team has seen speedups of 40-60%. That's amazing!

h/t Micah Cooper && bundler documentation

Ruby Method arity

Today I learned that Method#arity does not consider blocks.

Also it returns negative with splat arguments.

Finally, all keyword arguments counts 1.

class Foo
  def one; end
  def two(a, b); end
  def three(a, *b); end
  def four(a, &b); end
  def five(a, b:, c:); end
end

puts Foo.instance_method(:one).arity
# => 0
puts Foo.instance_method(:two).arity
# => 2
puts Foo.instance_method(:three).arity
# => -2
puts Foo.instance_method(:four).arity
# => 1
puts Foo.instance_method(:five).arity
# => 2

h/t @higgaion

Require Entire Gemfile In Pry Session

Want to experiment in a pry session with some of the gems in your project's Gemfile? You can quickly require all the gems for your project using Bundler's #require method.

Just require bundler itself and then execute Bundler.require. Everything will be loaded in.

> require 'bundler'
=> true
> Bundler.require
=> [Gem::Dependency.new("devise", Gem::Requirement.new([">= 0"]), :runtime),
 Gem::Dependency.new("rails", Gem::Requirement.new(["= 4.2.5"]), :runtime),
 Gem::Dependency.new("pg", Gem::Requirement.new(["~> 0.15"]), :runtime),
...

String Interpolation With Instance Variables

When using regular variables with string interpolation in Ruby, they must be wrapped in curly braces (e.g. "This is a #{variable}"). With instance variables (and class and global variables) you can just use the octothorp followed directly by the variable.

Here is an example of this in action:

class Person
  def initialize(name)
    @name = name
  end

  def whoami
    puts "I am #@name"
  end
end

bob = Person.new("bob")
#=> #<Person:0x007fdaf3291618 @name="bob">

bob.whoami
# I am bob

This is a handy shortcut, but may affect readability and/or result in an interpolation error at some point. Your mileage may vary.

h/t Josh Davey

Ruby Here Documents - "squiggly"

Today I learned that ruby 2.3.0 has released the squiggly heredoc <<~HEREDOC, like:

sql = <<~SQL
SELECT *
FROM users
WHERE users.status = 'active'
SQL

ActiveRecord::Base.connection.execute(sql)
  • <<HEREDOC => plain text
  • <<-HEREDOC => plain text, may indent the closing identifier
  • <<~HEREDOC => plain text, could indent the content

reference

Ruby Literals - Here Documents

Create A Hash From An Array Of Arrays

The ::[] method on the Hash class allows you to succinctly create a hash from an array of arrays -- or rather an array of tuples which are key value pairs.

> Hash[ [["a",2],["b",4]] ]
{"a"=>2, "b"=>4}
> Hash[ [[1,2],[3,4]] ]
{1=>2, 3=>4}

See the Hash::[] docs for more details.

h/t Josh Davey

Edit Previous Parts Of The Pry Buffer History

Each line of Ruby you enter into a Pry session is recorded with a number in the buffer history. Pry keeps this buffer history so that you can recall parts of it for editing and subsequent execution.

If you use the edit command by itself, Pry will open the previous Ruby statement in your default editor. But what if you want to edit a statement from a while back? Or even a series of statements?

Use the --in flag with edit either specifying a single record in the buffer history or a range of records.

$ pry
[1] pry(main)> puts "Hello"
Hello
=> nil
[2] pry(main)> puts "World"
World
=> nil
[3] pry(main)> puts "People"
People
=> nil
[4] pry(main)> edit --in 1..2
Hello
World
=> nil

The Ruby % notation

So ruby have this % notation inspired by Perl to define a string.

Here are some different ways to generate the same string:

%{hello world}
%<hello world>
%(hello world)
%[hello world]
'hello world'
"hello world"

=> "hello world"

Ruby Associative Arrays

assoc_arr = [[:foo, :bar], [:baz, :qux]]

assoc_arr.assoc(:foo)
# => [:foo, :bar]
assoc_arr.assoc(:baz)
# => [:baz, :qux]

assoc_arr.rassoc(:bar)
# => [:foo, :bar]
assoc_arr.rassoc(:qux)
# => [:baz, :qux]

Tap that

While Object#tap's primary usage is to tap into a pure functional styled method chain (get it... tap into?) its usefulness for me comes from returning its receiver. This is fairly typical Ruby code you're likely to encounter in the wild:

def tiny_rick!
  user = User.new
  user.name = 'Rick'
  user.surname = 'Sanchez'
  user
end

Making use of Object#tap we can golf this down and remove the need for the implicitly returned user:

def tiny_rick!
  User.new.tap do |user|
    user.name = 'Rick'
    user.surname = 'Sanchez'
  end
end

This is all the better when you consider the few lines that make up Object#tap's implementation:

class Object
  def tap
    yield self
    self
  end
end

rvm get master

Today while upgrading Rubies with RVM, I learned something— you have to go outside rvm get stable && rvm list known to see all the Ruby versions available.

When I ran these two commands on my machine, the newest Ruby listed was 2.3.0. I happen to know this is not correct; 2.3.1 was released last month.

An alternative is to use rvm get master && rvm list known. The master branch revealed the newer release. Interestingly, I was still able to install 2.3.1 via RVM before I found this solution, I just couldn't see that it was available.

The release manager for RVM explains:

http://stackoverflow.com/questions/12650164/update-rvm-list-known#answer-12650963

How to take next elements with Enumerator

So we had this logic to get the next 10 Tuesdays and Thursdays:

date = Time.current
(1..10).map { date = next_available_day(date) }

def next_available_day(date)
  loop { return date if tuesday_or_thursday?(date += 1.day) }
end

def tuesday_or_thursday?(date)
  date.wday == 2 || date.wday == 4
end

With Enumerator it seems cleaner:

next_available_dates(Time.current).take(10)

def next_available_dates(date)
  Enumerator.new do |enumerator|
    loop { enumerator.yield date if tuesday_or_thursday?(date += 1.day) }
  end
end

def tuesday_or_thursday?(date)
  date.wday == 2 || date.wday == 4
end

h/t by @mwoods79

Using pessimistic gem version to catch betas

The trouble with pessimistic (~>) versioning is that it still won't catch pre-release library versions... or will it.

It actually can allow 'beta' versions by adding an 'x' to the version you'd like to catch.

gem "rails", "~> 5.x"

Since 'beta' versions (5.0.0.beta3) actually register as higher than 5.0.0, the pessimistic operator will not catch the beta version. Gem versioning shows any version with a letter as 'pre-release' which is how beta3, rc1, alpha versions work.

Using the 'x' as a wildcard will allow pre-release gem versions to be caught.

Running A Single MiniTest Example

Consider the following MiniTest file:

# test_stuff.rb
require 'minitest/autorun'

class TestStuff < MiniTest::Unit::TestCase
  def test_first_thing
    assert_equal 4, (2 * 2)
  end

  def test_second_thing
    assert_equal 9, (3 * 3)
  end
end

If we want to run all the tests in this file, we can do so with:

$ ruby test_stuff.rb

But what if we want to run a specific test? We can target a single MiniTest example with the --name flag and the name of that example. We can do something like the following:

$ ruby test_stuff.rb --name test_second_thing

source

Ruby Keyword Arguments - mandatory params

If you do not set a default value for a keyword argument it will become mandatory and will raise an ArgumentError.

an example:

def mandatory_keyword(bar:)
  "foo=#{bar}"
end

def default_keyword(bar: nil)
  "foo=#{bar}"
end

and its test:

describe 'keyword_arguments' do
  it { expect{mandatory_keyword()}.to raise_error(ArgumentError) }
  it { expect(mandatory_keyword(bar: 'bar')).to eq('foo=bar') }

  it { expect(default_keyword()).to eq('foo=') }
  it { expect(default_keyword(bar: 'bar')).to eq('foo=bar') }
end

In case you don't want this behavior you can always set a default to nil.

Ruby array shortcuts - "&:" and "&method"

Call a method on every items with &:

So this:

[:foo, :bar].each do |item|
  item.to_s
end

Can be reduced to:

[:foo, :bar].each(&:to_s)

But, what if you want to call a method for each item in an array, and this item should be a parameter for this method?

Call a method with every items as a parameter with &method

So this:

[:foo, :bar].each do |item|
  puts(item)
end

Can be reduced to:

[:foo, :bar].each(&method(:puts))

Ruby Retry- Where you been?

For some reason, I never knew about ruby's retry keyword. The more you know...

def api_request
  TwitterWrapper.make_request # Throws a ServiceUnavailabe(506)- Server overloaded
 rescue ServiceUnavailable => error
    retries = retries.to_i + 1 # Increment a retry counter
    retries < 5 ? retry : raise(error) # run the method again until "retries is exceeded"
    # notice the local variable "retries" is persisted through retries
end

You could put a sleep in there if you wanted to wait a certain amount of time before retrying.

h/t Vinicius Negrisolo

Difference betweent `to_a` and `to_ary`

  • to_a => called for explicit conversions
  • to_ary => called for implicit conversions

example:

class Coordinates
  attr_reader :x, :y
  def initialize(x, y)
    @x, @y = x, y
  end

  def to_a
    puts "to_a called"
    [x, y]
  end

  def to_ary
    puts "to_ary called"
    [x, y]
  end
end

coordinates = Coordinates.new(5, 7)

puts "splat"
a = *coordinates
# => to_a called

puts "multiple assignment"
x, y = coordinates
# => to_ary called

puts "Implicit conversion into block params"
[coordinates].each { |(x, y)| puts x }
# => to_ary called

Don't load gem docs by default.

You don't need to generate/install the ruby documentation of those gems if you don't want to!

Put a .gemrc file in your home dir and include the line.

gem: --no-document

H/T Vidal Ewechukwu

Ruby Hash's update method

Today I learned that update is a synonym for merge! for a hash.

a = {x: 1}
a.update({y: 2})
a == {x: 1, y: 2}

I say update is a synonym for merge! but really the C method that they share is called rb_hash_update. So who is the synonym of who? I think the etymology of all the various alias methods in ruby core would be a fun subject. Was map or collect introduced first, etc, etc.

Create Thumbnail Image For A PDF

The rmagick gem is a wrapper around the ImageMagick software suite. This gem can be used to create a thumbnail image of a PDF using the following snippet of code.

require 'rmagick'
pdf = Magick::ImageList.new('document.pdf')
first_page = pdf.first
scaled_page = first_page.scale(300, 450)
scaled_page.write('document-thumbnail.jpg')

The scale can be adjust as necessary to the use case.

source

Ruby String Mutability

Until Ruby 3 we need to explicitly call the method freeze on literal strings, so they become immutable. And, if you have a lot of literal strings in a file, this will be very repetitive and verbose. In order to let our code cleaner there is a magic comment that can be added in the top of each file.

the magic:

# frozen_string_literal: true

And it is done, all literal string are frozen now :)

example:

class Unfrozen
  def foo
    'bar'
  end
end
class StringFrozen
  def foo
    'bar'.freeze
  end
end
# frozen_string_literal: true
class ClassFrozen
  def foo
    'bar'
  end
end

To test that:

require 'spec_helper'

describe 'Ruby String Mutability' do
  it 'validates string mutability' do
    expect(Unfrozen.new.foo.frozen?). to be false
    expect(StringFrozen.new.foo.frozen?). to be true
    expect(ClassFrozen.new.foo.frozen?). to be true
  end
end
Randomized with seed 51265
.

Finished in 0.00179 seconds (files took 0.45396 seconds to load)
1 example, 0 failures

\o/

Variable Hoisting in Ruby

This afternoon my pair and I spent quite a while on a subtle bug. The culprit? Variable hoisting.

Take this file:

class Test
  def self.hoist
    require 'pry'; binding.pry;
    bar = 1
  end
end

Test.hoist

When we hit the PRY debugger, what will the value of bar be? I would have thought it would raise NameError, because bar has seemingly not yet been defined.

Wrong:

$ ruby test.rb

From: /test.rb @ line 4 Test.hoist:

    2: def self.hoist
    3:   require 'pry'; binding.pry;
 => 4:   bar = 1
    5: end

[1] pry(Test)> bar
=> nil

When Ruby parses a file, it 'hoists' each variable to the top of its scope, declaring and setting it to nil, even if that variable is never assigned by our code. So variables inside an if false conditional get hoisted and set to nil, as described in this blog post.

This is can be a real gotcha.

h/t Jack Christensen

super_method

If a class has the same method defined somewhere in the inheritance chain, we can use super_method to access it.

module Foo
  def foo 
    'foo'
  end
end

class Bar
  include Foo

  def foo 
    'bar' 
  end
end

Bar.new.method(:foo).call
# => "bar"

Bar.new.method(:foo).super_method.call
# => "foo"

Colorize MiniTest Output

I use MiniTest all the time for my hobby Ruby projects. I like its simple syntax and easy setup.

The test output can be a little sparse. Today I learned that it's easy to colorize the output of MiniTest, just like the defaults in more heavyweight test frameworks.

Add this to your Gemfile:

gem 'minitest-rg'

Then require the package in any test:

# test/my_test.rb

require 'minitest/rg'

Now we get a nice red, green, yellow colorized output.

minitest-rg

A high level view of Rspec tests

Test files in ruby/rspec can grow to gigantic soul crushing sizes, which makes it hard to really get a sense of what tests are in the file and where. This is troublesome when trying to determine a sensible place to add a new test to the already gigantic file.

To get a better sense of the structure of the file you can combine the dry-run and format options for readable, hierarchical documentation in a small amount of time.

rspec -fdoc --dry-run specs/my_massive_test_file_spec.rb

Private Class Methods in Ruby

Every object oriented language has a different take on the rules of methods and objects and classes, and I cut my teeth on Java, which means that forever and ever after I'll assume everything works like Java. That left me writing code like the Apple class below that has a private class method, but not really. You can still call it.

class Apple
  def self.latin_name
    binomial_name
  end

  private
  def self.binomial_name
    "Malus domestica"
  end
end

puts Apple.latin_name
puts Apple.binomial_name  #no error, works fine

There's a way to make class methods private in Ruby, you just gotta jump through some hoops. Err, I mean use the class << self syntax. This oddity pushes an instance singleton onto the class effectively creating class methods.

class Orange
  def self.latin_name
    binomial_name
  end

  class << self
    private def binomial_name
      "Citrus × sinensis"
    end
  end
end

puts Orange.latin_name
puts Orange.binomial_name # ERROR!!! you can't call a private method.

H/T Mike Chau

Point the Gemfile.lock to a new branch version

One very flexible option for gluing your softwares together is to point a gem to a branch on Github in your Gemfile like so:

gem 'fancy_addition', github: 'chriserin/fancy_addition', branch: 'double_add'

But that reference is locked to a specific version of your branch in the Gemfile.lock

remote: git://github.com/chriserin/fancy_addition.git
revision: dca3f25fa294ee68b41b2c736064e5e200039b6d
branch: double_add

If you update that branch, the repository that depends on it will not automatically receive that update. To update the Gemfile.lock reference to the most recent version of that branch use the --source option of bundler like so:

bundle update --source double_add

If You Detect None

The Enumerable#detect method, which is synonymous with #find, can be given an optional argument, ifnone, that is called when nothing in the array meets the conditional in the block. Though I am not sure how this is practically useful and cannot find an example of it in use, this contrived example illustrates how it works.

# without the fallback behavior
> [2,4,6,8].detect { |x| x.odd? }
=> nil

# with a proc as an argument
> [2,4,6,8].detect(->{0}) { |x| x.odd? }
=> 0

The last example can also be written as:

> [2,4,6,8].detect(->{0}, &:odd?)
=> 0

And if you want to be really explicit:

> [2,4,6,8].detect(ifnone=->{0}, &:odd?)
=> 0

Split Strings with Trailing Nulls

Ruby's String .split accepts an optional number argument, and this lets us do some interesting things.

For instance, here is a naive full name splitter using such an argument:

> first_name, last_name = 'Benico del Toro'.split(' ', 2)
 => ["Benicio", "del Toro"]

It's naive because it doesn't work on names like 'Philip Seymour Hoffman', returning ["Philip", "Seymour Hoffman"].

Today I learned this argument can be negative. When it is, there is no limit to the number of fields returned, and trailing null fields are not suppressed:

> "Academy Award Winner....".split(".", 2)
 => ["Academy Award Winner", "..."]
> "Academy Award Winner....".split(".", -2)
 => ["Academy Award Winner", "", "", "", ""]

The actual value of the negative number seems to be irrelevant:

> "Academy Award Winner....".split(".", -1)
 => ["Academy Award Winner", "", "", "", ""]
> "Academy Award Winner....".split(".", -12)
 => ["Academy Award Winner", "", "", "", ""]

http://ruby-doc.org/core-2.3.0/String.html#method-i-split

Access Middleman template vars from a helper

Say you pass a local variable to a Middleman template via something like proxy:

proxy('/someplace/nice', 'nice.html', :locals => { :foo => 'boop' })

And you want to use :foo inside a helper without manually passing the variable as an argument. Turns out local variables are accessible in all helpers via current_page.metadata[:locals]:

helpers do
  def helpyhelp
    foo = current_page.metadata[:locals][:foo]
  end
end

Ruby Regex Supports Interpolation

Today we built a Ruby regex that included an interpolated string. It looked like this:

# app/models/developer.rb
validates :email, format: { with: /\A.+@(#{ENV['permitted_domains']})\z/ }

This allows permitted_domains to be customized as an environmental variable:

# config/application.yml
permitted_domains: 'hashrocket.com|hshrckt.com'

The parens and pipe allow us to white-list multiple domains in a single environmental variable.

Defaulting To Frozen String Literals

The cold never bothered me anyway.

The release of Ruby 2.2 introduced the ability to freeze string literals, making them immutable. With the release of Ruby 2.3, strings can be frozen by default without the use of #freeze. By adding the following magic comment at the top of a file

# frozen_string_literal: true

all string literals will default to frozen. That means that all string literals in that file are immutable, cannot be modified. This gives the Ruby interpreter some performance gains due to reduced object allocation.

This is the issue that introduced it.

Returning With Sequel

The sequel gem is a database toolkit that allows you to interact with most databases. PostgreSQL has support for composite primary keys, but sequel, which is supposed to return the id of newly inserted records, isn't sure what to return when faced with a composite primary key. You can get around this by telling sequel exactly what should be returned using the #returning method. For instance, get it to return just the id of the new record:

DB[:floors].returning(:id).insert(hotel_id: 4, id: 1, ...)
# [{id: 1}]

To get it to return both parts of composite key:

DB[:floors].returning(:id, :hotel_id).insert(hotel_id: 4, id: 1, ...)
# [{id: 1, hotel_id: 4}]

Read Commented Notes

Want to resolve all those # TODO, # FIXME, and # OPTIMIZE comments in your Rails app? Good call, we don't want these getting too comfortable.

To demonstrate, push a note into a new file app/models/foo.rb:

$ echo '# TODO DRY this up!' >> app/models/foo.rb

Then run rake notes:

$ rake notes
app/models/foo.rb:
  * [1] [TODO] DRY this up!

rake -T | grep notes shows our options, including flags to filter results. We also get rake notes:custom, to find a custom note tag:

$ echo '# HACK woah.' >> app/models/foo.rb
$ rake notes:custom ANNOTATION=HACK
app/models/foo.rb:
  * [2] woah.

Block Comments

Ruby supports (ugly) block comments. They look like this:

=begin
This is a block comment.

I can put whatever I want in here.
=end
def do_something
  ...
end

source

Rendering ERB

If you have a string that contains ERB templating, you can quickly generate the resulting string with the following code snippet:

require 'erb'

some_template_string = <<-TEXT
The top
<% 5.times do |i| %>
Item <%= i + 1 %>
<% end %>
The bottom
TEXT

puts ERB.new(some_template_string).result

This will print the following to stdout:

The top
Item 1
Item 2
Item 3
Item 4
Item 5
The bottom

source

Ruby optional arguments can come before required

I'm used to seeing optional arguments after required ones, as so:

require 'date'

def age(date, today=Date.today)
  (today - date) / 365.25 # good enough
end

birthdate = Date.parse("2011-06-15")

# How old am I today?
age(birthdate) #=> 4.583

# How old was I on the first?
age(birthdate, Date.parse("2016-01-01")) #=> 4.547

The second argument is optional.

However, you can also make the first argument optional:

def age(today=Date.today, date)
  (today - date) / 365.25 # good enough
end

birthdate = Date.parse("2011-06-15")

# How old am I today?
age(birthdate) #=> 4.583

# How old was I on the first?
age(Date.parse("2016-01-01"), birthdate) #=> 4.547

I don't recommend doing this. It's confusing.

Identify Outdated Gems

Bundler can be used to identify outdated gems for a given project. By running bundle outdated in a project's directory, Bundler will compare the versions of all stated gem dependencies against the gem server and report a list of those gems that are not up to date.

See the Bundler docs for more details.

Refinements

In Ruby 2.1 and later, you can require monkey patching to be explicitly active inside of a class/module by defining your method inside of a refine block. You can activate the changes with the using keyword.


module Confusion
  refine String do
    def length
      "Yes"
    end
  end
end

module BadString
  using Confusion
  def self.count(string)
    string.length
  end
end

module GoodString
  def self.count(string)
    string.length
  end
end

BadString.count("four") # => "Yes"
GoodString.count("four") # => 4

Find a Random Open Port

Let's say you need an open port, and you don't actually care what number it is as long as it's open:

server = TCPServer.new('127.0.0.1', 0) #0 is special, it finds any open port
port = server.addr[1]   # get the port
server.close   #close the server, now we have an open port number

h/t @joshuadavey

Succeed, Precede, and Surround in Haml

Haml's design makes HTML and Ruby tricky to mix inline. But we have Haml helper methods to make it easier.

Here is succeed in action:

Developer at
  = succeed ', ' do
    = link_to "Hashrocket", "https://hashrocket.com/"

This becomes:

Developer at
<a href="https://hashrocket.com/">Hashrocket</a>,

Notice the comma at the end, outside of the a tag?

precede and surround work in a similar fashion, and do what we'd expect.

http://haml.info/docs/yardoc/file.REFERENCE.html#succeed

Pass A Block To Count

Ruby's Enumerable module comes with the method #count for determining how many items are in an array or hash.

> [1,2,3].count
=> 3
> {a: 1, b: 2}.count
=> 2

The #count method has a trick up its sleeve though. It can take a block with a predicate that returns true or false. It essentially acts like #select returning the count rather than the array subset itself.

> [1,2,3].count { |x| x.odd? }
=> 2
> {a: 1, b: 2}.count { |(x,y)| y < 0 }
=> 0

Safe Navigation Operator

With the release of Ruby 2.3, the safe navigation operator (&.) is now available. This addition to the Ruby language allows you to collapse all those pesky nil checks into the accessor call they are guarding. Consider this snippet of common Ruby code:

if user && user.authenticate(params[:password])
  # proceed with logged in user
end

With the safe navigation operator, the predicate can now be collapsed:

if user&.authenticate(params[:password])
  # proceed with logged in user
end

If user is nil, then the predicate will evaluate to false and the body of the if-statement will be passed over.

Source

Comparing Arrays In RSpec

Among its many built-in matchers, RSpec includes a set of array matchers. One of the array matchers is match_array which compares two arrays independent of ordering. This is handy if you need to check that a resulting array matches your expectations when ordering is unimportant and not necessarily deterministic. It can be used like so:

expect([1,2,3]).to match_array([3,2,1])

This expectation is met, the test will pass.

How Sinatra avoids polluting inheritance chain

When you open a new file:

[13] pry(main)> self
=> main
[14] pry(main)> self.class
=> Object

main is an instance of Object

An example: the Sinatra DSL

require 'sinatra'

get '/' do
  'Hello world!'
end

#get is put in main's singleton class

[1] pry(main)> require 'sinatra'
=> true
[2] pry(main)> method(:get).source_location
=> .../sinatra-1.4.6/lib/sinatra/base.rb", 1987]
pry(main)> Object.new.get
NoMethodError: undefined method `get' for #<Object:0x007fc423d9ec18>

This is achieved by extending the singleton class of main.

from Sinatra:

extend Sinatra::Delegator

A simple example:

class Foo
  module DSL
    def foo
      'bar'
    end
  end
end

extend ::Foo::DSL

Ruby's Kernel::abort

Today I used Ruby's Kernel::abort for the first time. It's one of those incredibly useful methods I can't believe I've never seen before.

Observe:

# abort.rb                                                                                                                                                    {1}
def no_message
  abort
end

def message
  abort('Process terminated')
end
$ irb
2.2.2 :001 > require './abort'
 => true
2.2.2 :002 > no_message
$ irb                                 {1}
2.2.2 :001 > require './abort'
 => true
2.2.2 :002 > message
Process terminated
$

Use it to bail from a script.

http://ruby-doc.org/core-2.1.2/Kernel.html#method-i-abort

Accessor Performance Gap

This week I learned that attr_reader is more performant than a simple getter method.

Here’s a gist from five years ago where Aaron Patterson explains:

https://gist.github.com/pjb3/629716

I ran that same benchmarking script today on Ruby 2.2.3. The gap has narrowed, but still exists:

ruby-2.2.3
Rehearsal -----------------------------------------------
method        0.070000   0.000000   0.070000 (  0.074840)
attr_reader   0.050000   0.000000   0.050000 (  0.052603)
-------------------------------------- total: 0.120000sec

                  user     system      total        real
method        0.070000   0.000000   0.070000 (  0.072229)
attr_reader   0.050000   0.000000   0.050000 (  0.053374)

I like attr_reader because it’s a Ruby convention and is one line instead of three. Now, I also like its performance relative to a getter.

h/t Josh Davey

Accessors For All

Today I learned that accessors like attr_reader work in the private and protected visibilities.

class Test
  def initialize(getter, reader)
    @getter = getter
    @reader = reader
  end

  private

  def getter
    @getter
  end

  attr_reader :reader
end
2.2.3 :001 > t = Test.new('foo', 'bar')
 => #<Test:0x007f8f9b259bf8 @getter="foo", @reader="bar">
2.2.3 :002 > t.send(:getter)
 => "foo"
2.2.3 :003 > t.send(:reader)
 => "bar"

This can produce warnings in tests, discussed here:

https://bugs.ruby-lang.org/issues/10967

My current feeling is that these methods are a Ruby convention and should be used whenever appropriate, despite warnings in test.

Install a gem for all rubies in your system (RVM)

If you want a certain gem to be available in all your rubies (particularly common with gems which expose a CLI) use this command to install it for all ruby versions installed with RVM.

for x in $(rvm list strings); do rvm use $x@global && gem install hitch; done

(Replace hitch with your desired gem)

Ruby objects from YAML

For certain objects if the ISO8601 standard is followed, Ruby will create an instance instead of a string when parsing the value.

A date can be represented by its year, month and day in ISO8601 order.

For example:

post.txt

title: Updated
date: 2011-09-25
pry(main)> p = YAML.load(File.new('post.txt'))
=> {"title"=>"Updated", "date"=>#<Date: 2011-09-25 ((2455830j,0s,0n),+0s,2299161j)>}
pry(main)> p['date'].class
=> Date

http://yaml.org/YAML_for_ruby.html#date

Proc.new inside a method

Typically, you see blocks passed with yield:

def foo
  yield
end
foo { 1 + 1 }
=> 2

or with the explicit to proc (&block ) at the end of your method arguments:

def foo(&block)
  block.call
end
foo { 1 + 1 }
=> 2

Proc.new can be called without a block within a method and it will capture an attached block

def foo
  Proc.new.call
end

foo { 1 + 1 }
=> 2

Colorful Output With MiniTest

Ruby's MiniTest is a minimal testing framework that you can easily drop-in to any Ruby project. For those used to using RSpec with it's fancy red/green output, MiniTest can be a little disappointing. It prints boring, uncolored text to the screen that lacks visual feedback. Fortunately, red and green coloring can be added with minitest/reporters.

Update your Gemfile:

gem 'minitest-reporters'

Then require and configure minitest-reporters in your testing setup file (e.g. test/test_helper.rb):

require 'minitest/reporters'
Minitest::Reporters.use! [Minitest::Reporters::DefaultReporter.new(:color => true)]

You can now enjoy that Red, Green, Refactor cycle.

Uncover monkey patched methods

Due to Ruby's open classes, anyone can monkey patch any thing at any time, which could lead to confusion if you aren't aware of the patched methods. You can check a method to see if it's been monkey patched in irb/pry/byebug without exiting and grepping the source code.

class Array
  def length
    "MONKEY PATCHED!"
  end
end
arr = []
suspect_method  = arr.method :length
method = arr.method :size

Here we create some references to the length and size methods on Array. When you call source_location on one of these, if the method is defined in native Ruby, it will return nil, if it has been monkey patched, it will return the file name and line number where it was defined.

suspect_method.source_location
# ['some_file.rb', 2]

method.source_location
#nil

Fetch your Environmental Variables

It's important to fetch Ruby environmental variables rather than directly referencing them.

This code depends on 'secret_key':

key = ENV['secret_key']

When 'secret_key' is not set, 'key' will be assigned nil, which is an object.

Later, a call to key.upcase will produce a NoMethodError, because Ruby doesn't know how to uppercase nil.

This is better:

key = ENV.fetch('secret_key')

Now, when 'secret_key' is not set, KeyError will be raised. The code fails fast.

fetch takes a second argument as a default, which means you can even prevent KeyError from ever happening, if you choose:

key = ENV.fetch('secret_key', 'some_default_numbers')

http://ruby-doc.org/core-2.2.3/ENV.html#method-c-fetch

Construct A Constant From A String

Ruby's Module.const_get can be used to look for and retrieve the constant for a given name.

This can be used to construct a class name

> Object.const_get("Math")
#=> Math
> Object.const_get("Math")::PI
#=> 3.141592653589793

It can also be used to reference a constant

> Object.const_get("Math::PI")
#=> 3.141592653589793

You can even be more specific if you'd like

> Math.const_get("PI")
#=> 3.141592653589793

Symbols are valid as well

> Math.const_get(:PI)
#=> 3.141592653589793

Redefine #respond_to_missing with #method_missing

Initial attempt:

class User
  def method_missing(name, *args, &block)
    if "#{name}" =~ /foo/
      'exists'
    else
      super
    end
  end
end
> u = User.new
=> #<User:0x007fdf3b152c60>
> u.foo
=> exists
> u.method(:foo)
=> NameError: undefined method `foo' for class `User'
User.class_eval do
  def respond_to_missing?(name, include_private = false)
    "#{name}" =~ /foo/ || super
  end
end
> u = User.new
=> #<User:0x007ffcda847f90>
> u.method(:foo)
=> #<Method: User#foo>

Replace The Current Process With An External Cmd

Ruby's Kernel#exec method can be used to run an external command. What differentiates it from executing commands with the likes of back ticks or %x[] is that instead of forking a child process, it replaces the current process.

For instance, the following ruby script, when executed, will replace itself with an irb session.

Kernel.exec('irb')

The external command will even benefit from the existing environment. For example, if I set the following environment variable

$ export GREETING=hello

and then execute a file containing

Kernel.exec('echo $GREETING')

I can expect to see hello printed to stdout.

ruby operators <, >, === etc.

ruby -v 2.2.2

Different implementations of some of these operators can be used to do some cool things.

The #< implementation on Module for example.

> Module < BasicObject
=> true

> Object < Class
=> false

#== and #=== are implemented the same on Fixnum or BigDecimal, but on Module

> a === b

evaluates to true if b is an instance of a or a's descendants

> (1..10) === 5
=> true

> 5 === (1..10)
=> false

> 'str' === String
=> false

> String === 'str'
=> true

This is the case-equality operator and this behavior can be overridden to customize case statements. An example of overriding.

class Range
  def ===(o)
    puts 'nope sucka'
  end
end

case 5
when(1..10)
'This would normally work'
else
end
=> nope sucka

Ruby Regex Literal

Ruby has a nice percent string literal for regular expressions, %r. It's like // but allows your regex to contain backslashes without escaping them.

Check it out:

2.1.0 :001 > 'http://google.com'.gsub(/http:\/\/google.com/, 'fine')
 => "fine"
2.1.0 :002 > 'http://google.com'.gsub(%r{http://google.com}, 'better')
 => "better"

As the example implies, this is useful when matching URLs.

Documentation

Testing a multipart request with RSpec

Use Rack::Test::UploadedFile to issue a multipart request. You will have to include it if it's not in your stack.

post "/api/v1/logs/create",  log: { name: Foo, "file" => Rack::Test::UploadedFile.new("me.jpg", "image/jpeg") }

Invoking Rake Tasks Multiple Times

I have a rake task, build, that builds a single record for development purposes. I want a supplemental rake task, build:all, that builds a bunch of different records. To keep things dry, build:all should just invoke build a number of times.

namespace :build do
  task :all do
    predefined_list.each do |data|
      Rake::Task["build"].invoke(data)
    end
  end
end

This doesn't work though. No matter how many items are in the list, the build task only seems to get run once. This is because by default tasks can only be invoked once in a given context. To get around this, the task needs to be reenabled after each invocation.

namespace :build do
  task :all do
    predefined_list.each do |data|
      Rake::Task["build"].invoke(data)
      Rake::Task["build"].reenable
    end
  end
end

URI::regexp

You can generate a regular expression that matches URIs using URI from Ruby's stdlib:

require 'uri'

matcher = URI.regexp(["http"])
md = matcher.match("I like http://google.com, for real")
#=> #<MatchData "http://google.com" 1:"http" 2:nil 3:nil 4:"google.com" 5:nil 6:nil 7:nil 8:nil 9:nil>
md[0]
#=> "http://google.com"

You can use this with String#scan to extract all URIs from a string:

urls= []
"I like http://google.com, for real. Also, http://localhost:3000 is useful.".scan(matcher) { urls << Regexp.last_match[0] }
urls
#=> ["http://google.com", "http://localhost:3000"]

See http://ruby-doc.org/stdlib-2.2.2/libdoc/uri/rdoc/URI.html#method-c-regexp for more information.

Ruby's __END__

I recently used Ruby's __END__ keyword in a client project.

__END__ denotes the end of regular source code in a Ruby file; nothing below it will be executed.

It's essentially a one-line block-commenting device, which is how we used it when trying to recreate a successful pattern borrowed from somewhere else in the project. Instead of toggling between files, we copied beneath __END__ the code we wanted to emulate, started building the new method, and cleaned up before committing.

One benefit of this technique is that any code below __END__ is available via the special filehandle DATA:

# foo.rb
puts DATA.map(&:upcase)

__END__
'foo'
'bar'
'baz'
$ ruby foo.rb
'FOO'
'BAR'
'BAZ'

Documentation

Last Raised Exception In The Call Stack

In Ruby, the $! global variable contains the last exception that was raised in the current call stack. This makes it trivial to check what error is being rescued even if it hasn't been captured in a local variable.

class MyError < StandardError; end

def do_stuff
  raise MyError
rescue
  puts "rescuing #{$!}"
end

do_stuff
#=> rescuing MyError

to_partial_path

Passing an active record instance to the render will look for a partial of the active record's name. This is because the active record implements to_partial_path.

This can be mimic'd by a non-active record object like so.

class Fruit
  def to_partial_path
    "fruit"
  end
end

Passing Fruit.new to render like so:

render Fruit.new

Will look for a partial name _fruit.html.erb

I need to iterate with an index! With index!

You need an index while iterating over your collection, right?

> a = ['apple', 'orange', 'banana'];
> a.map.with_index {|fruit, index| puts index}
0
1
2

with_index is a method on Enumerator, and map returns an Enumerator.

Array method

Ruby's Array(arg) method, from the Kernel class, is awesome. I like it because to me it's really clear what it does (type casting), and it tries both to_ary and to_a.

Also, it just looks cool.

2.1.0 :001 > Array(%w(some cool words))
 => ["some", "cool", "words"]
2.1.0 :002 > Array("word")
 => ["word"]
2.1.0 :003 > Array(nil)
 => []
2.1.0 :004 > Array(1..5)
 => [1, 2, 3, 4, 5]

Ruby usec

Two Time objects are almost never equal:

2.2.2 :001 > t = Time.now; t2 = Time.now
 => 2015-08-11 19:22:39 -0500
2.2.2 :002 > t == t2
 => false

This is true despite the fact that they were created in the same second of time, which we can verify by casting them to integers.

2.2.2 :003 > t.to_i
 => 1439338959
2.2.2 :004 > t2.to_i
 => 1439338959

The difference between these two times is in microseconds, which aren't displayed by default. Cast them as floats to see the difference.

2.2.2 :005 > t.to_f
 => 1439338959.099774
2.2.2 :006 > t2.to_f
 => 1439338959.099776

Another path to this information is Ruby's usec method, which returns just the microseconds.

2.2.2 :007 > t.usec
 => 99774
2.2.2 :008 > t2.usec
 => 99776

Documentation

Rake Only Lists Tasks With Descriptions

Rake describes the -T flag as

Display the tasks (matching optional PATTERN) with descriptions, then exit.

And rake -T does just exactly that. It lists all the tasks with descriptions. Any rake task that you define without a desc will not be included.

Consider the following rake task definitions

desc 'foobar does this and that'
task :foobar do
  puts 'this and that'
end

task :foobaz do
  puts 'not so much'
end

This is what I get when listing the rake tasks filtered by foo

$ rake -T foo
rake foobar  # foobar does this and that

The foobar task (which has a description) is listed, but foobaz is not.

A hack of sorts to get around this is to use the -P flag which will end up listing all tasks even if they do not have a description (rake -P | grep 'foo').

Passing Arguments To A Rake Task

You can create a rake task that takes arguments by including an array of named arguments in the task declaration.

task :greeting, [:name] do |task, args|
  puts "Hello, #{args.name}!"
end

You can then pass an argument to that task when invoking it.

$ rake greeting[World]
Hello, World!

source

`undef_method` And The Inheritance Hierarchy

As the docs state, Ruby's undef_method

prevents the current class from responding to calls to the named method.

This means you can do some weird things to the inheritance hierarchy. I'll use the following code example to illustrate.

class Phone
  def ring
    puts 'brrrrriiing'
  end
end

class Smartphone < Phone
  def ring
    puts 'boop beep boop'
  end
end

class Iphone < Smartphone
end

smartphone = Smartphone.new
iphone = Iphone.new

smartphone.ring
#=> boop beep boop
iphone.ring
#=> boop beep boop

Everything works as expect. Now, I'll use undef_method.

class Smartphone
  undef_method(:ring)
end

smartphone.ring
#=> NoMethodError: undefined method `ring' for #<Smartphone:0x007fd0a20b7960>
iphone.ring
#=> NoMethodError: undefined method `ring' for #<Iphone:0x007fd0a20b7938>

Not only have instances of Smartphone been prevented from responding to ring, but any subclasses of Smartphone that call ring will get tripped up when traversing the inheritance hierarchy in search of a definition of ring.

Passing Arbitrary Methods As Blocks

Use Object#method to create a callable Method object that can be passed to methods that yield to a block.

def inc(x)
  x + 1
end

[1,2,3].map(&method(:inc))
#=> [2,3,4]

Listing Local Variables

In Ruby 2.2, the binding object gives us access to a method #local_variables which returns the symbol names of the binding's local variables. We can see this in action with

def square(x)
  puts binding.local_variables.inspect
  x.times do |a|
    puts binding.local_variables.inspect
  end
  z = x * x
  puts binding.local_variables.inspect
  z
end
square(2)

which results in

[:x, :z]
[:a, :x, :z]
[:a, :x, :z]
[:x, :z]
=> 4

source

`each_cons` in ruby to get differences

I want to get the difference between consecutive elements in an array. Ruby has a method each_cons that provides a block with consecutive numbers of an enumerator.

[1, 3, 7].each_cons(2).map {|a, b| b - a }
=> [2, 4]

Ruby Partition Methods

One cool way to chop through a Ruby string is the partition String method. This uses regex to search for a match in a string. If it finds one, it returns what came before the match, the match, and what came after as elements in an array.

2.2.2 :001 > 'foo bar baz bat'.partition 'bar'
 => ["foo ", "bar", " baz bat"]

This is not to be confused with the partition Array method, which takes a block. Any elements that evaluate true are returned first, followed by the elements that evaluate false.

2.2.2 :002 > [1,2,3,4,5].partition(&:even?)
 => [[2, 4], [1, 3, 5]]

Question Mark Operator

Ruby has a question mark (?) operator that works like so

> ?a
=> "a"
> ?\s
=> " "
> ??
=> "?"
> ?a + ?b + ?c
=> "abc"

It essentially creates single character strings. At least in Ruby 1.9+ it does. In versions of Ruby before 1.9, the ? operator could be used to get the ascii character code of the operand character.

h/t Josh Davey

source

Ruby Redo

Ruby has a keyword redo that you might see inside a block. It causes the unconditional re-execution of the block, with the same parameter bindings as the current execution.

Here it is, causing an endless loop:

n = 0
until n == 1 do
  puts n
  n += 1
  redo
end

redo does not evaluate the 'until' condition, so the likelihood of it causing an endless loop is high.

I'd love to see a practical application. It seems to me that redo would have to be inside a conditional, based on some information coming from outside the loop-- information we are certain will eventually be false.

That's a lot to ask; I would avoid redo in most cases.

Percent Notation

Ruby has many uses for the % character. One of the more obscure uses is as a notion for custom delimited strings. Use the percent notation with a non-alphanumeric character to surround a string.

> %=Jurassic Park=
=> "Jurassic Park"
> % Ghostbusters 
=> "Ghostbusters"

It even works with balanced characters

> %(The Goonies)
=> "The Goonies"

This is useful for defining a string that has both types of quotes

> %[That'll be the "day"]
=> "That'll be the \"day\""

It's also useful for creating horribly obfuscated code

> %=what===%?what?
=> true

h/t Josh Davey

Ruby Array Set Intersection

Ruby's Array class has a method & which returns a new array containing elements common to two arrays, excluding duplicates.

I used this on a project today to compare a random number (17) to a set of numbers with special meaning to the program.

2.2.2 :001 > (5..32).step(3).to_a & [17]
 => [17]
2.2.2 :002 > ((5..32).step(3).to_a & [17]).size > 0
 => true

The order is preserved from the original array:

2.2.2 :003 > [2,3,1] & [1,2,3]
 => [2, 3, 1]

h/t Chris Erin

Ruby Threequals

Ruby's == is pretty straightforward. From the Object class documentation:

Equality — At the Object level, == returns true only if obj and other are the same object. Typically, this method is overridden in descendant classes to provide class-specific meaning.

Some examples from the String class:

irb > 'foo' == 'foo'
 => true
irb > 'foo' == :foo
 => false
irb > 'foo' == 'bar'
 => false

The triple equals, ===, sometimes called a ‘threequals’ or ‘case equality operator’, is different (again from the Object docs):

Case Equality – For class Object, effectively the same as calling #==, but typically overridden by descendants to provide meaningful semantics in case statements.

The threequals compares the type of two arguments. One way to think about a === b is: 'does b belong in a box a’?

A few examples:

irb > String === 'foo'
 => true
irb > Array === %w(one two three)
 => true
irb > Range === (1..10)
 => true
irb > /car/ === 'carpool'
 => true

All of these evaluate false when the == operator is used.

Ruby's case statement operator uses the threequals for its control flow.

h/t Chris Erin

http://ruby-doc.org/docs/keywords/1.9/Object.html#method-i-case http://stackoverflow.com/questions/7156955/whats-the-difference-between-equal-eql-and

Bundle Open

Looking to source dive? This command opens the source directory for the provided gem.

bundle open GEM

Do something when a cucumber scenario fails

When your cukes fail, you might want to take a screenshot, or automatically open a pry. This can help when debugging flaky tests.

After do |scenario|
  if scenario.failed?
    # take a screen shot, or open a pry
  end
end

Casting Created At

Four posts have been created for ’Today I Learned’ since yesterday. This code looks like it would return that count, but it doesn’t.

Post.where('created_at between ? and ?', Date.yesterday, Date.today).count              
   (0.8ms)  SELECT COUNT(*) FROM "posts" WHERE (created_at between '2015-06-09' and '2015-06-10)
=> 2

It returns 2; the two posts from yesterday but not the posts from today.

This is because Date.today is a Ruby Date object, which represents midnight on the given date, while created_at is a Rails ActiveSupport::TimeWithZone object, which includes time and zone details. Using Date.today as a comparator actually excludes any posts created after midnight today.

One solution is to cast created_at to a date:

Post.where('cast(created_at as date) between ? and ?', Date.yesterday, Date.today).count
   (1.1ms)  SELECT COUNT(*) FROM "posts" WHERE (cast(created_at as date) between '2015-06-09' and '2015-06-10')
=> 4

In the scope of this query, created_at loses its time information, so a post created today will return true when compared to Date.today. This is the Rails equivalent:

Post.last.created_at.to_date == Date.today
=> true

More Info

Override The Initial Sequence Value

FactoryGirl sequences can be defined with an initial starting value

FactoryGirl.define do
  sequence :email, 1000 do |n|
    "person#{n}@example.com"
  end
end

thus:

> FactoryGirl.generate :email
=> "person1000@example.com"
> FactoryGirl.generate :email
=> "person1001@example.com"

Invert a Hash

Ruby's Hash includes the method invert, which takes a hash and returns it with the keys and values reversed.

2.2.2 :001 > {blackhawks: 'chicago'}.invert 
 => {"chicago"=>:blackhawks}

FactoryGirl Sequences

FactoryGirl sequences are often used inline for unique values such as emails:

factory :user do
  sequence(:email) { |n| "person#{n}@example.com" }
end

However, a sequence can be defined on its own

FactoryGirl.define do
  sequence :email do |n|
    "person#{n}@example.com"
  end
end

That means it can be invoked outside the context of a factory

> FactoryGirl.generate :email
=> "person1@example.com"
> FactoryGirl.generate :email
=> "person2@example.com"

Or it can be used as a shared sequence across multiple factories

factory :customer do
  ...
  email
end

factory :admin do
  ...
  email
end

Comparing Class Hierarchy Relationships

The comparator methods (<,>, etc.) can be useful for a lot of things. In Ruby, they can be used to compare classes in order to understand how they relate to one another on the class hierarchy.

# Fixnum is a subclass of Integer
> Fixnum < Integer
=> true
# Integer is not a subclass of Fixnum
> Integer < Fixnum
=> false
# Fixnum and String are not related to one another
> Fixnum < String
=> nil

The < operator will tell you if there is a subclass relationship. The > operator will tell you if there is an ancestor relationship. When nil results, it means the two classes do not have a direct relationship.

There are a few more of these types of operators on the Module class.

source

Run Code if Current File is Calling File

This conditional tells Ruby to execute the code within if the current file is the file running the code.

# exec.rb
if __FILE__ == $0
  puts 'shown when exec.rb is run directly; not when required'
end

This works by comparing the current file (__FILE__) with the file that started the program ($0). If they aren't the same (exec.rb), the statement will not be printed.

You don't need those traces!

Josh looked at disassembling ruby recently.

It outputs code like:

0000 trace            1                                               (   1)
0002 putobject_OP_INT2FIX_O_1_C_
0003 dup
0004 setlocal_OP__WC__0 2
0006 leave

The first instruction trace tells ruby to emit a trace event (trace system detailed here).

The trace instructions may not be useful when examining disassembled code and as such you can compile the code without the trace instructions.

RubyVM::InstructionSequence.compile_option = {
  trace_instruction: false
}

Multiline strings in YAML

If you're using Middleman data files (which are awesome), you might run into an issue where you want to store text intended for Markdown processing within a .yaml file. To do so, just use |:

widget:
  content: |
    # This is some markdown content in YAML that will be output as an <h1>.

    This will be output as a paragraph tag.

    So will this!

Technically you can use > instead of |, but > does not output linebreaks when the YAML is parsed, which can create issues when the text is processed through Markdown.

Puts Multiple Lines

Ruby's puts can take multiple arguments!

2.2.0 :002 > puts 'so', 'many', 'statements', 'to', 'puts'
so
many
statements
to
puts
 => nil

Disassemble Some Codes

The RubyVM::InstructionSequence class makes it easy to compile, disassemble, and inspect bits of Ruby code. We can quickly take a peek under the hood at a simple ruby statement, such as a = 1 + 2, like so:

> ruby_code = 'a = 1 + 2'
=> a = 1 + 2
> compiled_code = RubyVM::InstructionSequence.compile(ruby_code)
=> <RubyVM::InstructionSequence:<compiled>@<compiled>>
> puts compiled_code.disasm
== disasm: <RubyVM::InstructionSequence:<compiled>@<compiled>>==========
local table (size: 2, argc: 0 [opts: 0, rest: -1, post: 0, block: -1, kw: -1@-1, kwrest: -1])
[ 2] a
0000 trace            1                                               (   1)
0002 putobject_OP_INT2FIX_O_1_C_
0003 putobject        2
0005 opt_plus         <callinfo!mid:+, argc:1, ARGS_SIMPLE>
0007 dup
0008 setlocal_OP__WC__0 2
0010 leave
=> nil

It is a bit archaic, but when we get to the line starting with 0002, we see values (1 and then 2) pushed onto the stack, then operated on, and finally set on the local variable a. Fun!

Truthy Strings

Ruby strings are truthy, and they evaluate to zero, unless they start with a number.

> 'nine to five'.to_i
 => 0
> '9 to 5'.to_i
 => 9

Implementing an enumerator is easy

All you need to implement an enumerator is the each method.

class ChicagoDevs
  include Enumerable

  def each &block
    ['ce','jb', 'jc', 'jd', 'jw', 'bd', 'dp'].each{|member| block.call(member)}
  end
end

h/t Brian Dunn

Evaluating One-Off Commands

When I need to quickly test something out in Ruby, I will often reach for irb. However, there is an even quicker way to send a line of code to ruby for evaluation. Use the ruby binary with the -e flag followed by your line of ruby. For instance,

$ ruby -e 'puts Class.ancestors'
[Class, Module, Object, Kernel, BasicObject]

Squeeze out the extra space

Remove all the excess spaces from a string using the squeeze method:

> "this  is   a string".squeeze(' ')
=> "this is a string"

RVM binaries storage

RVM binaries are stored at:

https://rvm.io/binaries

They have binaries for 9 operating systems, the versions of each operating system, and the system architecture that each version supports.

Ruby timeout

Included in the ruby std lib is a timeout lib. It provides the capacity to auto-terminate a potentially long running operation.

http://ruby-doc.org/stdlib-2.2.1/libdoc/timeout/rdoc/Timeout.html

require 'timeout'
status = Timeout::timeout(5) {
  # Something that should be interrupted if it takes more than 5 seconds...
}

Convert interger to time

Time.at(Time.now.to_i)