Pivotal Labs

Main menu

Skip to primary content
Skip to secondary content
  • About
  • Case Studies
  • Team
    • Executives
    • Locations
      • San Francisco (HQ)
      • Boston
      • Boulder
      • Denver
      • London
      • Los Angeles
      • New York
  • Community
    • Blogs
    • Tech Talks
    • Events
  • Careers
    • Lifestyle
    • Principles & Practices
    • Benefits
    • FAQ
    • Apply
  • Contact
    • Press Room
    • Press Releases
    • In The News
    • Press Kit
  • All
  • Labs
  • Standup
  • Tracker
Abhijit Hiremagalur

Hash#fetch with confidence

Abhijit Hiremagalur
Sunday, May 5, 2013

Hash#fetch is stricter about key presence than Hash#[]

 {}[:foo]
 => nil

 {}.fetch(:foo)
 KeyError: key not found: :foo

If you forget to set an ENV variable, would you rather your application fail late or immediately?

 ENV['TWITTER_OAUTH_TOKEN']
 => nil

 ENV.fetch('TWITTER_OAUTH_TOKEN')
 KeyError: key not found

It’s especially interesting when a key with a truthy default is explicitly set to a falsy value.

options = {on: false}

@on = options[:on] || true 
=> true # yikes, ever fallen into this trap?

@on = options.fetch(:on, true) 
=> false
  • 0 Shares
  • Share on Facebook
  • Share on Twitter
Robbie Clutton

Failed attempt at trying to use refinements

Robbie Clutton
Monday, April 8, 2013

I was pretty interested in refinements in Ruby 2.0, and after listening to the latest Ruby Rouges podcast where some serious doubts were raised about the viability of refinements I thought I’d build a little example of how I was thinking I could use it.

I failed first time out and I tried copying and pasting examples without success. After some time poking around I found a blog post about why this wasn’t working. Ultimately, refinements are sort of left in the language, but not fully supported and are marked as experimental.

Here’s what I wanted to achieve. Coming from Scala in my previous job, I thought I could use refinements as a proxy for implicit conversions. Here I refine the Fixnum class to allow it to respond to a to_currency message. When called it converts the Fixnum instance to a Currency instance.

class Currency
  attr_reader :units

  def initialize units
    @units = units
  end
end

module CurrencyExtensions
  refine Fixnum do
    def to_currency
      Currency.new(self)
    end
  end
end

class App
  using CurrencyExtensions

  def initialize
    puts 3.to_currency
  end
end

App.new

Why is this interesting to me? Well, I think being able to write 3.to_currency can result in nicer to read code than the alternative Currency.new(3). Small difference perhaps.

There is a way to get this to work by having the using keyword in the global context, but it doesn’t deliver the full impact I was hoping for.

class Currency
  attr_reader :units

  def initialize units
    @units = units
  end
end

module CurrencyExtensions
  refine Fixnum do
    def to_currency
      Currency.new(self)
    end
  end
end

using CurrencyExtensions
puts 3.to_currency

I’ve got other ideas to build upon this if it ever makes it into the full specification. I’ll keep watching for now.

  • 0 Shares
  • Share on Facebook
  • Share on Twitter
Robbie Clutton

NY Standup: Documentation interpolation and RVM, Brew and autolibs FTW

Robbie Clutton
Tuesday, April 2, 2013

Interestings

Grant Hutchins / David Lee

If you wrap the opening name of a Ruby heredoc in single quotes, its insides will act like a single-quoted string.

If you wrap the opening name in backticks, the heredoc will be immediately executed through system()

<<-HEREDOC
1 + 2 = #{1 + 2}
HEREDOC
=> "1 + 2 = 3\n"

<<-'HEREDOC'
1 + 2 = #{1 + 2}
HEREDOC

=> "1 + 2 = #{1 + 2}\n"

<<-HEREDOC
uname
date
HEREDOC

=> "Darwin\nMon Apr 1 17:50:43 EDT 2013\n"

Found at http://jeff.dallien.net/posts/optional-behavior-for-ruby-heredocs

rvm autolibs

https://rvm.io/rvm/autolibs/

In the latest versions of RVM, you can have RVM build dependencies automatically for you. For instance, if you use Homebrew, you can run

$ rvm autolibs brew

and from then on, RVM will automatically build any packages it needs via Homebrew.

As always, read "brew doctor" to get more info about how to set up your particular system.

  • 0 Shares
  • Share on Facebook
  • Share on Twitter
John Barker

Start small and compose: A strategy for using FactoryGirl

John Barker
Tuesday, March 5, 2013

