Jeff DeanJeff Dean
Working with asynchronously loaded javascript
edit Posted by Jeff Dean on Wednesday September 01, 2010 at 12:06PM

My pair and I were recently working on an app that asynchronously loaded the Facebook Javascript SDK but synchronously loaded the jQuery library. We had to invoke some javascript once Facebook and jQuery were both loaded, and this post describes how we did it.

Glenn JahnkeGlenn Jahnke
Standup 9/1/2010 - Rspec2 + RubyMine and Testing for Class methods
edit Posted by Glenn Jahnke on Wednesday September 01, 2010 at 09:24AM

Help

Testing for class methods in Ruby

How do you test for the existence of a class method? Test it using #respond_to?

class Foo
    def self.bar 
        puts "Hello, World!"
    end
end

Foo.respond_to?(:bar)
 => true

And to make sure we are really just talking about class methods and not instance methods:

foo = Foo.new

foo.respond_to?(:bar)
 => false

Interesting

RubyMine and Rspec2 Bug Fixed!

We use the latest and greatest RubyMine version available at Pivotal, but sometimes technology choices such as Rails 3 and Rspec 2 are still ahead of it. The formatter that analyzes test output breaks on Rspec 2's output before any tests run. The bug is further discussed http://youtrack.jetbrains.net/issue/RUBY-6485. Luckily this bug will be fixed in the next EAP release.

Excuting .rvmrc commands and cruisecontrol

We've had a difficult time getting .rvmrc files to work with cruisecontrol.rb builds. Specifically, ccrb seems to launch the rake task in the project working directory. This means that the .rvmrc file is ignored. A workaround is to have your CI script directly use RVM or to add "cd .. && cd work" before your project cruise script or rake task.

Mike BarinekMike Barinek
Cucumber performance improvements with Devise Token Authenticatable
edit Posted by Mike Barinek on Wednesday September 01, 2010 at 08:45AM

We're using Devise's token_authenticatable to improve our Cucumber test suite performance.

Here's an example feature


  Scenario: I would like to edit a user account
    Given I am logged in as an admin user
    ...

And here's the token_authenticatable step


  Given /^(?:I am logged in|the user is logged in|the user logs in|I log in)(?: as an? (\w+) user)?$/ do |role|
    if ENV['use_token']
      visit admin_dashboard_path(:token => @user.authentication_token)
    else
      Given("the user logs in with email: \"#{@user.email}\", password: \"#{@password}\"")
      ...
    end

We'll then run cucumber using a "faster" profile


$ cucumber -p faster

And finally, here's our cucumber.yml


faster: <%= std_opts %> features FASTER=true

Our cucumber tests run significantly faster after switching to the token_authenticatable approach.

Josh KnowlesJosh Knowles
National Lab Day seeks Ruby Developer in NYC
edit Posted by Josh Knowles on Tuesday August 31, 2010 at 01:28PM

At Pivotal Labs, one of the services we provide our clients is helping them interview and hire. Pivotal Labs and our clients place a strong emphasis on Agile development and its many aspects: Pair Programming, Test-Driven Development, rapid iterations, and frequent refactoring.

National Lab Day a New York, NY non-profit company, is looking for an Agile UI Developer to join their team. The full job posting follows.

Mike BarinekMike Barinek
Reindexing Solr from Cucumber
edit Posted by Mike Barinek on Tuesday August 31, 2010 at 01:21PM

Here's a quick snippet that we're using to reindex Solr from our Cucumber features.

"And I reindex assets" helps to ensure that we didn't leave any cruft around from previous tests and that we've properly indexed our Pickle model.


  Background:
    And I am logged in as an admin user
    And an asset with snowboarding tags: "snowboarding" exists with title: "Snowboarding", alt_text: "Snowboarding", summary: "A summary about snowboards"
    And I reindex assets

  Scenario:  An Editor searches for an asset by title
    When I go to the url: "/assets?q=Snowboarding"
    Then I should see "Snowboarding"    

Here's the actual step


  When /^I reindex (.+)$/ do |model_name|
    model_name.singularize.capitalize.constantize.solr_reindex
  end

Glenn JahnkeGlenn Jahnke
Android Mongo Meetup
edit Posted by Glenn Jahnke on Tuesday August 31, 2010 at 09:39AM

There is meeting tonight at 7pm in San Francisco about using MongoDB for mobile backend servers. Will Shulman from MongoLab will be giving the talk. They will also be offering food and prizes to attendees.

More details can be found at:

http://www.sfandroid.org/calendar/14367370/?eventId=14367370&action=detail

Dan PodsedlyDan Podsedly
Aragorn: iPad app for Pivotal Tracker
edit Posted by Dan Podsedly on Monday August 30, 2010 at 11:45AM

We're excited to add a new entry to the 3rd party tools directory: Aragorn, the first Pivotal Tracker client for the iPad.

The first version of Aragorn supports read only views of your projects and stories within them. Thanks to @elight for writing the app!

