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
Pivotal Labs

NYC Standup Roundup – Week of 4/19

Pivotal Labs
Saturday, April 24, 2010

Interesting

  • A Pivot noted a facepalm + headdesk moment when debugging an issue whose cause turned out to be related to two adjacent string literals being auto-concatenated by Ruby’s parser.

    >> "foo" "bar"
    => "foobar"
    

In this case, a missing comma in a method call went undetected because of this language characteristic. Whether or not this follows the principle of least surprise is an exercise left up to the reader.

  • Another pair warned that while this is valid syntax in Ruby 1.8.7 and beyond:

    define_method(:burninate) { |&block| block.call("burninating") }
    

.. in 1.8.6 you can’t use a block as a parameter of a block.

  • Another pair noted that exceptions with Sunspot can cause wider failures on a site than just those that touch Solr. The symptom on this project was that if Solr was inaccessible for any reason every page on the site would throw an error. Their fix was to use Sunspot’s SessionProxy to wrap methods with some exception handling love.

  • Lastly, GoRuCo — the Gotham Ruby Conference — will be held on May 22nd at Pace University’s downtown campus. The roster of talks is up and registration is open for business.

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

NYC Standup Roundup – Week of 4/12

Pivotal Labs
Sunday, April 18, 2010

Help

Does anybody have any good techniques for dealing with STDOUT/STDERR and exception handling when shelling out in Ruby on Windows?

Nobody did. Do you? Please share in the comments.

Interesting

A pair ran system updates on their Snow Leopard box which caused bunch of test failures in their project. Most of the failures were occurring around the parts of the application that used BigDecimal. After digging they found:

     >> BigDecimal.new("1.01").to_f
     => 1.1

Oops! Looks like Apple shipped Ruby 1.8.7 p173 with a recent update. p173 has a bug that some dude introduced into BigDecimal. The fix was to update to p174 which was released quickly after this was discovered.

While on the subject, BigDecimal is kind of a drag. Its #inspect output is inhumane and new’ing up BigDecimal objects requires an ugly call to its constructor. A Pivot recommended using the undocumented bigdecimal/util which adds a convenience method to Float for creating new BigDecimals:

    >> require 'bigdecimal/util'
    >> 3.14159265.to_d
    => #<BigDecimal:10056bea8,'0.314159265E1',12(16)>

And a nickel’s worth of free advice?

    >> BigDecimal.send :alias_method, :inspect, :to_s
    >> 98.6.to_d
    => 0.986E2

Unless you prefer:

    #<BigDecimal:101137c78,'0.986E2',8(8)>
  • 0 Shares
  • Share on Facebook
  • Share on Twitter
Pivotal Labs

Ruby Summer of Code at Pivotal Labs

Pivotal Labs
Thursday, April 1, 2010

As you may have heard, this year there aren’t any Ruby projects as part of this year’s Google Summer of Code. The Ruby community’s response to this is a pretty amazing validation of the awesomeness of us! We have created our own Ruby Summer of Code, and raised $100K in just 3 days to sponsor 20 students to work on Ruby open source projects. That’s actually a lot more than Google would have sponsored anyway. And Pivotal Labs is one of the six full-project sponsors, woot! We’re sponsoring $5K, the amount to cover one student’s work full time for the whole summer.

We will no doubt have some pivots volunteering for mentor spots. If you want to volunteer to mentor, you need to apply by the end of this week (April 3rd).

Pivotal Labs is also going to be providing desk space for (a couple?) local students who want to come work in the office for the summer – they’ll get to come to our daily standups, eat breakfast with us, attend our tech talks, play Pivot Pong, and just be part of the Pivotal experience. We hope there are some local students who participate in RSoC and that someone comes to hang out with us for the summer. It’s also likely that some local students would get to do a report on their projects at the Golden Gate Ruby Conference in September.

Students can apply for spots during the period April 5th-23rd.

Thanks to everyone for stepping up and supporting this great response. This is the kind of thing that makes being a Ruby developer so gratifying, and so fun too.

  • 0 Shares
  • Share on Facebook
  • Share on Twitter

TextMate: The Last Straw

Alex Chaffee
Tuesday, March 16, 2010

That’s it. I’m done with TextMate. It hasn’t been updated in over 2 years, either for essential functionality (replace in path) or performance fixes (searching through log files) or UI issues (how many boxes must you click to enable autosave?) or bug fixes. Every few months the author pokes his head up and says “I’m working on TextMate 3.0!” and then disappears again, happily accepting new license fees into his PayPal account.

I’ve just been bitten twice in two weeks by a bug that caused not just data loss, but data mangling in a way that was very difficult to fix. Here’s the rough steps to reproduce:

  1. Edit some files in TextMate
  2. Leave TextMate running in the foreground
  3. Switch to console and “git pull” in the latest code from your workmates
  4. Run a search-and-replace that edits a file that was changed (by someone else) during the merge
  5. Save that edit

You’ll see (with “git diff”) that your version of the file has your new post-merge changes… but it also has reverted your buddy’s changes from the merge. It’s like you decided that those changes were no good and reverted them yourself and then added your own.

If you fail to notice this before checking in, you will totally hose your version control… but just for that one file. You can’t just revert a whole commit… you’ll have to step through change by change to figure out which change was theirs, which change was yours, and which change looks like it was yours but was actually an inadvertent revert of theirs!

I can’t work under these conditions. I’m switching to RubyMine today. See http://bjclark.me/2010/03/10/rubymine-a-love-story/ for why.

P.S. I just found a bug report for this dated 2008-04-02. That’s just about 2 years ago for a critical data-losing bug. Woot.

  • http://ticket.macromates.com/show?ticket_id=B036CF83
  • http://ticket.macromates.com/show?ticket_id=CACBB533
  • 0 Shares
  • Share on Facebook
  • Share on Twitter
Pivotal Labs

Second thoughts on initializing modules

Pivotal Labs
Monday, February 15, 2010

This morning Yehuda Katz posted a response to my previous post, Technique for extending a method from a module, showing how a more modular organization of the Person class would allow for a solution that does not require a crazy meta programming hack. The idea is that by extracting the method we want to decorate into an ancestor class, Ruby makes it a lot easier to do what we want.

Previously I was aware that there were other ways I could structure the host class to make the module’s job easier but I did not try that because but I was writing the code with the knowledge that I would only be in control of one side of the equation, the module. The host class was going to be written by the end-user of the Rubygem the module was to be packaged in. Since I did not want to try dictate how the end-user structured the host class I ended up adding a lot of complexity to the module. The goal became how to write the module in a such a way that the class would “just work” upon including Teacher without requiring any additional steps to be taken. Asking the user to create an AbstractPerson class that contained their initialize method and then creating a subclass felt like an obtrusive request to make through a README that would ultimate negatively impact the user’s experience with the library.

Shortly after I put that blog post up I got this tweet from Josh Susser:

egad! are you sure you're solving the right problem?

I was trying to solve how to decorate the initialize method from a mixed-in module. My real problem however, was that I was trying to modify the behavior of the host’s initialize from a module which is a good way to get into trouble. I am now of the opinion that if the module does need to be instantiated in some way, a good solution is to provide a initialization style method that the host class can call.

class Person
  include Teacher

  def initialize
    initialize_teacher
    # initialize person
  end
end

An added benefit of this approach is that initialize_teacher can be called from anywhere, and doesn’t have to happen within Person.new. This explicit instantiation violates my original goal of being unobtrusive to the user but it sidesteps the can of worms that the original approach has. One obvious problem that was likely to come up was the case where the module’s initialize needs to take a parameter. Once that happens it is not longer completely transparent to user. Even worse is if the host class’s initialize needs to take it’s own parameter. At that point it falls apart completely.

Credit to Austin Putman for suggesting this in a comment on the first post. Also thank you to Yehuda Katz for his informative post on writing modular ruby code.

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

Technique for extending a method from a module

Pivotal Labs
Sunday, February 14, 2010
Update: Read the follow-up post Second thoughts on initializing modules

I was recently presented the problem of appending to the initialize method from a module that was being included. To do this it would need to override the class’s initialize method with my own but keep the functionality of the original initialize method.

Whenever I need to do something in Ruby that I know will require some experimentation I like to move outside of my application and reproduce the problem in a simple way. For this problem I created a Person class that mixes in a Teacher module.

module Teacher
  def initialize
    puts "initializing teacher"
  end
end

class Person
  include Teacher

  def initialize
    puts "initializing person"
  end
end

The goal is to get the following output when a Person object is created:

> Person.new
initializing teacher
initializing person

The basic program fails as expected; Teacher.new prints “initializing person” because Person’s initialize is trumping Teacher’s. Our immediate goal is to replace Person’s initialize with Teacher’s but in a way that preserves the original initialize method. By using alias_method we can create a copy of the original initialize method that we can call later.

module Teacher
  def self.included(base)
    base.class_eval do
      alias_method :original_initialize, :initialize
      def initialize
        puts "initializing teacher"
        original_initialize
      end
    end
  end
end

This solution is the simplest thing that could possibly work, unfortunately it also has one major limitation. For it to work the call to include Teacher in Person has to come after Person’s definition of initialize. This is may be fine in situations where you have total control over the Person class, but what if Teacher is going to be part of a library you are distributing? Asking your users to place the include line to your module in a specific spot is unacceptable.

To make this work we need to be able to capture definitions of the method we want to redefine even after our module has been included. This sounds like a good time to use Ruby’s method_added hook.

module Teacher

  def self.included(base)
    base.extend ClassMethods
    base.overwrite_initialize
    base.instance_eval do
      def method_added(name)
        return if name != :initialize
        overwrite_initialize
      end
    end
  end

  module ClassMethods
    def overwrite_initialize
      class_eval do
        unless method_defined?(:custom_initialize)
          define_method(:custom_initialize) do
            puts "teacher initialized"
            original_initialize
          end
        end

        if instance_method(:initialize) != instance_method(:custom_initialize)
          alias_method :original_initialize, :initialize
          alias_method :initialize, :custom_initialize
        end
      end
    end
  end

end

Whoa! As you can see a lot of complexity has been added to Teacher. However, what it’s doing is actually really cool. Here is the breakdown:

What self.included is doing:

  1. The ClassMethods module containing overwrite_initialize is added to base (Person).
  2. overwrite_initialize is invoked.
  3. method_added is defined on Person at the class level.

What overwrite_initialize does:

  1. If a method called custom_initialize does not exist it defines one. custom_initialize runs Teacher’s initialize logic and then defers to Person’s initialize.
  2. If the current initialize method is not our custom_initialize method then initialize is preserved as original_initialize and a copy of custom_initialize is made to replace initialize.

What method_added is doing:

  1. Watches for new methods with the name “initialize”.
  2. When an initialize method is defined method_added calls overwrite_initialize to put the chain from custom_initialize to this new initialize method in place.

What is particularly nice is that this implementation is flexible enough to handle multiple redefinitions of initialize. This is important because a subclass of Person may also define initialize. It is not perfect though—if the initialize in the subclass of Person calls super the program will go into an infinite loop where custom_initialize and the subclass’s initialize call each other indefinitely. If anyone has a suggestion on how to get around this please post a comment or fork the gist on Github.

Read the follow-up to this post Second thoughts on initializing modules.

  • 0 Shares
  • Share on Facebook
  • Share on Twitter

UTC vs Ruby, ActiveRecord, Sinatra, Heroku and Postgres

Alex Chaffee
Friday, January 22, 2010

Now that I’m starting to use DelayedJob to perform jobs in the future in my Heroku Sinatra app, its important that they happen at the scheduled time. But unless you pay attention, you’ll find that times get mysteriously changed — in my case, since I’m in San Francisco in the wintertime, by +/-8 hours — which means that some conversion to or from UTC is being attempted, but it’s only working halfway.

Trying to keep a handle on which libraries are attempting, and which are failing, to convert times is a losing battle, so I’m trying to do the right thing and save all my times in the database in UTC, and convert them to and from the user’s local time as close to the UI as possible. Unfortunately, a variety of gotchas in Ruby and ActiveRecord and PostgreSQL makes this trickier than it should be. Here’s a little catalog of my workarounds.


You must set both Time.zone = "UTC" and ActiveRecord::Base.default_timezone = :utc. Since I’m using Sinatra, not Rails, this stuff goes either in main (i.e. not inside any class) right after require 'active_record', or in a configure block in your app, depending on your preference.


When ActiveRecord creates queries — which are used for both reading and writing, mind you — it will only convert to UTC times that are instances of ActiveSupport’s proprietary TimeWithZone class. It will not convert regular Ruby Time objects, even though Time objects are perfectly aware of their time zones, and AR is perfectly aware that you’d prefer they be written as UTC (due to the default_timezone setting). This is clearly a bug IMHO, but the Rails core marked the bug as “will not fix”, so w/e. Here’s a monkey patch, courtesy of Peter Marklund:

  module ActiveRecord
    module ConnectionAdapters # :nodoc:
      module Quoting
        # Convert dates and times to UTC so that the following two will be equivalent:
        # Event.all(:conditions => ["start_time > ?", Time.zone.now])
        # Event.all(:conditions => ["start_time > ?", Time.now])
        def quoted_date(value)
          value.respond_to?(:utc) ? value.utc.to_s(:db) : value.to_s(:db)
        end
      end
    end
  end

When outputting timestamps to a UI — either inside HTML or in a JSON API — you’ll probably want to use Time#strftime. Beware: on Mac OS X under Ruby 1.8, the %z (lowercase Z) selector will emit the local time zone, not the zone of the Time object you’ve called strftime on. The solution is to either use %Z (capital Z) or just a plain Z which stands for Zulu Time. The latter is OK if you know you’re using UTC, which, if you’ve followed my advice, you probably do. This is a pretty annoying issue, since it’s much safer to use %z‘s hour offsets than %Z‘s three-letter codes, since the three-letter codes can be ambiguous, and in any case require an extra conversion to time offset, so you may as well just emit the offset.

Here are some methods on Time you may want to use that work around this %z issue:

  # Note: do NOT call this file 'time.rb' :-D

  require 'time'

  class Time
    def full_date_and_time
      strftime('%Y-%m-%d %H:%M:%S %Z')
    end

    def iso8601
      strftime('%Y-%m-%dT%H:%M:%SZ') # the final "Z" means "Zulu time" which is ok since we're now doing all times in UTC
    end
  end

That iso8601 method comes in really handy when you’re using the excellent timeago jQuery plugin by Ryan McGeary (@rmm5t).


By default PostgreSQL saves timestamps sans time zone, which means that ActiveRecord interprets them as being in the default_timezone. If you want to be extra clear and save them with time zone, you’ll have to change the Postgres adapter’s type mapping. ActiveRecord doesn’t let you configure this but here’s a monkey patch, courtesy of
Chirag Patel (with a couple of mods):

    require 'active_record/connection_adapters/postgresql_adapter'
    class ActiveRecord::ConnectionAdapters::PostgreSQLAdapter < ActiveRecord::ConnectionAdapters::AbstractAdapter
      def native_database_types
        {
          :primary_key => "serial primary key".freeze,
          :string      => { :name => "character varying", :limit => 255 },
          :text        => { :name => "text" },
          :integer     => { :name => "integer" },
          :float       => { :name => "float" },
          :decimal     => { :name => "decimal" },
          :datetime    => { :name => "timestamp with time zone" },
          :timestamp   => { :name => "timestamp with time zone" },
          :time        => { :name => "time" },
          :date        => { :name => "date" },
          :binary      => { :name => "bytea" },
          :boolean     => { :name => "boolean" }
        }
      end
    end

It turned out that I didn’t need this, so I ended up commenting it out. It may be that storing timestamps with time zones will cause a hiccup with some other random DB code, so watch out. If you do use it, and you’ve already got some data, make sure to write a migration that changes the types of all extant datetime and timestamp fields, and maybe a migration that shifts the times too.


That’s all I’ve got for right now. I’m sure some more problems will come up on March 14, 2010…

  • 0 Shares
  • Share on Facebook
  • Share on Twitter

annotate 2.4.0 released

Alex Chaffee
Sunday, December 13, 2009

Remember the annotate_models rake task? Dave Thomas wrote it many years ago and it corrects one of the flaws in ActiveRecord: it describes the schema for a table as a comment inside the Ruby model file that it maps to. Unfortunately Dave hasn’t had time to maintain it, so a couple of years ago I cleaned up some bugs and re-published it as a pastie. Then Cuong Tran made it a gem and put it on Github, and since then, there’s been a whole lotta forkin’ goin’ on!

I recently pulled in a bunch of the forks into ctran’s master branch, and just pushed it to Gemcutter as version 2.4.0. Just run gem sources and make sure http://gemcutter.org is in your list — otherwise do gem source -a http://gemcutter.org — and sudo gem install annotate and it’ll install a binary called annotate in /usr/bin. See the README on github for more info and have fun!

One caveat: ImageMagick installs a tool called annotate too (if you’re using MacPorts it’s in /opt/local/bin/annotate). So if you see

Usage: annotate imagein.jpg imageout.jpg

then put /usr/bin ahead on the path and you’ll get ours instead.

  • 0 Shares
  • Share on Facebook
  • Share on Twitter

Why Wouldn't You Use Erector?

Alex Chaffee
Thursday, October 8, 2009

No, seriously. Why wouldn’t you use Erector? Cause I think it’s a pretty awesome view framework, but for some reason it hasn’t caught fire yet. So if you think writing actual Ruby to emit HTML, with a clean, nestable syntax with full support for Ruby features like inheritance, delegation, and yield is neat, but there’s something holding you back, then please let us know what it is. At best we can fix it, and at worst, at least we’ll know why.

Here are some reasons I think you might not use Erector:

You love angle brackets. If this is the case then I can’t help you. I don’t think anybody can.

You like typing every tag name twice. Since Erector elements are Ruby statements, every open tag gets automatically closed.

You like invalid HTML. Since Erector elements are Ruby statements, every open tag gets automatically closed. (See how that works?)

You always remember to call ‘h’. Rails 3.0 is going to HTML-escape all output by default. Erector’s been doing this the whole time. Cause, you know, why wouldn’t you?

You like having to rewrite your code when you extract a partial, and then again when you extract a helper method. In ERB, templates, partials, and helpers all have slightly (and annoyingly) different syntax for things like referring to variables and calling other code. Erector is all Ruby, so you can use your favorite refactoring browser, or just cut and paste, to move your code around. Check out this excerpt from Jeff Dean’s RailsConf talk to see this in action, or read the slides from the whole talk on SlideShare.

You hate encapsulation. You think that your views should have direct access to all the instance variables of your controller. Unless they’re partials, in which case you shouldn’t, even though you can, although the names might be different. Confused yet? So am I.

You like putting code for one component in three separate files. Erector’s new “externals” feature allows you to put all the code — HTML, CSS, and JavaScript — inside a single Ruby class. The CSS and JavaScript then get output inside the HEAD, once per HTML page, while the HTML gets rendered in the BODY as usual, as many times as necessary. This follows the OO paradigm of cohesion, otherwise known as “put similar stuff together,” which is the complement of loose coupling, which means, “keep different stuff apart.”


Okay, so those were sarcastic reasons. Here are some more possible reasons why you wouldn’t use Erector. I suspect that these next ones hit closer to the mark. But I believe that they’re all specious, if not downright false.

Your site contains a whole lot of complex HTML and a few inserted Ruby variables. OK, this makes sense. Erector’s not great for static sites. But I’ve never personally worked on a web application where the code inside the views didn’t quickly get complex enough to require codey things like loops and functions. And if you’re writing code, then why not do it in a programming language?

Your designers don’t know Ruby. I’ve heard this complaint a lot, but I have yet to meet this mythical designer who’s smart enough to understand modern HTML, CSS, JavaScript, ERB, and partials, but is not smart enough to learn that “div ‘foo’, :class=>’bar’” outputs “<div class=’bar’>foo</div>”. On the contrary, I’ve worked with several designers who, after a few tutorial pairing sessions, were comfortable checking code in and out and editing Erector view code at will. Like any junior coder, they need to stay away from the tough stuff, but they’re pretty good at knowing what they don’t know and asking for help when they need it. (Which they would also do if working inside ERB.)

View code needs to look as similar to HTML as possible. Well, I hear this, but have you looked at HAML? That language is hella popular, and it doesn’t look anything like HTML. Its structure is similar, in the abstract, but so’s Erector’s, and at least in Erector the method for emitting a div is called, you know, “div”. And it’s a method. And I don’t want to turn this into a war between HAML and Erector — I think HAML is gorgeous — but HAML suffers from the same design flaw as every templating technology: views are not objects, and markup isn’t code. After a certain point of complexity, HAML’s elegance breaks down and you’d be better off doing loops and functions in code.

You’ve already got a bunch of stuff in ERB and it’d take too long to convert it. Yes, legacy code is a pain, but we have a command-line tool that converts ERB (or HTML) to Erector to make it a bit smoother. And you don’t have to convert your whole app to Erector at once. Erector views can interoperate with ERB or HAML in Rails and Sinatra.

You’re stuck on an old version of Erector. Yes, legacy code is a pain, but we have an upgrade guide for getting to 0.6.0, and people on the mailing list ready to help.

Erector’s too slow. Lies! Erector is faster than a greased rattlesnake going downhill. Check out these benchmarking results. Erector is about 2x as fast as ERB and 4x as fast as HAML about the same speed as ERB and HAML(*) under typical conditions. We make sure to use the same output stream to minimize string copy or realloc, and using Ruby objects means much lower parsing overhead.

(*) Update: the “2x/4x” figure was based on a benchmark program that didn’t use template caching, which speeds things up for both ERB and Haml. With template caching, Erector and Haml are about the same speed; Haml is about 20% faster when rendering a page with no partials. See this ongoing thread on the Erector list.

There’s no documentation. More lies! We have a whole bunch of documentation at http://erector.rubyforge.org, including a FAQ and a user guide.

You got burned by Markaby. Underneath the elegant facade of Markaby lay a confusing and often counter-intuitive engine. Its use of instance_eval and other tricks made simple things break in weird ways and made debugging a real chore. Erector was born out of those frustrations, and one of its main design goals is “no magic.” Also, there was a long time where Markaby wasn’t being maintained (although that’s changed recently); we have a core group of developers committed to responding on the mailing list and github, and we run integration tests against the latest stable Rails release (and soon, against Edge) to catch incompatibilities early on.

Rails has all these great helpers and I want to keep using them. Okay, go right ahead! Erector’s Rails integration allows you to call any helper, either directly through a proxy method, or indirectly through the helpers object. If you find a helper that doesn’t work, let us know and we’ll add it to the list of supported helpers. (We haven’t done all of them yet because it’s a pain in the neck to look at each function and figure out what its input and output semantics are. Does it return a string or emit directly onto the output stream? Does it take a block? An options hash? An html_options hash? Etc.) We’re also slowly putting some Rails functionality into Erector, either in the base class or in custom widgets. If there’s something you need, ask on the mailing list, or better yet, send us a patch.

Its name is a dirty word. I’ve heard this more from people who didn’t grow up in the United States, where the Erector Set was a popular toy among the 6-to-12-year-old DIY set in the 70s and 80s. (Apparently it was called Meccano in the UK.)
Erector is a normal word, used all the time in the news and in business names. And as the name of a view library it’s evocative in a way that’s relevant and interesting, in that it’s a builder, and you build a view up out of parts.

