Articles tagged with ruby

Obscure RubyGems Error

ruby June 22 2008

A week or so ago my gem command magically stopped working. Honestly, it was magic! There is no other logical explanation. The fetcher’s socket marshaled all over, spewing this error:

$ gem --version
1.1.0
$ sudo gem update --system
Updating RubyGems
ERROR:  While executing gem ... (Gem::RemoteFetcher::FetchError)
    Hostname not known: gems.rubyforge.org (SocketError)
    getting size of http://gems.rubyforge.org/Marshal.4.8

Googling different parts of that error didn’t yield anything useful. Lo, I post my solution in case some other poor soul has the same problem. Upgrade to 1.2.0.

Since gem upgrade --system is broken, download the rubygems-update manually.

$ sudo gem install ~/path/to/rubygems-update-1.2.0.gem
$ sudo update_rubygems

Ah, all better. Oh, by the way, rubygems 1.2 rocks!

posted by brandon | 0 comments

Proxy support for Tinder

ruby April 18 2008

I got to feel the pain of being stuck behind an HTTP proxy this week while working at Xerox’s office in El Segundo, CA. It sucked. You don’t realize how much you use the internet until you can’t get to half of the sites that you use every day.

So, in an effort to sympathize with other poor souls that are stuck behind a proxy during the work day, I added proxy support to Tinder:

  c = Tinder.new('subdomain', :proxy => 'http://user:pass@proxy.example.com:8000')

I don’t actually have access to testing this, so I’d appreciate if someone behind a proxy could check out the code from git and confirm that it works, and then I will put out a new release.

Speaking of git, I’m now only pushing changes to git. The subversion repository will stay around but will not be kept up to date.

posted by brandon | updated April 18th 04:33 AM | 0 comments

Daily WTF: NilClass#method_missing

ruby April 18 2008

With great power comes great responsibility.

I’ve been leading Ruby and Rails training over the last couple weeks for a company in Brisbane, Australia, Xerox in El Segundo, CA, and yellowpages.com in Glendale, CA. Visiting companies is always so interesting because you get to see how different people work together and how they go about solving problems. You also get to see some really interesting code.

I was helping one of the companies walk through some code they inherited from an acquisition and came across something similar to this wonderful snippet of code:

  class NilClass
    def method_missing(method, *args)
      raise(NoMethodError, "undefined method '#{method}' for nil")
    rescue => e
      CustomLogger.error(e)
      nil
    end
  end

WTF? They’re overriding #method_missing on nil to raise an exception, they then proceed to rescue it, log the error, and return nil!

I’m guessing they had some buggy code that was calling a method on nil, causing a NoMethodError to be raised. And instead of fixing the code, they just decided to change it so that you could call methods on nil and it would just silently fail.

>> nil.foo.bar.baz
=> nil

It took me a while to figure out why they were raising an error and then rescuing it, but I’m guessing it’s so they have access to a stack trace in the logger.

I’ll give them credit for being creative, but whoever wrote that piece of code doesn’t deserve to be using Ruby. Yes, Ruby’s open classes are powerful, but that’s just ridiculous.

posted by brandon | updated April 18th 03:28 AM | 5 comments

Ruby on Rails Training in San Francisco: April 1–4

ruby February 28 2008

I’ll be leading another hands-on, interactive workshop exploring the ins and outs of Ruby on Rails in San Francisco on April 1–4. Experience the Rails way of approaching web applications, starting with the basics of Ruby and Rails, and then diving into the full Rails’ MVC stack, testing techniques, Ajax and even web services. In the 4 day class, we’ll work through the full life-cycle of a Rails project, giving you experience with all facets of a typical app, lead by people that have been working with Rails every day for 2 years.

Sign up now on Marakana’s website and receive $150 off using the coupon code “collectiveidea”.

posted by brandon | updated February 28th 01:16 PM | 2 comments

RSpec flirts with git

ruby February 28 2008

The RSpec team is hoping to move to some form of distributed version control, giving both git and Mercurial a test run. This month, they’re checking out git.

You can clone the git repository using:

git clone git://gitorious.org/rspec/mainline.git rspec
posted by brandon | 1 comment

Camper: Jabber for Campfire

ruby February 18 2008

Jared Kuolt has put together a cool little app that lets you use Jabber with campfire. The app simply uses Tinder to listen in on a campfire room, forwarding messages on to a Jabber account, and posting any messages it receives from Jabber. Very cool. Adium chat window

Campfire chat window

posted by brandon | updated February 16th 12:59 PM | 2 comments

Getting a glimpse into Net::HTTP requests

ruby February 16 2008

While trying to debug some HTTP code, I wanted to be able to see what the actual HTTP request looked before it was sent. So, I added a #to_s method:

require 'stringio'

class Net::HTTPGenericRequest
  def to_s
    io = StringIO.new
    exec(io, '1.1', path)
    io.string
  end
end

All the built in requests extend HTTPGenericRequest, so now I can call #to_s on any request:

request = request = Net::HTTP::Get.new('/some/path')
request.set_content_type 'text/html'
request.basic_auth 'username', 'password'

puts request.to_s

Which gives me:

GET /some/path HTTP/1.1
Accept: */*
Content-Type: text/html
Authorization: Basic dXNlcm5hbWU6cGFzc3dvcmQ=

I had also intended to add a #to_s method to the response, but it wasn’t obvious how to accomplish that, and I found my bug before I needed it. So, if anyone feels ambitious…

posted by brandon | updated February 17th 12:08 PM | 1 comment

Tinder fixed after Campfire update

ruby January 25 2008

A week or so ago, 37 Signals released an update to Campfire that broke the ability to listen in a room with Tinder. Version 0.1.5 of Tinder has been released, which fixes the Room#listen method.

posted by brandon | updated January 25th 12:33 AM | 1 comment

Ruby on Rails Training in San Francisco, Jan 29–Feb 1

ruby January 11 2008

Maybe you’ve heard of it, but there’s this fancy web framework called Ruby on Rails. Apparently it’s all the rage these days. It’s only 2.0 right now, so the big kids say it still belongs on the playground, but there’s rumors of people using it to do real work. The word on the street is that it makes you more productive and makes programming fun again. If that sounds like something you’d like to learn, you can get more information and signup on Marakana’s website.

Update: Marakana is offering $150 off when you sign up using coupon code “collectiveidea”!

posted by brandon | updated January 16th 09:44 PM | 0 comments

Ruby's require doesn't expand paths

ruby January 08 2008

I ran across this issue several weeks ago, but it came up at the latest Grand Rapids Ruby Group meeting, so I thought I would share it.

Ruby’s require, for better or worse, doesn’t expand paths. As the docs point out, require 'a'; require './a' will load a.rb twice. This doesn’t matter most of the time, but there’s one place it’s used often that will bite you: tests and specs.

Every Rails’ test has a line similar to this:

require File.dirname(__FILE__) + '/../test_helper'

This doesn’t normally cause any problems, as long as every test has an identical require statement. Where you start to get into problems is when you have tests in a nested subdirectory (like test/controllers/admin/users_controller_test.rb), in which case the require statement would look like this:

require File.dirname(__FILE__) + '/../../test_helper'

require sees this as a different file and will re-load it. This still shouldn’t hurt you unless you’re doing something in test_helper.rb that would be changed by loading it twice (like aliasing a method). This also effects RSpec with requiring spec_helper.rb

The solution? Expand the path yourself.

require File.expand_path(File.dirname(__FILE__) + '/../../test_helper')

It’s not really clear to me why Ruby’s require works this way. You would think a method that was intended to only load a file once would make sure that it never re-loaded the same file, no matter how it was referenced. It definitely doesn’t adhere to the “principle of least surprise”. Any idea why?

posted by brandon | updated January 8th 11:32 PM | 6 comments

Hack for partial matches in Ferret

ruby December 12 2007

I love ferret (the ruby port of Lucene, not the fuzzy little creatures, you sicko). But something I fight on every project is that ferret turns into a bear when you try to get it to do partial matches, like "ferr" matching "ferret" and "ferrari".

Ferret allows you to append an asterisk to your search query ("ferr*"), which works great, but we can’t expect our users to do that because damn Google 1 has set the expectation that search just works; I don’t need to use any funky syntax to find my pogs, Harry Potter gossip or BRATZ 2.

So, we can do this manually in code by appending an asterisk to anything users enter and problem solved, right? Not quite.

  • It breaks if you’re using the StemFilter, which allows you to match variations of words ("happy" would match "happiness" and "happiest")
  • It will only match partials on the last word that the user entered ("Ed Brad" won’t find "Edward Bradley")
  • Apparently the asterisk tells ferret that there has to be more characters, because full matches no longer work ("ferret*" won’t match "ferret")

So, here’s my hack.

Book.find_by_contents "(#{term})^2 OR (#{term.split.map {|t| t + "*" }.join(' ')})"

This ugly little thing will match exactly what the user entered (making use of stemming and all the magic that comes from it) and give it a little boost in the ranking, or match any part of any of the words entered, giving me partial matches.

I acknowledge that this is an ugly hack at the moment, and will break miserably if the user is any kind of a wizard that knows how to do advanced searches, but it works for now. I have no idea what kind of consequences this will have as far as search performance and such. The goal is to wrap this into a filter.

Any one else have any cleaver ideas for doing partial matches?

  1. Yes, Google, we love and hate you for raising the bar.
  2. We’re talking normal users here, which excludes anyone that is reading this.
posted by brandon | updated December 12th 01:11 PM | 3 comments

Autotest without Rails

ruby December 06 2007

Autotest is a gem (well, technically ZenTest is a gem that includes autotest). But seriously, autotest is a gem! I can’t write code without it anymore. It has become my coding security blanket.

I started going through withdrawal last night while I was working on a Ruby library because autotest doesn’t work out of the box with plain ol’ Ruby projects. It assumes you’re using one of the Ruby web frameworks.

Here’s how to remedy that.

Aizatto shows us how to use autotest with your Rails plugins and RSpec. That’s a great start, but unfortunately, not all of my projects use RSpec (yet), and not all of them are Rails plugins.

To make autotest work with Test::Unit, we need to tell it how to map files to their tests. Here is a simple mapping that maps each ruby file in lib/ to the a corresponding test test/*_test.rb. For example, lib/foo/bar.rb would map to to a test in test/foo/bar_test.rb.

# autotest/testunit.rb
require 'autotest'

class Autotest::Testunit < Autotest
  def initialize # :nodoc:
    super
    @exceptions = /^\.\/(?:config|doc|log|tmp|website)/

    @test_mappings = {
      %r%^test/.*\.rb$% => proc { |filename, _|
        filename
      },
      %r%^lib/(.*)\.rb$% => proc { |_, m|
        ["test/#{m[1]}_test.rb"]
      },
      %r%^test/test_helper.rb$% => proc {
        files_matching %r%^test/.*_test\.rb$%
      },
    }
  end

  # Given the string filename as the path, determine
  # the corresponding tests for it, in an array.
  def tests_for_file(filename)
    super.select { |f| @files.has_key? f }
  end
end

We have the mapping, now all we need to do is tell autotest about it.

# autotest/discover.rb
require File.dirname(__FILE__) + '/testunit'

Autotest.add_discovery { "testunit" }

Throw both of those files into a autotest/ directory in your plain ol’ Ruby project and autotest should just work for you.

Extra credit: Make it work with RSpec on plain ol’ Ruby projects.

posted by brandon | updated December 6th 09:28 AM | 6 comments

acts_as_ferret will_paginate

ruby August 17 2007

Here’s a little nugget to add to acts_as_ferret to make your searches paginate with will_paginate.

module ActsAsFerret
  module ClassMethods
    def paginate_search(query, options = {})
      page, per_page, total = wp_parse_options(options)
      pager = WillPaginate::Collection.new(page, per_page, total)
      options.merge!(:offset => pager.offset, :limit => per_page)
      result = find_by_contents(query, options)
      returning WillPaginate::Collection.new(page, per_page, result.total_hits) do |pager|
        pager.replace result
      end
    end
  end
end

Updated from Behrang’s comment based on changes to will_paginate.

There was a slight challenge in that will_paginate expects that you do one query to get the count, create a new collection object based on that count, and then perform the actual search. But acts_as_ferret does it all in one method call, so I have to create a temporary collection object to get the offset, then do the search and create the collection object. It’s a little messier than it needs to be, but it works.

Product.paginate_search params[:q], :page => params[:page]
posted by brandon | updated March 14th 10:55 AM | 44 comments

Round floats to the nearest X

ruby July 18 2007

For those pesky times when whole numbers just won’t cut it, but you only want some precision.

7.7.round(0.5)   #=> 7.5
7.95.round(0.5)  #=> 8
8.2.round(1.5)   #=> 7.5
8.3.round(1.5)   #=> 9

The magic, courtesy of Daniel Morrison:

class Float
  def round(round_to = 1.0)
    mod = self % round_to
    rounded = self - mod + (mod >= round_to/2.0 ? round_to : 0)
    rounded % 1 == 0 ? rounded.to_i : rounded
  end
end

Note that do to some quirks with Ruby’s handling of floats, you won’t get what you expect in some situations:

3.5.round(0.2)   #=> 3.4, instead of 3.6
posted by brandon | 2 comments

Ruby on Rails Training

ruby July 18 2007

I will be leading a 4 day Ruby on Rails training course in San Francisco on September 4-8 through Marakana.

From Markana’s website:

In Ruby on Rails Training course you will learn to put your web development on Rails using Test-Driven Development to create clean Ruby code that works, developing the confidence you need to fearlessly refactor and enhance your Rails application going forward…Students will build a Rails application, learning the TDD lifecycle from the beginning. Time spent in lecture will focus on an introduction to Ruby, a thorough discussion of Test-Driven Development, and an in-depth exploration of the Rails framework, including a final day focused on using Ajax with Rails. The majority of the course will involve intense, hands-on learning to provide students with opportunities to encounter more realistic obstacles as they familiarize themselves with the rhythm of development on Rails.

If you can’t make it to San Francisco in early September, or are interested in private training for your company/group from developers with 2 years of real world Rails experience, feel free to contact me.

posted by brandon | updated July 18th 11:49 AM | 2 comments

About

I'm Brandon Keepers, a web application developer that likes beautiful code, valid markup and adherence to standards. As a part of Collective Idea in Holland, Michigan, I practice Agile software development primarily using Ruby on Rails.

-86.103171 42.785037

Contact:

more »

Syndicate