Mike BarinekMike Barinek
Fast user switching with Devise
edit Posted by Mike Barinek on Saturday August 28, 2010 at 10:12PM

Ever wondered how to login as another user within Devise?

Recently we had a feature request that would provide Admins with the ability to sign is as another user. You could imagine live demonstrations or even production support calls where you would like to be signed in as another user, yet not have to ask for or decrypt their current password. After stewing for a bit, we found a pretty nice solution with Devise.

Here's the Cucumber feature...


  Feature: Sign in as another user
    As an admin
    I want to sign in as another user

    Scenario: Admin can sign in as another user
      Given I am logged in as an admin user
      And a user: "bob" exists with email: "bob@example.com", password: "password", ...
      When I go to the admin users page
      And I follow the "Sign in as" link for user: "bob"
      Then I should see "Welcome Bob"

The trick was to store the admin info within the rack session.

request.env['rack.session']['devise.remember_admin_user_id']

We decided on using a Rails 3 concern to keep our actual strategy clean.


require 'devise/strategies/base'

module SignInAs
  module Concerns
    module RememberAdmin
      extend ActiveSupport::Concern

      private

      def remember_admin_id
        request.env['rack.session']['devise.remember_admin_user_id']
      end

      def remember_admin_id=(id)
        request.env['rack.session']['devise.remember_admin_user_id'] = id
      end

      def remember_admin_id?
        request.env['rack.session'] && request.env['rack.session']['devise.remember_admin_user_id'].present?
      end

      def clear_remembered_admin_id
        request.env['rack.session']['devise.remember_admin_user_id'] = nil
      end
    end
  end
end

The above really makes writing the Devise strategy fairly easy.


require 'devise/strategies/base'

module SignInAs
  module Devise
    module Strategies
      class FromAdmin < ::Devise::Strategies::Base
        include SignInAs::Concerns::RememberAdmin

        def valid?
          remember_admin_id?
        end

        def authenticate!
          resource = User.find(remember_admin_id)
          if resource
            clear_remembered_admin_id
            success!(resource)
          else
            pass
          end
        end
      end
    end
  end
end

Warden::Strategies.add(:sign_in_as, SignInAs::Devise::Strategies::FromAdmin)

Then we just wire in our new strategy. Last line above.

Lastly, here's our sign-in-as controller which sets the Devise session variable.


class SignInAsController < ApplicationController
  include SignInAs::Concerns::RememberAdmin

  layout 'admin/application'

  def create
    if can?(:manage, :users)
      self.remember_admin_id = current_user.id
      sign_in :user, User.find(params[:user_id])
    end

    redirect_to '/admin'
  end

end

That's it, pretty neat and might make for a nice Gem or Devise addition.

Mike GehardMike Gehard
Ruby Enumerable and string
edit Posted by Mike Gehard on Friday August 27, 2010 at 07:07AM

Did you know that you can call map() and each() on a Ruby string? Do you know how they behave? I hope I'm not the only one that thought they understood it but was proven mistaken.

What would you expect the following code to do?

"hello".map{|char| "Char#{char}"  }

I thought it would return me an array with a bunch of "Char" where x is each letter in "hello". Nope...it returns:

["Charhello"]

What would you expect the following code to do?

"hello".each{|char| puts "Char#{char}"}

Yeah I thought it would write out a bunch of puts statements "Char" where x is each letter in "hello". Nope it prints:

Charhello

Ok so maybe my thoughts on strings being enumerable were a little off...I've been wrong before and will probably be wrong again.

What really threw me for a loop was that I can access the characters in a string by index:

"hello"[1]

returns

101

which is the ASCII representation of "e".

So what is the moral of this story? Sometimes things aren't as the seem at first glance. And sometimes you need to step back, fire up irb and see what really is happening.

Update: Thanks all for the responses below.

JT ArchieJT Archie
Standup 08/26/2010 - Rails controls too much of cache
edit Posted by JT Archie on Thursday August 26, 2010 at 09:17AM

Help

"Does Postgres have an equivalent MySql Myisam high write performance?"

A Pivot was wondering what settings in Postgres can be enabled for high performance INSERTs (willing to sacrafice SELECT performance on said table).

"Why is Paperclip giving a Stream close error when in development?"

When using Paperclip in development, any file upload results in a Stream IOError. Trying to replicate the problem with Paperclip on its own causes no problems, so it appears to be a conflicting library.

Interesting Things

  • An update to yesterday's Rubymine font size issue. The file drawer can not be specifically updated, but the overall system font can be under Preferences > Appearance > Fontsize. Make sure to restart Rubymine.
  • Google Voice has been added as a service on to GMail. Make phone calls for free to anywhere in the US from your browser.
  • An update to yesterday's Safari 'Back' button issue. Safari caches the previous ajax call (dubbed ajax zombie) when going back to a previous page. The fix had to do with changing Rails default "Cache-control" header to be "no-store".

Other articles: