Feeds : Pivotal Blabs


      view feed content Standup 11/26/2008: Assorted Incompatibilities (Pivotal Blabs)   4 d and 23 h ago
Interesting Things

The garbage collection bug we encountered on Monday has popped up in new places:

Also, speaking of libxml:

Ask for Help

"Turning off cache-busting for test environment replaces cache-busting junk with ??. Is there a way to make it replace it with nothing instead?"

With cache busting on, you have would have to test like this:

admin_button.should have_tag("a > img[src ='/images/v3/admin/image_name.png?12121212?']")

which is awkward.

We turned it off by adding the following to config/environments/test.rb (google said to do it)

ENV['RAILS_ASSET_ID'] = ''

But, then we had to do this:

admin_button.should have_tag("a > img[src ='/images/v3/admin/image_name.png??']")

Is there a way to turn off cache-busting that doesn't put weird/ugly question marks at the end of your image names?

"with_tag & have_tag don't work in non-controller (e.g. model) rspecs?"

Yes, they don't. Use Hpricot instead. Or maybe assert_elements.



View original post|Add to del.icio.us | Share

      view feed content Tracker 101 Screencast (Pivotal Blabs)   5 d and 13 h ago

If you're new to Tracker, or are considering trying it out but haven't signed up yet, check out the Tracker 101 screencast. Thanks to Ian McFarland for recording it.



View original post|Add to del.icio.us | Share

      view feed content Better View Testing with Elementor (Pivotal Blabs)   6 d and 15 h ago

We've got a few mantras at Pivotal. One of them has to do with testing all the time. It's a Good Thing, for sure. Until recently though, I had always inserted a tacit "except for views" to the end of it. The reason for my reservations wasn't the fact that view tests can be brittle. Any test can be brittle. I didn't like testing views because it seemed like the test I was writing never really described the code I was writing. Let's look at a typical view test to see what I mean:

describe "/posts/index.html.erb" do def render_view render "/posts/index.html.erb" response.body end before(:each) do assigns[:posts] = [ stub_model(Post, :name => "First!", :body => "first body."), stub_model(Post, :name => "Second!", :body => "second body.") ] end describe "assertions using have_tag" do it "renders posts" do render_view response.should have_tag(".post", 2) end it "renders post headers" do render_view response.should have_tag(".post .post-name", "First!", 1) response.should have_tag(".post .post-name", "Second!", 1) end it "renders post bodies" do render_view response.should have_tag(".post .post-body", "first body.", 1) response.should have_tag(".post .post-body", "second body.", 1) end end end

This snippet uses the have_tag helper. It's somewhat slow, and to my eyes, expresses intent about as well as an apple floating in a top-hat filled with perfume. The "tag" is a selector? The content filter is just the second argument? And the last argument is the amount of "tag" the response should have? You can test like this, but why would you?

I've also seen a more manual pattern, using a library like Hpricot or Nokogiri to parse the response body, then asserting on the results of that:

describe "assertions using Nokogiri" do def doc @doc ||= Nokogiri(render_view) end it "renders posts" do doc.search('.post').should have(2).nodes end it "renders post headers" do headers = doc.search('.post .post-name') headers.should have(2).elements headers.detect { |element| element.text == "First!" }.should_not be_nil headers.detect { |element| element.text == "Second!" }.should_not be_nil end it "renders post bodies" do bodies = doc.search('.post .post-name') bodies.should have(2).elements bodies.detect { |element| element.text == "first body." }.should_not be_nil bodies.detect { |element| element.text == "second body." }.should_not be_nil end end

It's faster, since it's not using have_tag, but still not very expressive. CSS selectors are still littered across the it statements, but at least it's only once per test. Still, using detect to find content is no good. And I don't think CSS selectors have any business in it statements at all. That seems like asserting on the name of a method being called, not its behavior.

The solution!

Given my problems with the above approaches, I created a gem that allows the following assertion syntax:

it "renders posts" do result.should have(2).posts end it "renders post headers" do result.should have(2).post_headers result.should have(1).post_header.with_text("First!") result.should have(1).post_header.with_text("Second!") end it "renders post bodies" do result.should have(2).post_bodies result.should have(1).post_body.with_text("first body.") result.should have(1).post_body.with_text("second body.") end

What's a result? And how does it know how many posts, post_headers, and post_bodies it has? The result is defined in a before block like so:

require 'elementor' require 'elementor/spec' include Elementor attr_reader :result before(:each) do @result = elements(:from => :render_view) do |tag| tag.posts ".post" tag.post_headers ".post .post-name" tag.post_bodies ".post .post-body" end end

