Tuesday, October 13, 2009

Mocha stub_chain with AnyInstance

There is a module floating around called stub_chain:
Stub Chain

In short, it allows you to do:

>> Object.stub_chain(:this, :is, :my, :chain).rerturns(true)
>> Object.this.is.my.chain
=> true


It cleans up a bunch of mocking, stubbing code. Very cool.

So in Rails I found myself with the following chain in a controller:

current_user.profile.photos.build


So naturally I tried:

User.any_instance.stub_chain(:profile, :photos, :build).returns(Photo.new)


This did not work. After some investigation I found that technically the stub_chain was working. It was just stubbing each method call on a Mocha::AnyInstance object instead of the instance of the class like I wanted. My solution:

profile = mock("Profile")
profile.stub_chain(:photos, :build).returns(Photo.new)
User.any_instance.stubs(:profile).returns(profile)

Not as concise but still much less code than without stub_chain

Saturday, October 10, 2009

Rounding a Float to a Fraction

I had a need for more rounding precision than the regular Ruby Float#round method. For example, if I wanted to round to the nearest half Ruby does:

>> (0.6).round
=> 1

What I needed was:

>> (0.6).round_to_fraction(0.5)
=> 0.5

So I wrote up this monkey patch for the Float class:
Float#round_to_fraction(fraction = 0.5)

This works with any fractional value:

>> (0.75).round_to_fraction(0.65)
=> 0.65


My use case was to round out distance values. I wanted to round to nearest quarter mile values.

Rails Filter Matchers in RSpec

This is pretty granular TDD but I've found it useful:

Rails Filter Matchers for RSpec

I wrote these out of necessity for testing out the inheritance of certain filters I was writing in a recent app. Just save the file in:

RailsRoot/spec/support/active_record/have_filter.rb


It's pretty simple to use:


class HomeController < ApplicationController
before_filter :require_user, :except => [:action_1, :action_2]
...
end

describe HomeController do
it { should have_before_filter(:require_user).except(:action_1, :action_2) }
end


All of the Rails filters are covered:

have_before_filter(action)
have_skip_before_filter(action)
have_after_filter(action)
have_skip_after_filter(action)
have_around_filter(action)
have_skip_around_filter(action)

And you can call options on each filter:

.only(*args)
.except(*args)


I don't think that you should be writing out a filter test for every filter. For example, if you are assigning an instance variable from a param value for several actions. That does not seem to be appropriate for a filter test. As I mentioned up top my use case is to test that I am properly inheriting certain filters and also skipping inherited filters for certain actions. (mostly authentication stuff)

Tuesday, September 1, 2009

jferris-mocha and Rspec

I ran into a small issue when using Joe Ferris' fork of Mocha with Rspec. In the spec helper you have "


config.mock_with :mocha


I'm on version 0.9.5.0.1241126838 of jferris-mocha and the library load was failing. The reason is because Mocha::Standalone has been changed to Mocha::API.

To fix this, add this to your spec_helper.rb file:


module Mocha
module API
def setup_mocks_for_rspec
mocha_setup
end
def verify_mocks_for_rspec
mocha_verify
end
def teardown_mocks_for_rspec
mocha_teardown
end
end
end


Make certain it is defined before Spec::Runner is being called. Then use this:


config.mock_with Mocha::API


You should be good.

Monday, August 31, 2009

Decoder

Decoder


I just released Decoder.

So what is Decoder? It is a simple library for postal code lookups. For example:


>> country = Decoder::Countries[:US]
=> <Decoder::Country @name = "United States", @code = "US", @states = { "MA" => "Massachusetts", ... } >


So you do a code lookup and get back a Country object. If the country has states then you can lookup via a state code:


>> country[:MA]
=> <Decoder::State @name = "Massachusetts", @code => "MA" >


Right now there is only state support for the United States, Canada and Australia. But adding states to a given country is as simple as adding another YAML file. If you check out the code then go to:


$ cd lib/i18n/states/


Create a new directory that corresponds to the country code. Then create a new YAML file called 'eng.yml" that contains a hash of codes containing the full name for each code. The keys should be strings, not symbols.

i18n Support


By default Coder is set to English. If you wanted to change the language to French:


>> Decoder.i18n = :fre


Currently Decoder only has English support. But please feel free to add other languages. As shown above, each subdirectory under i18n currently has 'eng.yml' files. Just add a 'fre.yml' that contains the proper translations.

Please use the 3-letter ISO 639-2 Code standard for language codes.
http://www.loc.gov/standards/iso639-2/php/code_list.php

Wednesday, July 1, 2009

Need a Help desk? Try Zendesk!

This is a shameless self-promotional post.

I just started working at Zendesk.com, we provide SAAS Help Desk software that is dead simple to use. It costs nothing to try. Learn not to hate answering tickets! :)

http://zendesk.com

Sunday, April 19, 2009

Ruby 1.8 and 1.9 living together on Mac OSX

Lately I've been playing with Ruby 1.9.1 But for my professional life I still need 1.8.6 So here is how I have them setup to live happily together.

What you first want to do is, of course, install Ruby 1.9.1 (your tarball name might differ)

> wget ftp://ftp.ruby-lang.org/pub/ruby/1.9/ruby-1.9.1-p0.tar.gz
> tar xvf ruby-1.9.1-p0.tar.gz
> cd ruby-1.9.1-p0
> autoconf
> ./configure --prefix=/usr --enable-pthread
> make <== This will take some time

Now before you install you should backup your current Ruby's bin files...
> sudo cp /usr/bin/ruby /usr/bin/ruby-1.8
> sudo cp /usr/bin/irb /usr/bin/irb-1.8
> sudo cp /usr/bin/gem /usr/bin/gem-1.8

Okay, let's continue with the install
> sudo make install

After this is complete confirm that Ruby 1.9.1 is installed
> ruby --version
> irb
> RUBY_VERSION
> exit

Now, because we're assuming that you'll most likely be usining 1.8.6 most of the time still let's restore it and backup the bins for 1.9.1

> sudo mv /usr/bin/ruby /usr/bin/ruby-1.9
> sudo mv /usr/bin/ruby-1.8 /usr/bin/ruby
> sudo mv /usr/bin/irb /usr/bin/irb-1.9
> sudo mv /usr/bin/irb-1.8 /usr/bin/irb
> sudo mv /usr/bin/gem /usr/bin/gem-1.9
> sudo mv /usr/bin/gem-1.8 /usr/bin/gem

Now if you want an app to run with Ruby 1.9.1 just replace the first line of the script:

#!/usr/bin/ruby
with
#!/usr/bin/ruby-1.9

Happy Hacking!


> ./configure --program-suffix=19

The End
 
Brian Cardarella Mr Brian Cardarella 55b173094e2f213f26aadd24ccef3923ea0e078c