While I’m still not entirely sold on FactoryGirl, I often see it being used in a particularly lazy way. Imagine your basic factory:

factory :project

Before long you’re adding relations to projects, and the first thing people do is this:

factory :project do
  association :user
end

This immediately means that every single time you instantiate a project, you’re getting a user as well. In most cases this is more than you want, and if you continue to follow down this path you end up with a huge slow test suite. I prefer a slightly different strategy: start small and compose.

factory :project do
  ...
end

trait :with_manager do
  association :user, factory: :manager
end

This defines a very simple factory :project which gives you only a project and allows you to build a project with an associated user like so:

FactoryGirl.create(:project, :with_manager)

The result is a couple more arguments when you use the factory, but the overall code is more intention revealing.

If this is too much, you could always create a more descriptive factory:

factory :managed_project, parent: :project, traits: [:with_manager]

If you stick with this strategy, you’ll find that tests are more concise, factories are more useful and your test suite run time won’t grow as fast.

  • 0 Shares
  • Share on Facebook
  • Share on Twitter
Ken Mayer

method_missing hazardous to your module?

Ken Mayer
Friday, February 22, 2013

We built an(other) object factory module for our current project and it looks a lot like all the others:

Continue reading →

  • 0 Shares
  • Share on Facebook
  • Share on Twitter
Mark Rushakoff

Building identical gems

Mark Rushakoff
Friday, February 22, 2013

We ran into a problem where we were running `gem build` on identical input files and the built gems had different checksums; that is to say, if you run `gem build` twice in a row, the resulting `foobar.gem` files will not be identical.

A .gem file is actually a tar file (not compressed) containing two gzipped files (manifest.gz and data.tar.gz). What’s happening, as far as we can tell, is that gzipping a file embeds a timestamp somewhere in the file — here’s a gist of a Bash session that demonstrates just this idea:

Apparently gzip on its own can exclude the timestamp, but that option doesn’t seem to be exposed through tar.

So how do you build identical gems from the same input? As far as we could discover, that is not supported through any `gem` commands. To normalize a gem, you would have to untar the .gem file and then decompress the files inside; then you can do a full comparison of those contents against another .gem file that went through the same process.

  • 0 Shares
  • Share on Facebook
  • Share on Twitter
Mark Rushakoff

How to simultaneously display and capture the output of an external command in Ruby

Mark Rushakoff
Sunday, February 17, 2013

There are many ways to run external commands in Ruby: surround with backticks, enclose in %x{}, call Kernel#system…

None of those approaches let you display the output of the command in real time while simultaneously capturing the output. Here’s a gist showing how to use IO.popen to capture output, display output, and check exit status:

  • 0 Shares
  • Share on Facebook
  • Share on Twitter
Mark Rushakoff

What happened to stdout on CI?

Mark Rushakoff
Thursday, February 14, 2013

We were struggling for a bit yesterday trying to figure out why the few puts statements in our tests weren’t being displayed in Jenkins’ console output.

It turns out the ci_reporter gem that we were using (so that Jenkins could parse our test results) swallows stdout and stderr by default — unless you set the CI_CAPTURE environment variable to the string "off", like it tells you to do in the readme.

That was a confusing default setting. Since my pair and I weren’t involved in setting up Jenkins, and we didn’t install the ci_reporter gem, we assumed something was misconfigured in Jenkins before we started digging through the code.

Hopefully this saves someone else some time!

  • 0 Shares
  • Share on Facebook
  • Share on Twitter
Phil Goodwin

“expect errors”

Phil Goodwin
Friday, February 8, 2013

Helps

"expect errors" when compiling Ruby with clang

Compiled Ruby with clang and the compile output contained a warning to "expect errors". Has anyone experienced these alleged errors?

One member or our audience said that they had compiled the same way and not experienced any problems.

Interestings

Update your rack gem

Nasty remote execution vulnerability.

rack.github.com

parallel_tests prepare task does not drop tables

If you're using parallel_tests, be aware that, unlike rake db:test:prepare, the rake parallel:prepare task does not purge the databases before it loads the schema. You'll only notice this if you're dropping tables – the dropped tables will stay forever in the parallel databases.

We have a fork that works properly. (Pull request coming soon.)
https://github.com/pivotal-gemini/parallel_tests

Events

02/15: Block Party

http://engine.is/blockparty

next Friday celebrating start ups in SF w/food trucks at lunch time.

  • 0 Shares
  • Share on Facebook
  • Share on Twitter
Travis Grathwell

Running tests with Zeus in RubyMine

