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

Monthly Archives: October 2008

Adam Milligan

Rake test error due to –trace argument

Adam Milligan
Friday, October 31, 2008

We’ve had some trouble with test task errors causing failing builds on our continuous integration boxes ever since the release of the version 0.8.3 rake gem. Sound familiar? Read on!

As it turns out, we run all of our continuous integration tasks with the –trace option, so we can see what went wrong in the (extremely rare, of course) eventuality of some kind of error.

This is the output we started seeing with the new gem:

** Invoke selenium:local (first_time)
** Invoke environment (first_time)
** Execute environment
** Execute selenium:local
running selenium tests locally...
invalid option: --trace
Test::Unit automatic runner.
Usage: /usr/bin/rake [options] [-- untouched arguments]
<snip valid command line options>

After some investigation we uncovered changes in how rake 0.8.3 parses command line arguments. In particular, it doesn’t remove rake-specific arguments, like –trace, from the ARGV. So, when test tasks invoke the Test::Unit::AutoRunner class, it receives these arguments, fails to recognize them, and complains. Messily.

Unfortunately, we don’t have an immediate fix for you. We submitted a patch to the project, and Jim Weirich has already filed a bug report, so version 0.8.4 should resolve the problem.

Comments welcome.

  • 0 Shares
  • Share on Facebook
  • Share on Twitter
Rajan Agaskar

Standup 10/31/08

Rajan Agaskar
Friday, October 31, 2008

Interesting Things

  • Aliasing ActiveRecord reader methods

    ActiveRecord reader methods are not eagerly loaded, and as such cannot be aliased using alias_method. There are a number of workarounds to this, those talked about included: calling self.define_read_methods, after which all your read methods will be loaded and available for aliasing, or you can simply define the alias instead of using alias_method.

  • belongs_to and foreign keys.

    If you specify an alternate foreign key when using belongs to, you will have access to that id via the name of the foreign key, and not the name of the belongs_to association. It may be worthwhile allowing access to the id via the belongs_to association in order to keep consistency.

  • boo

    BOOOO!!!!! BOOOOOOOOO!

  • 0 Shares
  • Share on Facebook
  • Share on Twitter
Rajan Agaskar

Standup 10/30/08

Rajan Agaskar
Thursday, October 30, 2008

Interesting Things

  • Removing class definitions with Object.send(:remove_const, :Foo)

Sometimes it is necessary to reload or replace a stub/test class during testing (apparently rspec is particularly susceptible to this). This can be achieved using Object.send(:remove_const, :Foo) where Foo is the camel-cased name of the class. If your class is defined within a module, it may be necessary to use Module.send(:remove_const, :Foo)

Ask for help

  • foo.bar.reload versus foo.bar(true)

As a point of curiosity, does anybody know when has_many relationship reloading moved from (or to?) foo.bar(true) to foo.bar.reload? The reload syntax seems preferable for readability; will foo.bar(true) continue to work in the future?

  • 0 Shares
  • Share on Facebook
  • Share on Twitter
Pivotal Labs

Hacking a subselect in ActiveRecord

Pivotal Labs
Wednesday, October 29, 2008

This week, Damon and I were doing a performance optimization for some slow queries. The most performant solution involved denormalizing some data into a join table and doing a subselect to get the ids of the records we wanted. Not rocket science, but also a bit ugly to construct the SQL by hand. Our solution was to cheat a tiny bit and use an ActiveRecord internal method to generate the SQL for us.

def favorite_posts(options={})
  subselect = Favorite.send(
                :construct_finder_sql,
                  :select => "post_id",
                  :conditions => {:blog_id => self.id},
                  :order => "published_at DESC",
                  :limit => options[:limit] || 10, :offset => options[:offset])
  Post.find(:all, :conditions => "posts.id IN (#{subselect})", :order => "published_at DESC")
end

That code uses the private method Favorite.construct_finder_sql to generate the following SQL:

SELECT * FROM posts WHERE posts.id IN (
    SELECT post_id FROM favorites WHERE blog_id = 42 ORDER BY published_at DESC LIMIT 10 OFFSET 10
  ) ORDER BY published_at DESC

The Ruby may look like more code than the SQL, and in that form it is… but if you go the hack up a string route, once you start using string operations or interpolation to deal with the variable parts of the query it gets ugly pretty fast. Using the ActiveRecord code to put it all together keeps it nice and clean, and even makes sure things are sanitized and quoted properly too.

  • 0 Shares
  • Share on Facebook
  • Share on Twitter
Rajan Agaskar

Standup 10/29/08

Rajan Agaskar
Wednesday, October 29, 2008

Interesting Things

  • has_many_polymorphs preloads models

has_many_polymorphs will scan through the models directory for any files that include the plugin and preload them. This can cause problems if these models depend on other plugins (that have not yet been loaded) to operate correctly. The has_many_polymorphs source mentions this behavior in a comment and includes a fix:

Searches for models that use has_many_polymorphs or acts_as_double_polymorphic_join and makes sure that they get loaded during app initialization. This ensures that helper methods are injected into the target classes.

Note that you can override DEFAULT_OPTIONS via Rails::Configuration#has_many_polymorphs_options. For example, if you need an application extension to be required before has_many_polymorphs loads your models, add an after_initialize block in config/environment.rb that appends to the ‘requirements’ key:

  Rails::Initializer.run do |config|
    # your other configuration here

    config.after_initialize do
      config.has_many_polymorphs_options['requirements'] << 'lib/my_extension'
    end
  end

Instead of using config.has_many_polymorphs_options, we were able to achieve the same effect by simply dropping our required plugins into the after_initialize block. If we decide to remove has_many_polymorphs in the future, the config file should still run correctly. It’s worth noting that the UltraSphinx search plugin operates in a similar fashion.

  • returning JavaScript in an Ajax IFrame Method (AIM) call

If you are using AIM for file uploads, you may find that any content returned to the IFrame is escaped (as if it were regular HTML). On some browsers, this occurs regardless of what the content-type is set to. A workaround is to embed any content that you don’t want escaped into a comment tag; after the request completes, you can use JavaScript to retrieve the contents and optionally eval them.

Ask for help

  • Ajax click_and_wait for Selenium?

assert_text_present offers a simple way to test Ajax behaviors in Selenium, as it will wait 5 seconds (during which the Ajax callback can complete) while looking for the specified text (which can be the body of your Ajax response). Another strategy with which we’ve had some luck is to write a custom method that will wait a specified amount of time before continuing (particularly useful if your Ajax call takes a lengthy amount of time to complete).

  • 0 Shares
  • Share on Facebook
  • Share on Twitter

Vertebra

Wednesday, October 29, 2008 | Run time: 41:54

Ezra Zygmuntowicz talks about Vertebra, Engine Yard’s distributed cloud application programming platform.

  • 0 Shares
  • Share on Facebook
  • Share on Twitter
Mike Grafton

New York Standup 10/29/2008

Mike Grafton
Wednesday, October 29, 2008

Interesting

  • Until a recent commit, Polonium defined a method on Module named deprecate, which (at least in our case) overrode the method of the same name defined in Rails. This caused some code in Rails to blow up at class loading time when trying to call Rails’ deprecate method with the wrong number of arguments.

    We changed the name of Polonium’s method so it wouldn’t clash with Rails, and checked this into the master branch of Polonium on GitHub.

  • As of Rails 2.1, ActiveRecord support partial updates, which means that it’s smarter about what fields get updated in the SQL UPDATE statement issued by save. If you haven’t updated any fields in the object, no update will happen at all, no AR callbacks will fire, etc. If you depend on these things to happen even when not updating any fields, you can call will_change! on the model object. It was floated that a force_save method might be helpful.

  • It is often claimed that Symbol#to_proc is to slow to use in production code. But a clever Rubyist out there found a way to speed it up by 4x.

  • The test run for one of our projects here runs in 223 seconds on OSX, but in in 157s on Ubuntu. We’d like to figure out why (we’re pretty sure we’re using the MySQL Gem rather than the built-in MySQL driver that comes with Rails)

  • Git4Idea is now available through the IntelliJ Plugin manager. No more hand installation!

  • ActiveRecord::Base#to_param must return a String if you override it. If you return an Integer you will get a weird “Can’t convert Fixnum to String” exception somewhere deep in the routing code. You can’t even tell where the exception is coming from due to the routing code’s bizarreness.

  • 0 Shares
  • Share on Facebook
  • Share on Twitter
Rajan Agaskar

Standup 10/28/08

Rajan Agaskar
Tuesday, October 28, 2008

Interesting Things

  • before_save and after_save may not perform as you expect!

Previously, returning false from before or after filters callbacks would halt the chain entirely. This is no longer the case, except with before_save and after_save — returning false in a before_save will stop the filter callback chain and prevent a save, returning false in an after_save will stop the filter chain silently, and NOT rollback the save. This can be troublesome if you have after_save filters callbacks you expect to execute, especially if you have conditional clauses in an after_save, as they can easily return a false value where you did not intend it.

Please see Brandon Keepers’ clarification regarding filters vs. callbacks below — thanks Brandon!

Ask for help

  • Bootstrapping data into an existing system?

Using migrations for one-time data inserts can be problematic (for example, when changing seed data; additionally, it’s advisable to create a database from the schema.rb rather than migrations) , it can be useful to create a class that is responsible for inserting the seed data into the database. This class can be wrapped in a capistrano or rake task. The db-populate plugin is designed to aid in this task.

  • Multiple Routes/One controller