The elements method allows you to name your CSS selectors using the tag block argument. The tag object uses method_missing to register your names. The :from option specifies a method to be called that will return some raw markup.

Naming selectors alone was a huge win for me, but there are a few other cool bits about the @result object. First, you get to use the with_text helper for filtering content. You'll also get a with_attrs helper for filtering based on a hash of attribute values.

The project is called Elementor, and you can install it like so:

[sudo] gem install elementor

The code is on the GitHub here: github.com/nakajima/elementor (and you can see the CI build here). Take a look at the specs for all of the examples of what you can do. Hopefully, you'll find it as useful as I have. If not, please share your reasons in the comments!



View original post|Add to del.icio.us | Share

      view feed content Hide .svn files in changes view of RubyMine (Pivotal Blabs)   6 d and 19 h ago

You have probably noticed that the changes view is unusable in RubyMine because of all the .svn files showing.

Well if you refresh ( ) the changes view they go away...Hurray!



View original post|Add to del.icio.us | Share

      view feed content Standup 11/24/2008: Changes to GC in Ruby 1.8.6? (Pivotal Blabs)   6 d and 22 h ago
Ask for Help

"Does anyone know about recent changes to Ruby 1.8.6 garbage collection?"

We're seeing a strange test failure on one of our CI boxes:

[BUG] object allocation during garbage collection phase ruby 1.8.6 (2008-08-11) [i686-linux]

ruby -v gives this:

ruby 1.8.6 (2008-08-11 patchlevel 287) [i686-linux]

On the developer's OSX machine, which doesn't experience this bug, ruby -v gives:

ruby 1.8.6 (2008-03-03 patchlevel 114) [universal-darwin9.0]

There have apparently been changes to garbage collection in 1.8.7 and 1.9 -- does anyone know if these have been backported to 1.8.6 somewhere between patchlevels 114 and 287?



View original post|Add to del.icio.us | Share

      view feed content New York Standup 11/24/2008 (Pivotal Blabs)   7 d and 2 h ago
Interesting

View original post|Add to del.icio.us | Share

      view feed content Unicode Transliteration to Ascii (Pivotal Blabs)   7 d and 17 h ago

Matthew O'Connor and I recently worked on a project that sent SMS messages to mobile customers. Unfortunately the SMS aggregator we used on the project rejected messages with non-ascii characters.

One approach we considered was to strip our messages of any characters that were not ascii and send them as is. After looking through some of the rejected messages we realized most of the problems occurred with unicode punctuation. Instead of simple deleting the characters we tried transliterating them to their ascii equivalent.

Our first approach used IConv:

require 'iconv' module SmsEncoder def self.convert(utf8_text) text = Iconv.iconv("US-ASCII//TRANSLIT", "UTF-8", utf8_text).first text.gsub(/`/, "'") rescue Iconv::Failure "" end end

For some reason the backtick ` also caused problems so we converted that after using Iconv.

This approach worked perfectly on OS X but as soon as we moved to the Linux servers the libiconv characteristics changed and most untranslatable characters became question marks instead of empty strings.

Instead of wrestling with libiconv we looked for a solution entirely in ruby. We found unidecode which got us most of the way there. Unidecode did a little more than we wanted though and translated Chinese and Japanese characters to their approximate sounds. e.g. 今年1月 gets transliterated to Jin Nian 1Yue

We decided to only transliterate extended latin charaters, punctuation and money symbols.

Here is the final code with the unidecode monkey patch:

require 'set' require 'unidecode' module SmsEncoder def self.convert(utf8_text) Unidecoder.decode(utf8_text.to_s).gsub("[?]", "").gsub(/`/, "'").strip end end module Unidecoder class << self def decode(string) string.gsub(/[^\x20-\x7e]/u) do |character| codepoint = character.unpack("U").first if should_transliterate?(codepoint) CODEPOINTS[code_group(character)][grouped_point(character)] rescue "" else "" end end end private # c.f. http://unicode.org/roadmaps/bmp/ CODE_POINT_RANGES = { :basic_latin => Set.new(32 .. 126), :latin1_supplement => Set.new(160 .. 255), :latin1_extended_a => Set.new(256 .. 383), :latin1_extended_b => Set.new(384 .. 591), :general_punctuation => Set.new(8192 .. 8303), :currency_symbols => Set.new(8352 .. 8399), } def should_transliterate?(codepoint) @all_ranges ||= CODE_POINT_RANGES.values.sum @all_ranges.include? codepoint end end end

and tests:

class SmsEncoderTest < Test::Unit::TestCase def test_transliteration_of_blank assert_equal "", SmsEncoder.convert(nil) assert_equal "", SmsEncoder.convert("") end def test_transliteration_of_whitespace assert_equal "", SmsEncoder.convert(" \t\n") end def test_transliteration_of_text_surrounded_by_space assert_equal "abc", SmsEncoder.convert(" abc ") end def test_transliteration_of_ascii orig_text = "!\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~" conv_text = SmsEncoder.convert(orig_text) assert_equal orig_text.gsub(/`/, "'"), conv_text end def test_transliteration_of_unicode_punctuation utf8_text = "“foo” ‹foo› ‘foo’ ,foo, –foo— {foo} (foo) `foo`" ascii_text = SmsEncoder.convert(utf8_text) assert_equal "\"foo\" <foo> 'foo' ,foo, foo-- {foo} (foo) 'foo'", ascii_text end def test_transliteration_of_common_latin1_characters utf8_text = "ñ ò ^ ¡ ¿ Æ æ ß Ç §" ascii_text = SmsEncoder.convert(utf8_text) assert_equal "n o ^ ! ? AE ae ss C SS", ascii_text end def test_transliteration_of_money_characters utf8_text = "€ £ $ ¥" ascii_text = SmsEncoder.convert(utf8_text) assert_equal "EU PS $ Y=", ascii_text end def test_untransliterable_characters utf8_text = "ɏ \x1f \x01 \x00 Ʌ \x7f" ascii_text = SmsEncoder.convert(utf8_text) assert_equal "", ascii_text end def test_transliteration_of_chinese_characters utf8_text = "ウェブ全体から検索" ascii_text = SmsEncoder.convert(utf8_text) assert_equal "", ascii_text end end

View original post|Add to del.icio.us | Share

      view feed content Standup 11/21/2008: Pro Bono Airwaves (Pivotal Blabs)   9 d and 17 h ago
Interesting Things Ask for Help

"How do you get Selenium to work with Firefox 3?"

If you know how, pull the jar files out of a later release and use those. Good luck!



View original post|Add to del.icio.us | Share

      view feed content Why I test. (Pivotal Blabs)   10 d and 11 h ago

This is a cross post from my personal blog, because I'd like to hear from other Pivots about why they test.

First about unit and integration tests.

Then about interaction and state based testing.

So, now it's your turn - why do you test?



View original post|Add to del.icio.us | Share

      view feed content Standup 11/20/2008: Engine Yard ssh key changes (Pivotal Blabs)   10 d and 16 h ago
Interesting Things

View original post|Add to del.icio.us | Share

      view feed content Standup 11/19/2008: Team Strength, Fixtures, and Pivot Pong (Pivotal Blabs)   11 d and 16 h ago
Interesting Things Ask for Help

"What is the life-cycle of test fixtures when using transactional fixtures?"

  1. The testing framework clears the database of all data within tables that have fixtures files defined.
  2. A test/spec file is loaded and all fixtures declared within it (or all if fixtures :all is declared) are loaded into the database.
  3. A transaction is started.
  4. The test/spec runs.
  5. The transaction is rolled-back.
  6. Repeat!


View original post|Add to del.icio.us | Share

      view feed content Standup 11/18/2008: Unbelievable has_many :through Gotcha (Pivotal Blabs)   12 d and 17 h ago


View original post|Add to del.icio.us | Share

      view feed content Notes on Google Chrome Compatiblity (Pivotal Blabs)   12 d and 18 h ago

Pivot Jonathan and I were recently working on support for Google Chrome in Pivotal Tracker. Tracker's extensive JsUnit test suite made this a lot easier.

Here's some quick notes I took on the issues we ran into.

Don't try to directly mock the 'reset' method on a Form Element

This was the original mocking code in one of our JsUnit tests:

var resetCalled = false; widget._uploadForm.reset = function() { resetCalled = true; };

This permanently blew away the "reset" method, so it was undefined when called in a subsequent. To fix it, we did this in our form builder method:

var element = Element.create("form"); element.nativeReset = element.reset; element.reset = function() { element.nativeReset() }; Hash keys sort differently

We had a testHash.keys() being compared to a hardcoded array. Chrome sorted the keys differently (apparently non-deterministically, so we had to do an explicit sort:

assertArrayEquals(['10001', '10002', '10003', 'endOfList'].sort(), $H(itemListWidget.draggables).keys().sort());

It wasn't good to depend on the keys order in the first place, but it worked under IE, Firefox, and Safari.

The same hash sorting bug bit us in a much more obscure way. There was some threading test code that simulated timeouts/concurrency using a mock clock. Previously, the test code was dependent on the order in which the functions were added to a hash the mock "clock". This broke with a different hash sorting order. We had to simulate some additional "ticks" to make the test pass.

Mozilla, but not Gecko

The browser string returned for Chrome by one of our utility functions, BrowserDetect.browser(), is "Mozilla". However, for some of our simulated keypress events in tests, the "Gecko" version did not work.

Specifically, we had to use "KeyboardEvent" instead of "KeyEvents", and "initKeyboardEvent" instead of "initKeyEvent". See the table in this mozilla doc page.

Here's the code we used to handle both cases:

evt = document.createEvent('KeyboardEvent'); if (typeof(evt.initKeyboardEvent) != 'undefined') { evt.initKeyboardEvent(eventName, true, true, window, false, false, false, false, options.keyCode, options.keyCode); } else { evt.initKeyEvent(eventName, true, true, window, false, false, false, false, options.keyCode, options.keyCode); }

The UserAgent (request.user_agent) returns

Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US) AppleWebKit/525.19 (KHTML, like Gecko) Chrome/0.3.154.9 Safari/525.19 The 'sort' function does not preserve order of equivalent elements

The following page outputs 'ACBD' under Chrome:

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html> <body> <a href="#" onclick="alert(doSort()); return false;">Sort</a> <script type="text/javascript"> function doSort() { var myArray = [ {id: "A", sortVal: 0}, {id: "B", sortVal: 1}, {id: "C", sortVal: 1}, {id: "D", sortVal: 2} ]; var sorted = myArray.sort(function(a,b) {return a.sortVal - b.sortVal}); return sorted[0].id + sorted[1].id + sorted[2].id + sorted[3].id; } </script> </body> </html>

View original post|Add to del.icio.us | Share

      view feed content Standup 11/17/2008: Google Chrome Gotchas (Pivotal Blabs)   13 d and 18 h ago
Interesting Things

View original post|Add to del.icio.us | Share

      view feed content Why is the sky blue? When does the wind blow? Why do tests fail? (Pivotal Blabs)   13 d and 20 h ago

Here's an interesting mental exercise that recently I've found more and more valuable:

  1. Test drive your code (duh).
  2. Before each time you run your tests, no matter how small the changes you've made, ask yourself why the tests will fail. Don't just gloss over this; be explicit. Say it out loud or write it down, if that helps. If you have a pair, tell your pair.

You might be surprised how often your assumptions turn out wrong. And, you might be surprised what you learn when you explicitly state those assumptions and then have to justify them when they do turn out wrong.

If you don't test drive, or you don't always test drive, (and you're still reading), ask yourself this: what happens those times when my assumptions are wrong and I don't have tests to protect me?



View original post|Add to del.icio.us | Share

      view feed content Volatility: it's not just for sublimation any more (Pivotal Blabs)   14 d and 20 h ago

Multithreaded programming was a hot topic at RubyConf this year, and a common theme in many talks was the use of functional languages to prevent contention between threads. This totally makes sense to me, to the limited extent that I can wrap my head around truly functional programming, and I'm sure it's an excellent approach. However, imagine a case in which we can't just drop in a new language, so we need to write some multithreaded code in Ruby. I'm sure you won't have to think too long or hard.

Now, one point several speakers at RubyConf made that I would like to reiterate is this: multithreaded programming is difficult. Gosh darn difficult. People who write software tend to thrive on determinism and linearity. After all, computers always do what we tell them to, right? They don't make mistakes or change their minds; not like those silly, silly humans. But now big, bad concurrent programming comes along and suddenly computers can come up with different answers depending on, oh, the alignment of the planets. Chaos.

So, functional programming languages aside for the moment, what tools do we have to rein in the inevitable entropy that will, more than likely, eventually bring the planets into alignment against us?

Several years ago Andrei Alexandrescu wrote this excellent article on how to use the C++ type system (stick with me, it's all Ruby after this paragraph) to automatically prevent race conditions at compile time. I recommend you read it; it's quite short. Now, however you feel about static typing, you must admit that the approach he describes is a beautiful use of the expressiveness of the C++ type system. The question is, can we do something analogous in Ruby?

First off, lets start with some thread-unsafe code, similar to what Jim Weirich used in his talk on threads at RubyConf:

account = Account.new threads = [] 1000.times do |i| threads << Thread.new(account) do |account| account.credit(1) end end threads.each { |thread| thread.join } puts account.balance

This code results in an account balance somewhere between 1 and 1,000. The exact value depends, of course, on the planets.

Now, to make this thread-safe. I came up with a few attempts using #alias_method and #undef_method, but didn't find anything satisfying. After that, I figured I'd try a simple proxy to approximate the effect. Here's a first cut:

class VolatileProxy attr_reader :obj def initialize(obj) @obj = obj end def method_missing(method, *args) raise "Unsynchronized message '#{method}' sent to volatile object" end end def volatile(obj) VolatileProxy.new(obj) end def locked_scope(volatile, mutex) mutex.synchronize do yield(volatile.obj) end end

Now, calls to methods on objects you declare as volatile (shared across threads) will fail messily unless you use them within a locked_scope. To make this work the example code now becomes:

mutex = Mutex.new account = volatile Account.new threads = [] 1000.times do |i| threads << Thread.new do locked_scope(account, mutex) { |safe_account| safe_account.credit(1) } end end threads.each { |thread| thread.join } puts account.balance

This example has some issues, namely:

I really like the idea of using blocks to scope behavior like this. This particular example doesn't feel particularly clean to me yet, but hopefully it will give some people something to think about. If you have a better approach, please don't be afraid to shout it out.



View original post|Add to del.icio.us | Share

      view feed content Standup 11/14/2008: XXL Mongrels and Non-Model Reports (Pivotal Blabs)   16 d and 15 h ago
Interesting Things Ask for Help

"How big should a typical mongrel be? Ours is starting out at over 200 megs but is not leaking from that point."

Everyone agreed that 50MB to 70MB is standard and anything over 100MB is considered pretty big. People suggested RubyProf for inspecting object counts and possibly tracking down the memory hogging code.

"What pattern does everyone use for non-model Reports with ActiveRecord? We are trying to create a report that counts a single model and groups by two associated models"

There was consensus around modeling a distinct report object and calling the referenced models. For example, FooReport and FooReportController fit nicely in a RESTful Rails world.



View original post|Add to del.icio.us | Share

      view feed content Pattern for Functional Testing (Pivotal Blabs)   17 d and 0 h ago

Regular Selenium tests (in Java) might look like:

selenium.open("/login"); selenium.type("id=username", "bob"); selenium.type("id=password", "password"); selenium.click("Login"); selenium.waitForPageToLoad(); selenium.click("My Account"); selenium.waitForPageToLoad(); assertEquals("bob", selenium.getText("//table[2]/tr[3]/td[2]/");

After a few tests, this kind of thing becomes painful to manage. The typical solution is to create a bunch of constants for IDs and Xpaths, but that doesn't help too much.

Fellow Pivot Mike Grafton came up with a cool pattern for improving on this. The idea is to create a class representing each page of your web app. Each class contains two types of methods: a bunch of action methods (clickMyAccountLink(), typeUsername()), and a bunch of inspection commands (isLoginButtonEnabled(), getLoggedInUsername()).

When an action takes you to a new page, the corresponding action method returns a new class representing that page. When it stays on the same page, the method just returns "this". This allows methods to be chained to make the tests more readable.

Here's how that test would look using this new pattern:

MyAccountPage myAccountPage = new LoginPage(selenium) .typeUsername("bob") .typePassword("password") .clickLoginButton() .clickMyAccountLink(); assertEquals("bob", myAccountPage.getLoggedInUsername());

The constructor of each page class should validate that it's on the correct page (waiting if necessary, and perhaps asserting on the page title).



View original post|Add to del.icio.us | Share

      view feed content Standup 11/13/2008: ActiveScaffold and Object Mothers (Pivotal Blabs)   17 d and 15 h ago
Interesting Things Ask for Help

"What are your current favorite Object Mother implementations or patterns?"

There are several approaches:

"Does anyone know how to disable caching in Safari? Caching can often break JSUnit between test runs"

Go to Develop -> Disable Caches and you get a fresh non-caching Safari.



View original post|Add to del.icio.us | Share

      view feed content Pivotal Tracker Fluid Icon (Pivotal Blabs)   17 d and 21 h ago

Here's a hot Fluid icon for Pivotal Tracker. Thanks, Ted!

Check out a couple of other icons in this Flickr upload.



View original post|Add to del.icio.us | Share

      view feed content Standup 11/12/2008: JSON2.js borked? (Pivotal Blabs)   18 d and 16 h ago
Interesting Things Ask for Help

"We were having problems when mocking an ActiveRecord association under Mocha when we called expects on a method that calls a method."

The solution was basically to not mock associations.

"Mod_rewrite + SSL was causing problems when redirecting to a subdomain behind SSL."

A wild-card SSL certificate solves the problem.



View original post|Add to del.icio.us | Share

      view feed content Standup 11/11/2008: Firefoxen goodness (Pivotal Blabs)   18 d and 16 h ago
Interesting Things Ask for Help

"As a followup to Firefox SSL certificate problems..."

It turns out that our server running nginx had an old version of OpenSSL installed. Upgrading OpenSSL solved the problem.



View original post|Add to del.icio.us | Share

      view feed content Standup 11/10/2008: Memory profiling tools for Ruby (Pivotal Blabs)   18 d and 16 h ago
Interesting Things Ask for Help

"We're having an issue with a long running Ruby process consuming too much memory and failing. What tools are available for finding and patching Ruby memory leaks?"

Several tools were suggested:

"Rake will often silently 'fail' when running RSpec. It will not blow up but rather silently quits in the middle of the suite. This seems to happen intermittently, usually on the first run of our test suite. If we run the suite again, it works."

It was suggested that this might be a Rake version issue since there have been other test suite problems with Rake 0.8.3. Though, this particular type of problem was not identical to previous Rake versioning issues and may be something altogether different.

Keep reading for a more detailed description of this weird RSpec + Rake issue.

More on the RSpec + Rake issue:

"It always manages to go through the integration tests, but when it hits the main tests, it will randomly quit (without a failure or error message) before all the tests are complete. At this point it'll give us a summary message (X tests run, X tests passed) as if no other tests exist. We've worked on the problem a little bit this morning and tried the following things, all without success: >1) upgraded to the latest version of rspec and rspec-rails (1.1.11) 2) downgraded from rake 0.8.3 to 0.8.1 3) tried running with rspec and rspec-rails gems only 4) tried running with rspec and rspec-rails plugins only.

We've tried it on another machine with similar results. Right now, I want to say it only happens when we've modified a file in the project, but that may be confirmation bias (we ran about 60 full rakes on one machine where we have not been mucking about in the codebase and it seems to have successfully run all of them).

There was one other mention of this online in this ticket: http://rspec.lighthouseapp.com/projects/5645/tickets/587-conflict-with-loadby-and-reverse#ticket-587-3, paraphrased below:

'This was caused by an error in handling a certain mal-formed spec; it was causing rspec to exit silently in the middle of one spec file. As I would edit files, --loadby mtime would cause them to load in different orders, which would then run different #s of examples because it would hit the file, and then quit silently, in different places'

You can close this one, I'll report another bug that's appropriate for the silent-exit-without-exception problem."

Anyways, at this point we're out of ideas and are leaving the problem behind for now, but we'd love to fix it, as it makes testing somewhat unpredictable."



View original post|Add to del.icio.us | Share

      view feed content Tracker: the iPod of project management software? (Pivotal Blabs)   18 d and 19 h ago

Nivi, from Venture Hacks, wrote a great article about why Pivotal Tracker is great for startups. It's worth reading even if you're already a fan of Tracker, and nails down the key ingredients to successful project management. Check it out:

http://venturehacks.com/articles/pivotal-tracker



View original post|Add to del.icio.us | Share

      view feed content Functional witness protection (Pivotal Blabs)   19 d and 18 h ago

I wrote a bit about function objects here. However, if you don't buy that the persistent state of function objects provides something that anonymous functions cannot, how about this: readability. In some cases.

Anonymous functions are boss and cool, and extremely common in idiomatic Ruby. However, in some cases they can get a little... esoteric. Consider:

people.sort do |lhs, rhs| lhs, rhs = rhs, lhs if ascending? result = lhs.name <=> rhs.name if result == 0 result = lhs.date_of_birth <=> rhs.date_of_birth end # etc... end

Sometimes, anonymity isn't the answer. Consider:

class ByNameAscending def self.to_proc Proc.new { |lhs, rhs| rhs.name <=> lhs.name } end end

This allows you to write this:

people.sort(&ByNameAscending)

Or, to push the example to the extreme:

class SortOrder def initialize(direction = :descending) @direction = direction end def by(attribute) attributes << attribute self end alias_method :and, :by def to_proc Proc.new do |lhs, rhs| lhs, rhs = rhs, lhs if ascending? return lhs <=> rhs if attributes.empty? attributes.each do |attribute| result = lhs.send(attribute) <=> rhs.send(attribute) return result if result != 0 end 0 end end private def attributes @attributes ||= [] end def ascending? @direction == :ascending end end def ascending; SortOrder.new(:ascending); end

Which gives us:

people.sort(&ascending.by(:name).and(:date_of_birth))

A DSL for generating sort order function objects. It could be useful.



View original post|Add to del.icio.us | Share

      view feed content Give up the func (Pivotal Blabs)   20 d and 18 h ago

I've been a C++ developer ever since I discovered the language in the early 90's and I realized that my beloved Pascal had nothing on objects. I've spent plenty of time working with other languages, of course, and over the past year or so I've written almost exclusively Ruby. But, one thing I've missed about C++ is the ease with which you can make objects act like functions.

In case your C++ is a little rusty, here's an example:

class Fibonacci { public: Fibonacci(): n1_(1), n2_(1) {} int operator()() { int result = n1_; n1_ = n2_; n2_ = result + n2_; return result; } private: int n1_, n2_; };

What you're looking at there is an overload of the function call operator. No, I'm not kidding; that will compile and run. Instances of the Fibonacci class are called function objects, or functors.

Now, you're wondering to yourself why anyone would care. The answer is, this function can now carry state around with it:

Fibonacci fibonacci; fibonacci(); // 1 fibonacci(); // 1 fibonacci(); // 2 Fibonacci()(); // 1 vector<int> v(5); generate(v.begin(), v.end(), Fibonnaci()); // [1, 1, 2, 3, 5] generate(v.begin(), v.end(), fibonnaci); // [3, 5, 8, 13, 21]

This may not seem particularly compelling for generating Fibonnaci numbers, but consider generators that may carry more complex state, or references to state owned by other objects. Consumers can also set initial state, such as a seed value for a random number generator, via the ctor.

Also, consider the generate method above. It expects a third parameter that supports function call semantics with arity of zero. And nothing else. That parameter could be a function pointer (should you desire statelessness and impenetrable syntax), a functor of any type, or anything else that supports operator (). That's duck-typing, my friends. In a statically-typed language. Dogs and cats sleeping together, and all that.

Again, you cry, why would anyone care? Well, blocks in Ruby carry around the state of the context in which they were created, but sometimes you want more. For instance, if you pass your Proc object around your code may be clearer with the state explicitly encapsulated. The initial state may simply not make sense as local variables when you create the Proc. You may want to save some secondary value that a consumer can query the functor for (how many Fibonacci numbers has this generator generated). Or, perhaps you want consumers to be able to mutate the state in some way.

In any case, this functor approach wacked me over the head recently while I was looking at some code that used the Rails Symbol#to_proc. We all know that Rails adds voodoo to symbols so that

User.find(:all).collect(&:name)

is equivalent to

User.find(:all).collect { |u| u.name }

And, we all know that this works because the & operator, when applied to an object in a parameter list, will implicitly call #to_proc on that object and then convert the result to a block. This is vanilla Ruby functionality, Rails just adds #to_proc to the Symbol class.

So, duh. Check it out:

class Fibonacci def initialize @n1 = @n2 = 1 end def to_proc @proc ||= Proc.new do result = @n1 @n1, @n2 = @n2, @n1 + @n2 result end end end fibonacci = Fibonacci.new fibonacci.call # 1 fibonacci.call # 1 fibonacci.call # 2 Fibonacci.new.call # 1 (1..5).collect(&Fibonacci.new) # [1, 1, 2, 3, 5] (1..5).collect(&fibonacci) # [3, 5, 8, 13, 21]

Voilà, a functor. I'd love to hear from anyone who has used this technique to do something really cool.



View original post|Add to del.icio.us | Share

      view feed content Give up the func (Pivotal Blabs)   20 d and 18 h ago

I've been a C++ developer ever since I discovered the language in the early 90's and I realized that my beloved Pascal had nothing on objects. I've spent plenty of time working with other languages, of course, and over the past year or so I've written almost exclusively Ruby. But, one thing I've missed about C++ is the ease with which you can make objects act like functions.

In case your C++ is a little rusty, here's an example:

class Fibonacci { public: Fibonacci(): n1_(1), n2_(1) {} int operator()() { int result = n1_; n1_ = n2_; n2_ = result + n2_; return result; } private: int n1_, n2_; };

What you're looking at there is an overload of the function call operator. No, I'm not kidding; that will compile and run. Instances of the Fibonacci class are called function objects, or functors.

Now, you're wondering to yourself why anyone would care. The answer is, this function can now carry state around with it:

Fibonacci fibonacci; fibonacci(); // 1 fibonacci(); // 1 fibonacci(); // 2 Fibonacci()(); // 1 vector<int> v(5); generate(v.begin(), v.end(), Fibonnaci()); // [1, 1, 2, 3, 5] generate(v.begin(), v.end(), fibonnaci); // [3, 5, 8, 13, 21]

This may not seem particularly compelling for generating Fibonnaci numbers, but consider generators that may carry more complex state, or references to state owned by other objects. Consumers can also set initial state, such as a seed value for a random number generator, via the ctor.

Also, consider the generate method above. It expects a third parameter that supports function call semantics with arity of zero. And nothing else. That parameter could be a function pointer (should you desire statelessness and impenetrable syntax), a functor of any type, or anything else that supports operator (). That's duck-typing, my friends. In a statically-typed language. Dogs and cats sleeping together, and all that.

Again, you cry, why would anyone care? Well, blocks in Ruby carry around the state of the context in which they were created, but sometimes you want more. For instance, if you pass your Proc object around your code may be clearer with the state explicitly encapsulated. The initial state may simply not make sense as local variables when you create the Proc. You may want to save some secondary value that a consumer can query the functor for (how many Fibonacci numbers has this generator generated). Or, perhaps you want consumers to be able to mutate the state in some way.

In any case, this functor approach wacked me over the head recently while I was looking at some code that used the Rails Symbol#to_proc. We all know that Rails adds voodoo to symbols so that

User.find(:all).collect(&:name)

is equivalent to

User.find(:all).collect { |u| u.name }

And, we all know that this works because the & operator, when applied to an object in a parameter list, will implicitly call #to_proc on that object and then convert the result to a block. This is vanilla Ruby functionality, Rails just adds #to_proc to the Symbol class.

So, duh. Check it out:

class Fibonacci def initialize @n1 = @n2 = 1 end def to_proc @proc ||= Proc.new do result = @n1 @n1, @n2 = @n2, @n1 + @n2 result end end end fibonacci = Fibonacci.new fibonacci.call # 1 fibonacci.call # 1 fibonacci.call # 2 Fibonacci.new.call # 1 (1..5).collect(&Fibonacci.new) # [1, 1, 2, 3, 5] (1..5).collect(&fibonacci) # [3, 5, 8, 13, 21]

Voilà, a functor. I'd love to hear from anyone who has used this technique to do something really cool.



View original post|Add to del.icio.us | Share

      view feed content Standup 11/07/2008: Selenium for Flash (Pivotal Blabs)   24 d and 0 h ago
Interesting Things Ask for Help

"I want to create a custom launcher for Firefox 2 and Firefox 3 with different profiles. Perhaps the real question is how do we create a custom version of a Mac application launcher, passing in the arguments we need?"

... without having to invoke it on the command line every time.

"We're trying to delete cookies in our Controller, but they keep appearing in the headers anyway."

Suggestion: make sure you are specifying your URL paths and domains correctly.

"Why won't our CSS and other assets load the first time when accessing an SSL-protected domain on Engine Yard?"

It's most likely not Engine Yard or Firefox 3's fault. More research needed.



View original post|Add to del.icio.us | Share

      view feed content Standup 11/07/2008: Selenium for Flash (Pivotal Blabs)   24 d and 0 h ago
Interesting Things Ask for Help

"I want to create a custom launcher for Firefox 2 and Firefox 3 with different profiles. Perhaps the real question is how do we create a custom version of a Mac application launcher, passing in the arguments we need?"

... without having to invoke it on the command line every time.

"We're trying to delete cookies in our Controller, but they keep appearing in the headers anyway."

Suggestion: make sure you are specifying your URL paths and domains correctly.

"Why won't our CSS and other assets load the first time when accessing an SSL-protected domain on Engine Yard?"

It's most likely not Engine Yard or Firefox 3's fault. More research needed.



View original post|Add to del.icio.us | Share

      view feed content Standup 11/6/2008 (Pivotal Blabs)   25 d and 0 h ago
Ask for Help

"console.log seems to be broken again in Firebug with 1.2.1?"

People have had some success with 1.3 beta. Get Firebug

"Suggestions for creating PDF's in Ruby?"



View original post|Add to del.icio.us | Share