But we have heard this complaint, and in sympathy, changed the name of the command-line tool (oh, sorry, guess I can’t say “tool” either)– uh, executable– from “erect” to “erector” even though the former is a venerable English verb that’s grammatically appropriate (”I asked him to erect the scaffolding.”). If you introduce the library and your coworkers get all giggly then I think if you just say the name with a straight face and then roll your eyes and mock your bawdy buddies when they snicker then all will be well. After a few repetitions it won’t sound odd at all.

You’ve never heard of it. Help spread the word! Post a review on your blog! Ask your favorite app framework whether they support it! Post code samples in Erector and when people say “What’s that?” then point them at http://erector.rubyforge.org! Give a talk at a meetup! Write your congressman and ask if she supports the Erector Mandate Bill of 2009! Buy ad space on the moon!


So, in conclusion, and despite my somewhat snarky tone throughout, I am honestly and desperately curious to know why the world has not yet beat a path to Erector’s door. Anybody got any more ideas?

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

Take a Looksee at how a Ruby Object got its Methods

Pivotal Labs
Monday, July 27, 2009

One property of the Ruby object model and object oriented programming in general is that a subclass of an object automatically inherits all of the methods of its superclass. Classes can further expand the number of methods available by mixing in a Module, or several.

Because of mixins and subclassing even a class that has declared just a few methods can actually have hundreds of methods on it. In Ruby, all classes subclass Object by default which declares a hefty 45 methods, guaranteeing you to have at least that many. Out of the box in 1.8.7, a Ruby String object has 176 instance methods. If you are programming on top of the Rails framework, ActiveSupport adds 98 methods bringing the total to 274!

On numerous occasions I have needed to see what methods are available on an object I am working with I will type the following in irb.

myobject.methods - Object.instance_methods

This prints out a large array of instance methods with the methods inherited from Object removed from the list. This is useful but what if the object I am working with mixed in several modules and I am left with a list of over a hundred methods? It would be great to view which Class or Module each method came from. Well, actually there’s a gem for that.™

Looksee

Looksee is a new gem by George Ogata that examines the method lookup path of any object. To use it add require 'looksee/shortcuts' to your ~/.irbrc. This will add a lp (”lookup path”) method to your irb environment. When passed an object lp prints out a colored display showing where each of an object’s methods lives.

looksee output for a string object

  • public methods are show in green
  • protected methods are show in yellow
  • private methods are show in red
  • overwritten methods are show in gray

Go ahead and install Looksee and play around with it for a moment. Run lp on a String in vanilla irb and then open script/console in a Rails project and do the same thing. It is quite eye-opening to see the additions that the Rails framework makes.

  • 0 Shares
  • Share on Facebook
  • Share on Twitter

Topics

  • agile (781)
  • rails (113)
  • testing (88)
  • ruby (83)
  • ruby on rails (70)
  • jobs (62)
  • javascript (55)
  • techtalk (44)
  • rspec (38)
  • ironblogger (32)
  • productivity (30)
  • activerecord (29)
  • gogaruco (29)
  • git (28)
  • nyc (27)
  • rubymine (26)
  • bloggerdome (23)
  • mobile (22)
  • process (21)
  • pivotal tracker (21)
  • cucumber (20)
  • design (19)
  • jasmine (19)
  • ios (18)
  • webos (17)
  • objective-c (17)
  • android (16)
  • tracker ecosystem (16)
  • palm (16)
  • "soft" ware (16)
  • fun (15)
  • ci (15)
  • cedar (15)
  • rails3 (14)
  • performance (14)
  • bdd (14)
  • gem (13)
  • css (13)
  • tdd (13)
  • selenium (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. ←
  2. 1
  3. 2
  4. 3
  5. 4
  6. 5
  7. 6
  8. 7
  9. 8
  10. 9
  11. →
  • 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 >