Travis Grathwell
Tuesday, February 5, 2013

(Adapted from a thread on the RubyMine support forums)

Zeus is a self-described “language-agnostic application checkpointer for non-multithreaded applications.” As a Rails developer, you can use Zeus to keep your rails environment loaded so your tests run super fast. Spork does this job as well, but Zeus is newer/shinier and requires less explicit configuration. Zeus’ standard operating mode requires you to keep a Zeus server running (started with zeus start) to which you can issue commands (like zeus rspec).

To get Zeus installed on your system, follow the readme or this lovely post at ThoughtBot. The issue they mention with require ‘rspec/autorun’ should be fixed in the latest Zeus, but you can safely remove it from your spec_helper anyway.

In your Gemfile, add zeus:

group :test do
  gem 'zeus'
end

Yes the Zeus manual wants you to only have one global install, but RubyMine won’t be able to see it when running tests, because it always runs them under bundler. (You’ll get a cannot load such file — zeus or zeus is not part of the bundle error.)

Add this script to your Rails project as script/rspec_runner.rb:

#!/usr/bin/env ruby

# Suppress zeus' whining about how it won't use your RAILS_ENV
ENV.delete('RAILS_ENV')

# Zeus 0.13.2 parses options badly. RubyMine will invoke this file like this:
# rspec_runner.rb spec/my_cool_file.rb --require teamcity/spec/runner/formatter/teamcity/formatter --format Spec::Runner::Formatter::TeamcityFormatter
#
# ...but Zeus will parse those options thinking --require is meant for it, and die.
# If the test file is moved to the end, it dies less.
ARGV.push(ARGV.shift)

# Add rspec to the beginning of the commands sent to Zeus
ARGV.unshift 'rspec'

require 'rubygems'
require 'zeus'
load Gem.bin_path('zeus', 'zeus')

In RubyMine’s ‘Edit Configurations’, under Default -> Rspec:

Check ‘Use Custom Rspec Runner Script’
Set it to [your-absolute-app-path]/script/rspec_runner.rb

Your ‘Edit Configuration’ window should look like this: zeus_setup

When starting the Zeus server, use the following line:

env RUBYLIB=/Applications/RubyMine.app/rb/testing/patch/common:/Applications/RubyMine.app/rb/testing/patch/bdd zeus start

(I made this a script in my project called script/startzeus.)

These directories are where RubyMine keeps its favorite test formatters, and if you don’t tell Zeus about them at server load time, it may never find them. (you’ll get a cannot load such file — teamcity/spec/runner/formatter/teamcity/formatter error). If you’re not on OSX, you should replace these directories with something relevant to your system.

Now you can run a test in RubyMine just like you would normally, and it should be LIGHTNING FAST. Get it? Lightning? Zeus? You get it.

  • 0 Shares
  • Share on Facebook
  • Share on Twitter

Topics

  • agile (778)
  • rails (113)
  • testing (87)
  • ruby (83)
  • ruby on rails (70)
  • jobs (62)
  • javascript (54)
  • techtalk (44)
  • rspec (38)
  • activerecord (29)
  • productivity (29)
  • gogaruco (29)
  • ironblogger (29)
  • git (28)
  • nyc (27)
  • rubymine (25)
  • mobile (22)
  • bloggerdome (21)
  • cucumber (20)
  • process (19)
  • pivotal tracker (19)
  • jasmine (19)
  • design (18)
  • ios (18)
  • webos (17)
  • objective-c (17)
  • android (16)
  • palm (16)
  • "soft" ware (16)
  • fun (15)
  • tracker ecosystem (15)
  • ci (15)
  • cedar (15)
  • rails3 (14)
  • performance (14)
  • bdd (14)
  • gem (13)
  • tdd (13)
  • selenium (12)
  • css (12)
  • goruco (12)
  • bundler (12)
  • meetup (11)
  • railsconf (11)
  • nyc-standup (11)
  • capybara (10)
  • mac (10)
  • mojo (10)
  • chef (10)
  • api (10)
Subscribe to ruby Feed
  1. 1
  2. 2
  3. 3
  4. 4
  5. 5
  6. 6
  7. 7
  8. 8
  9. 9
  10. →
  • About
  • Case Studies
  • Team
  • Community
  • Careers
  • Contact
  • Labs
  • Events

Contact Us

contact@pivotallabs.com
+1 415-77-PIVOT
TwitterLinkedInFacebook

Pivotal Tracker

Tracker is the award-winning agile project management tool that enables real-time collaboration around a shared, prioritized backlog.
Visit pivotaltracker.com >