Danny Burkes's blog



Danny BurkesDanny Burkes
Ruby + Salesforce = Happy Developers
edit Posted by Danny Burkes on Monday August 29, 2011 at 05:44PM

Pivotal is proud to announce the release of the databasedotcom gem. Developed in partnership with Heroku and Salesforce, this gem wraps the Force.com REST API in familiar Ruby idioms, making it a snap to create web applications that integrate with your existing Salesforce instance, or even straight Ruby apps that do offline analysis of your Salesforce data.

I will be giving a session at Dreamforce on Tuesday, August 30, introducing the gem and demonstrating how easy it is to integrate into a Rails application. The session is entitled Building and Deploying Great Applications with Salesforce, Ruby, and Heroku, and takes place in Moscone West Room 2008 from 5:00 pm - 6:00 pm.

Source code from the session will be available soon, as will the session slides.

Hope to see you there!

The Ugly Truth

On a recent project, we had an ActiveRecord model that declared some relationships and callbacks like so:

belongs_to :credit_card
before_create :build_credit_card

The intent was that build_credit_card would build the associated CreditCard instance, and ActiveRecord's default :autosave feature on the belongs_to would save it.

What we discovered was that no CreditCard object was being persisted. We confirmed that :autosave is on by default for belongs_to relationships, so we couldn't immediately understand why the new CreditCard wasn't being created.

Googling proved futile, so we dove right in to the ActiveRecord source- and boy did we have a good laugh about 10 minutes later.

What we found was that the :autosave option works by simply declaring a before_save callback- that makes perfect sense.

In our case, however, we were building the object to be autosaved in a before_create callback, which ActiveRecords runs after the before_save callbacks (cf. the callback ordering docs).

So our first problem was that we needed to move the call to build_credit_card from a before_create callback to a before_save :on => :create callback.

Did you catch that? There is a difference between before_create and before_save :on => :create. A big difference.

While I understand the how and why of this, the semantics don't make it obvious. So beware!

Now with our declarations changed to

belongs_to :credit_card
before_save :build_credit_card, :on => :create

We ran our tests again, and, still, no love. Ahhh, we've still got an ordering problem. In addition to the ordering semantics detailed in the docs, ActiveRecord also runs callbacks within a single group in the order in which they are declared. So, even though we changed the call to build_credit_card to occur in a before_save, it was still occurring after the :autosave before_save callback, because of the declaration order.

Finally, we changed our declarations to

before_save :build_credit_card, :on => :create
belongs_to :credit_card

and our tests were happy.

Takeaways

  • When using autosave with any ActiveRecord association, be very careful of callback ordering if you are building or modifying the inverse objects using ActiveRecord callbacks.

  • before_create isn't ever the same thing as before_save :on => :create, even if it sounds like it should be.

Danny BurkesDanny Burkes
Making WebMock, Selenium, and WebDriver Play Nicely
edit Posted by Danny Burkes on Friday June 10, 2011 at 11:53PM

Update

Since this article was written, version 1.7.0 of WebMock has been released, which includes WebMock.disable! functionality, as well as fixes the problem with selenium-webdriver. So please use that, instead of webmock-disabler.

The Problem

Recently, one of my projects ran into a problem where our integration tests would intermittently fail with weird timeout errors and complaints about page elements that couldn't be found.

A little googling revealed that we weren't the only ones having this problem.

Apparently, WebMock, Selenium, and WebDriver don't play nicely together, even if you tell WebMock to allow the outgoing connections necessary to drive the browser.

Some Gemfile hacking revealed that it was the mere presence of WebMock that caused the error. If we removed WebMock from our Gemfile, our integration tests ran fine, but then of course all of our tests that actually needed WebMock failed.

At that point, we could have decided to run our integration tests separately from the rest of the tests, but we really liked the idea of having all the tests run in the same VM, to avoid the duplicate VM startup time.

What we really needed was a way to turn WebMock on and off selectively for different types of tests.

The Solution

With some gnarly monkey patching and offensive use of alias_method, I have created webmock-disabler, a gem which provides new WebMock.disable! and WebMock.enable! methods. You can use these methods in individual tests, or on classes of tests as shown in the README.

The Result

We're now able to run our tests that need WebMock in the same VM as those that would otherwise break if we didn't do WebMock.disable!.

Celebration time!

Danny BurkesDanny Burkes
Standup 3/10/2011
edit Posted by Danny Burkes on Monday March 14, 2011 at 10:43AM

Interesting

RSpec 2.5, Capybara, and Selenium

Capybara, Selenium, and RSpec's request specs play nicely together, and you can even run tests that require javascript, using the :js => true option.

However, doing do requires the very latest Capybara, so be sure to specify the :git option in your Gemfile.

Ryan Bates has done an excellent RailsCasts episode on just this.

Danny BurkesDanny Burkes
Standup 3/9/2011
edit Posted by Danny Burkes on Wednesday March 09, 2011 at 09:17AM

Interesting

SFRuby Hack Nights

The San Francisco Ruby Meetup Group is hosting a hack night tonight. See the website for details.

Named scopes and includes

A pivot noted that, after an association was loaded via :include, application of a named scope to the association will result in a new query.

The moral- sometimes an :include is less efficient than loading the association separately. Mind your logs.

WADL

A pivot remarked on the existence of WADL, a sort-of SOAP-less version of WSDL, where you can describe a REST API in XML for machine consumption.

It's 100% less SOAPy, but still just as <tag>gy.

Danny BurkesDanny Burkes
Standup 3/8/2011
edit Posted by Danny Burkes on Tuesday March 08, 2011 at 09:11AM

Interesting

RVM local/server version mismatch

A pivot noted that if you are using RVM in both your development and production environments, and you are using Capistrano for deployment, that you could encounter weird errors at deploy time like:

99: rvm_error: command not found
 ** [out :: app_user] /home/app_user/.rvm/scripts/rvm: line
121: __rvm_conditionally_add_bin_path: command not found
 ** [out :: example.com] /home/app_user/.rvm/bin/rvm-shell: line
26: rvm: command not found

These errors occur even after you follow the instructions at http://rvm.beginrescueend.com/integration/capistrano/.

The moral- make sure your RVM version numbers match in development and production.

Danny BurkesDanny Burkes
Standup 5/27/2010
edit Posted by Danny Burkes on Thursday May 27, 2010 at 12:52PM

Ask for Help

Recurring jobs

A pivot asked "what is the current state of the art in scheduling recurring processes?"

The first-order answer was simply "cron", but then the conversation got interesting.

Cron has a few downsides-

  • Each task execution has to re-load the entire ruby/rails runtime, so, you pay a significant penalty in terms of startup time
  • Crontabs often don't get checked into source control, so there ends up being little visibility into which jobs are running when

One suggestion to solve the visibility problem was to use the whatever gem, which allows you to express your cron schedules in a ruby DSL that can easily be kept in source control.

A suggested alternative that eliminates cron altogether is resque-scheduler with resque.

The upsides with resque-based scheduling are that all your schedule logic is expressed in ruby, and you don't pay the ruby/rails startup penalty for each worker.

The downside is that it adds additional operational infrastructure for you to manage (the resque workers and the redis server(s)).

Danny BurkesDanny Burkes
Standup 5/25/2010
edit Posted by Danny Burkes on Tuesday May 25, 2010 at 12:46PM

Interesting Things

  • Rails 2.3.8 is out, fixing HAML compatibility and no longer inadvertently requiring rails_xss.

  • RailsBridge Open Workshop Project is hosting Mighty Ruby Tuesday tonight in San Francisco. RailsBridge puts on workshops around San Francisco (and last week, in New York) that give women a safe place to learn programming, or if they're already programmers, learn Ruby. Pivotal is a sponsor and we support this important effort to bring gender parity to the Rails community.

Danny BurkesDanny Burkes
Standup 5/24/2010
edit Posted by Danny Burkes on Monday May 24, 2010 at 03:40PM

Ask for Help

Identify and uploaded files

Running identify on uploaded files sometimes fails, because by the time identify gets hold of the file, the file extension has been lost (it has been written to /tmp or the like).

The suggested workaround was to see if the filename specified in the Content-Disposition header, if present, could be carried through to the temporary file.

Interesting Things

  • Amazon has recently introduced a reduced-durabilty pricing tier for S3 storage, with significant discounts available to those who can live with 4 9's versus 11 9's of reliability. This seems like a win for things like thumbnails, which can easily be re-created from the originals on the off chance that they were actually lost by S3.

  • Rails 2.3.7 is out, but it doesn't play nice with HAML just yet. Projects using HAML should avoid upgrading until those incompatibilities are ironed out.