It is possible to point multiple routes at a single controller, however, this situation may suggest a need for multiple controllers, possibly inheriting from a single base controller containing any shared logic. This prevents a excessive switching logic in controllers, which can help minimize the possibility of argument-related bugs.

  • 0 Shares
  • Share on Facebook
  • Share on Twitter
Pivotal Labs

RR 0.6.2 Released

Pivotal Labs
Tuesday, October 28, 2008

This release features a sexier Double definition block syntax using instance_eval:

mock(User) do
  find(1) {user_1}
  find(2) {user_2}
end

RR also maintains its non-instance_evaled Double definition block syntax, if the block has an arity of 1:

mock(User) do |expect|
  expect.find(1) {user_1}
  expect.find(2) {user_2}
end

The instance_eval syntax is very useful in the context of Double Definition chaining:

mock.proxy(User).find(1) do
  mock.proxy! do
    blogs do
      mock.proxy!.find_by_id(2) do |actual_blog|
        actual_blog.name.should == "My ranty blog"
        actual_blog
      end
    end

    fans do
      mock.proxy!.thank_everybody
    end

    foes do
      mock.proxy!.ask_for_forgiveness
    end
  end
end

user = User.find(1)
user.blogs.find_by_id(2) # My ranty blog
user.fans.thank_everybody
user.foes.ask_for_forgiveness

Of course the previous example is a complicated case of interaction testing, and a simpler state-based and/or hybrid approach may be better, but it demonstrates how using instance_eval can promote readability.

Here is the non-instance_eval solution:

mock.proxy(User).find(1) do
  mock.proxy! do |expect|
    expect.blogs do
      mock.proxy!.find_by_id(2) do |actual_blog|
        actual_blog.name.should == "My ranty blog"
        actual_blog
      end
    end

    expect.fans do
      mock.proxy!.thank_everybody
    end

    expect.foes do
      mock.proxy!.ask_for_forgiveness
    end
  end
end

instance_eval Controversy

Ola Bini warned against overusing instance_eval. While instance_eval adds beauty, it can also make things more difficult to extend and debug.

In RR, the DoubleDefinitionCreatorProxy (the object that is instance_evaled when defining Doubles using blocks) uses the blank slate pattern, so arbitrary method names can be passed in to define the Double. The Blank Slate implies that the DoubleDefinitionCreatorProxy will not be extended with methods. James Earl Gray explains the pattern that I used for RR.

spec/test helper methods will not be usable within the instance_evaled blocks because the intent of the DoubleDefinitionCreatorProxy object is incompatible with the instance_eval with delegation pattern. DoubleDefinitionCreatorProxy already uses method_missing to create DoubleDefinitions. If you wish to use spec/test helper methods, you will need to memoize it to a variable and use lexical scoping.

Now, one may want to define a helper method in the test/spec that is returned when the Double is invoked.

describe User do
  describe "#fans.thank_everybody" do
    it "thanks all of my lovely fans" do
      user = User.new
      memoized_my_lovely_fans = my_lovely_fans
      mock(user) {fans {memoized_my_lovely_fans}}
      memoized_my_lovely_fans.each {|fan| mock(fan).thank_you}

      user.fans.thank_everybody
    end

    def my_lovely_fans
      [Fan.new, Fan.new]
    end
  end
end

While I think this will be a good addition to RR, I recognize that adding the instance_eval has the possibility of making RR less usable. I’ll pay close attention to see how this pans out and am willing to remove it if there are major issues.

  • 0 Shares
  • Share on Facebook
  • Share on Twitter

Fire Eagle

Monday, October 27, 2008 | Run time: 44:35

Seth Fitzsimmons and Blaine Cook talk about Fire Eagle, a location-awareness provider for online applications. Fire Eagle is a Yahoo! venture that gives applications and websites user-configurable information about the user’s location.

  • 0 Shares
  • Share on Facebook
  • Share on Twitter

Topics

  • agile (778)
  • rails (113)
  • testing (86)
  • ruby (83)
  • ruby on rails (70)
  • jobs (62)
  • javascript (53)
  • techtalk (44)
  • rspec (38)
  • activerecord (29)
  • productivity (29)
  • gogaruco (29)
  • ironblogger (29)
  • git (28)
  • nyc (27)
  • rubymine (25)
  • mobile (21)
  • cucumber (20)
  • bloggerdome (19)
  • process (19)
  • pivotal tracker (19)
  • design (18)
  • jasmine (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)
  • gem (13)
  • bdd (13)
  • selenium (12)
  • css (12)
  • goruco (12)
  • bundler (12)
  • tdd (12)
  • meetup (11)
  • railsconf (11)
  • nyc-standup (11)
  • capybara (10)
  • mac (10)
  • mojo (10)
  • chef (10)
  • rubygems (9)
Subscribe to Community Feed
  1. 1
  2. 2
  3. 3
  4. 4
  5. 5
  6. →
  • 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 >