Quick testing of ActiveRecord validations in RSpec

ActiveRecord’s validations are a convenient way to test and control the state of objects before they hit the database.

Validations are themselves a presumably well-tested part of Ruby on Rails, but their usage in an application significantly changes the behaviour of your objects.

This means they should be spec’d like anything else.

Spec’ing out every single attribute on every single model is pretty repetitive though. Yesterday I rolled my own custom matcher to speed up this task. It takes advantage of the fact that I follow the convention of using a valid_attributes method somewhere in my model’s spec, which I use to create a basic object for testing. For example:

describe "Comment" do
  def valid_attributes
    {
      :commentable_type => 'Item',
      :commentable_id => 1,
      :content => "This is a comment!",
      :user_id => 1
    }
  end
  
  before(:each) do
    @comment = Comment.new(valid_attributes)
  end
  
  it "should ..."
end

My custom matcher allows me to add a single spec which ensures that the comment validates with exactly these attributes, and no less.

  it "should validate with exactly the specified attributes" do
    @comment.should validate_with_exactly(valid_attributes)
  end

The spec will fail - with an readable error message - if either:

  • The object is invalid with all the specified attribues
  • Any one of the attributes is missing and the object is valid

The spec code is available at http://pastie.org/230565 - pastie it into your spec_helper.rb.

This is still so hot off the press it’s positively steaming. Do you have any comments, bug reports or suggestions?

Rubinius’ lurking presence continues to be felt

Merb now seems to be tentatively running on Rubinius, the fledgling Ruby virtual machine. I’m watching both of these projects with real interest, although I have nowhere near enough free time to put either through their paces just yet (neither are close to production levels of usability at this point in any case).

It’s good to see Ruby’s boundaries being pushed, though. And there’s a reasonable chance that one or both of these projects could be the future.

And of course, Rubinius on Rails...

That will really be interesting.

Why I am switching to test-driven development

I am going to change the way I code.

My working pattern is, roughly, as follows:

  1. Sketch a basic method implementation
  2. Test it manually
  3. Fine tune the code, improve implementation
  4. Further manual testing, fix a few bugs
  5. Write a test
  6. Done! Make a cup of coffee.

Is there anything so bad about this process? I write a test, so I get one gold-star. And there’s nothing wrong with the end results: I write good code, which usually works. But I think I could work better. Every time I’ve written a model or controller for as long as I can remember, a little voice in my head asks: “Why haven’t you written the test first…?

Anybody else get the same little voice? I suspect there’s a few of you out there.

The more I’ve learnt about TDD, the more I’ve wanted to practice it. At first, it just seemed like a way of ensuring thorough test coverage, but that is actually just a sweet, sweet bonus. For me, TDD is more about changing my entire mindset when it comes to coding. The benefits promise to run deeper than may first appear obvious.

Sure, testing first will remind me to focus on what I want my code to do, before I start coding. This is valuable, yes - and I can see it helping me avoid a few refactoring/start-from-scratch sessions when my brain hasn’t quite been in gear - but I don’t believe that it will much improve my resulting finished code, so much as make the process of getting there a more efficient.

The more precious benefit, is that the pre-written tests will tell me exactly when to stop - and that’s a time when it’s a lot easier to trip up. Especially a day later, or a month later. The habit of testing first will prompt me to keep my methods small and manageable. Small and manageable in the short-term, equates to easy-to-maintain and stable in the long-term. A method of working which virtually obliges me to create manageable, bug-free code? And as good as guarantees a working stack of tests across my application?

There’s a whole host of other good reasons too, some of which I am perhaps yet to fully appreciate, but enough already. I am convinced.

So, why aren’t I doing it? My only problem is discipline. That’s going to change.

Test-unit Zappa

How will I switch to TDD? Firstly, I will drop Test::Unit and make the switch to RSpec.

Why switch? After all, the Test::Unit framework is a proven system in itself. It’s been shown to be more than capable of providing in-depth test coverage in complex applications, and is also usable within a strictly test-driven environment. What’s more, it’s true to say that there’s little testing that can be done with RSpec, that can’t already be done, one way or the other, using Test::Unit.

Isn’t switching from a system I am already well familiar with, simply going to be a short-term hindance - and offer questionable benefits in the long-term?

There are two stand-out reasons. Firstly, working with a different testing framework will force me to throw out my old habits, and hopefully help me to break my old routines and shake up my testing in the way that I want. Old habits die hard, and sometimes need a little persuasion.

Secondly - and perhaps even more importantly - it’s about changing the the language in which I write tests. RSpec’s descriptive idioms - typically written as something.should_have - are forward-looking, and cry out to be written and defined before the method they test. This is quite different to Test::Unit, which really encourages working the other way around.

As Josh Stephenson highlights here:

Just as sociologists have postulated that the language we use to express the world around us directly affects the way we interpret it, the language we use to test applications directly affects the way we develop them.

So RSpec will force me to throw out both my testing routines, and my vocabulary. I can’t do much more to create a catalyst for change.

Of course, I will be monitoring my work-flow, productivity and the resulting code carefully. If, after a reasonable period it is clear to me that TDD is not working - back I can go. But a decent spell of practicing TDD, a good level of familiarity - a fair test, so to speak - is going to be needed before I can conquer that little voice in my head, one way or the other.

In due course, I will post my progress here.

References/Further reading

http://www.oreillynet.com/pub/a/ruby/2007/08/09/behavior-driven-development-using-ruby-part-1.html?page=1

http://www.agiledata.org/essays/tdd.html

http://blog.daveastels.com/files/BDD_Intro.pdf

Ruby, from the perspective of SuperCollider

SuperCollider? It’s a programming environment designed for live digital signal processing, audio manipulation and algorithmic composition - making music, in other words. It is also contains a fully-fledged, dynamic, object-oriented language strongly influenced by both Smalltalk and functional programming, and as such it has a fair bit in common with Ruby.

There’s nothing like using two languages a lot (which I do) to get you comparing their finer details. Here’s what I have come to see differently about Ruby from coding in SC, and a few things I miss in Ruby that are present in SC. Maybe I’ll follow it up in the future, and do it the other way round.

Punctuation can be beautiful after all

Amongst a beginning Ruby programmer’s first acts, still flushed with the excitement of escaping from Java or PHP, will be to quite consciously throw away the habit of finishing each line of code with a semi-colon. And why not? They bugged me for years too, being obviously unnecessary in 99% of cases, cluttering up the page and and causing countless exceptions and failed builds when misplaced. And basically, for no good reason.

How many semi-colons do you see in Ruby code? Not a whole lot, in my experience. It’s almost like they’re omitted in order to somehow punish Java, perhaps deservedly.

SuperCollider requires the semi-colon at the end of (most) lines, and I used to feel it a bit of a pain. But semi-colons have kind of grown on me. Perhaps it’s because of SC’s strong functional programming paradigms, which means that it’s easier to chain multiple messages together than Ruby, even while splitting them across multiple lines.

SCWindow.new("A window!", Rect(20, 20, 300, 300))
    .alwaysOnTop_( true )
    .onClose_{ "Goodbye!".postln }
    .userCanClose_( false )
    .front
    ;

Most people seem to hide the semi-colon away. I prefer to give it pride of place, hanging it off the end of the indentation like a tear-drop.

The semi-colon is dead… Long live the semi-colon.

Syntactic sugar, SC style

Assuming iteration over a list - or range - makes a lot of sense. Actually, this isn’t syntactic sugar at all - just sensible proxying of messages - but it certainly feels like it.

Ruby:
(1..10).to_a.collect{ |num| num.squared }
# Ruby version >= 1.9
(1..10).to_a.collect(&:squared)

#=> [ 0, 1, 4, 9, 16, 25, 36, 49, 64, 81 ]
SuperCollider:
(1..10).squared

#=> [ 0, 1, 4, 9, 16, 25, 36, 49, 64, 81 ]

Also worth a mention is SC’s ! notation, as an alternative to Object#dup. This can often be used to fill an array.

Ruby
Array.new(10){ rand(10) }
SuperCollider
{ 10.rand } ! 10

Partial application

Partial application allows the creation of functions from implicit input data - that is, call a method sending less than the required number of arguments. This is a trick picked up from functional languages such as Haskell. There, however, it’s better known as currying.

It can be (vaguely) comparable, in effect, to Symbol#to_proc in Rails (and Ruby 1.9), but is endlessly more flexible and powerful.

Each pair of lines are equivalent:

(1..10).collect{ |number| number.postln };
(1..10).collect(_.postln);

(1..10).collect {|x| Polar(x, pi) };
(1..10).collect(Polar(_, pi));

There are ways to approximate this kind of thing in Ruby, but none which look (to me) remotely as elegant.

Currying is cool.

Instant API

Why does coding in SC seem so quick and easy?

Maybe, its partly down to the speed of access to the language documentation. And it really is quick. Not sure how to scan each item of array? Just type Array, select it and hit CMD-D - up pops the SC documentation for Array class. Unsure of where a method you are calling is implemented in the class hierarchy? Select it and hit CMD-Y, and up pops a list of classes where the method is implemented, including extensions and plugins.

And best of all, select the name of any class and hit CMD-J. There in front of you is the source code for that actual class.

Now, it would be unfair to use this as a criticism of Ruby, as SC has an integrated editing environment which makes this sort of thing possible to build in as standard. But anybody who created a Ruby version of this system, perhaps as a plugin for TextMate, would be an instant superstar in my eyes, and I would think a good few others too.

My conclusions…

I am increasingly aware of how much Smalltalk is responsible for, and more and more interested in getting to know it a bit better in itself. Learning a new language never did anybody any harm.

Under the hood: Ruby’s global variables

Tinkering in irb earlier, I ran this line of code.

global_variables.each{ |var| puts var + ": " + eval(var).inspect }

Ruby’s global variables - I have long been aware of their existence in the background, but I hadn’t realised quite how many are initialized by default. What are they all for - and what cool metaprogramming tricks can I use them for?

I actually use one of these variables very often, and it deserves a special mention. $! points to the most recently raised exception, and is a useful shortcut in many contexts. A lot of the others promise to be most useful in a shell/CGI script environment - but it’s good to know they’re there, and a little peek under the hood of Ruby usually proves instructional.

Here’s the global variables initialized by default on my system (Ruby 1.8.6 on OSX 10.5) - where I have some idea what they refer to, I’ve added that too.

Variable name Value (on my machine) Purpose?
$0 “irb” Name of current script executing
$” [”e2mmap.rb”, “irb/init.rb”, “irb/workspace.rb”, “irb/context.rb”, “irb/extend-command.rb”, “irb/output-method.rb”, “irb/notifier.rb”, “irb/slex.rb”, “irb/ruby-token.rb”, “irb/ruby-lex.rb”, “readline.bundle”, “irb/input-method.rb”, “irb/locale.rb”, “irb.rb”] Alias for $LOADED_FEATURES
$$ 6100 Ruby interpreter process ID
$< ARGF Points to ARGF (user input)
$_ nil Last string read by ‘gets’
$-K “NONE” $KCODE option passed via command line
$DEBUG false Can be set to true with ruby –debug myscript.rb. Just for program use I think?
$-i nil See ruby command line options: in-place-edit mode
$deferr # Usually points to $stderr
$/ “\n” Input record separator
$’ nil Text after regexp match
$stdout # Standard output (eg, the console usually)
$-l false See ruby command line options: automatic line-ending processing
$LOAD_PATH [”/usr/local/lib/ruby/site_ruby/1.8″, “/usr/local/lib/ruby/site_ruby/1.8/i686-darwin9.0.0″, “/usr/local/lib/ruby/site_ruby”, “/usr/local/lib/ruby/1.8″, “/usr/local/lib/ruby/1.8/i686-darwin9.0.0″, “.”]
$. 184 Last line of script read by interpreter
$KCODE “NONE” KanjiCODE - determines how Ruby handles characters
$-w false See Ruby intepreter command line options - sets $VERBOSE to true
$FILENAME “-” ?
$defout # Usually points to $stdout
$, nil ?
$` nil Text before regexp match
$* [] Command line arguments passed to current script
$stdin # Standard user input (usually, console)
$-F nil Field separator passed via command line
$-p false Used for command line file processing/looping (See also: -n)
$-I [”/usr/local/lib/ruby/site_ruby/1.8″, “/usr/local/lib/ruby/site_ruby/1.8/i686-darwin9.0.0″, “/usr/local/lib/ruby/site_ruby”, “/usr/local/lib/ruby/1.8″, “/usr/local/lib/ruby/1.8/i686-darwin9.0.0″, “.”] Library script path (passed via command line option -I)
$\ nil Output record separator
$= false Was last regular expression match case-sensitive?
$binding nil ?
$-v false Alias for –verbose command line option
$> # Points to standard output
$& nil Last matched regular expression (also $1, $2, etc)
$! nil Last raised exception
$PROGRAM_NAME “irb” Alias for $0
$LOADED_FEATURES [”e2mmap.rb”, “irb/init.rb”, “irb/workspace.rb”, “irb/context.rb”, “irb/extend-command.rb”, “irb/output-method.rb”, “irb/notifier.rb”, “irb/slex.rb”, “irb/ruby-token.rb”, “irb/ruby-lex.rb”, “readline.bundle”, “irb/input-method.rb”, “irb/locale.rb”, “irb.rb”] Alias for $”
$? nil Status of last executed child process (useful with Kernel#system and similar)
$; nil Input field separator
$SAFE 0 Ruby safe mode
$-d false Command line option –debug
$: [”/usr/local/lib/ruby/site_ruby/1.8″, “/usr/local/lib/ruby/site_ruby/1.8/i686-darwin9.0.0″, “/usr/local/lib/ruby/site_ruby”, “/usr/local/lib/ruby/1.8″, “/usr/local/lib/ruby/1.8/i686-darwin9.0.0″, “.”] Alias for library path(?)
$-0 “\n” Separator character(?)
$+ nil ?
$-a false Ruby command line options: auto-split mode
$VERBOSE false Ruby command line options: –verbose (some methods print extra information if this is on)
$stderr # Standard error destination
$~ nil Last matched regular expression data (instance of MatchData)
$@ nil Position of an error occurence

References

http://www.ruby-doc.org/docs/UsersGuide/rg/globalvars.html

http://cbcg.net/talks/rubyidioms/index.html

http://www.math.hokudai.ac.jp/~gotoken/ruby/ruby-uguide/uguide20.html

Hal Fulton: The Ruby Way (2nd Edition), Addison Wesley

AJAX performance trickery

This is a comprehensive guide to improving AJAX performance, including a guide to a Firefox plugin I hadn’t come across before - YSlow.

To me, AJAX performance isn’t so much a scalability issue, as a user interface one. The slicker and more responsive the interface, the better the user experience. And so a deeper understanding of the AJAX protocol has got to be a good thing.

http://www.ibm.com/developerworks/web/library/wa-aj-perform/?ca=dgr-lnxw01FasterAjax

Optimizing ActiveRecord :includes with :select

I have just read two posts (here and here), both of them discussing the sometimes formidable challenges faced when attempting to optimize ActiveRecord’s performance.

For me, ActiveRecord is easily Rails’ weakest link. Arguably, part of the problem is its ease of use. The object-oriented syntax means many developers find it far too easy to avoid opening up the hood and get their hands dirty with raw SQL, something which - in my opinion - every web developer should be able to do. But this is hardly AR’s fault. If that was the only problem, then ActiveRecord could stroll away unscathed while the workmen stood around blaming their tools. The real problems lie in other areas, and for me the most common I encounter is its inability to join two tables without then selecting every column in each table in the query.

For example:

User.find :all, :include => [ :posts, :comments ], :select => 'users.id, users.name, comments.content, posts.title'

will ignore the :include entirely, and go ahead and try to select from tables which weren’t included in the query. (This seems to have changed from earlier versions of AR, which ignored the :select options instead). Either way, this behaviour means it is difficult or impossible to sculpt elegant, effecient queries in many cases, and seriously erodes AR’s performance on complex queries.

I’ve seen a few patches published to solve this problem - and the highly useful select_with_include gem packaged up one of these patches, but sadly seems to be broken with the more recent builds of ActiveRecord (probably since this change, which I’m not sure fixes the same problem). Finding an alternative is high on my list of priorities, but surely something should have been baked into AR itself by now?

Storing Rails’ Flash object throughout multiple redirects

I am occasionally faced with the sometimes awkward problem of how to store a Flash message during more than one redirect. The problem is that the flash is usually cleared after one redirect, but sometimes you want to redirect more than once, but retain some flash message to display on the final destination.

These less than well known Rails methods probably hold the answer.
http://api.rubyonrails.com/classes/ActionController/Flash/FlashHash.html

Calling SetReturnURL from ebay4r

Garry Dolley’s ebay4r gem provides a Ruby interface to eBay’s SOAP API.

The following script extends it to allow the calling of eBay’s SetReturnURL method - required on a one-off basis to define redirect URLs for any eBay application authenticating users over the web.

ebay4r attempts to authenticate itself using the standard authToken, but this is one of the few calls which requires a username and password to be supplied instead of the token. The following script fixes the problem by inserting the required data into the header of the SOAP request before sending.

If there is a more straightforward way of doing this, I’d like to know - extensive delving into the ebay4r docs and examples revealed nothing.

require 'rubygems'
require 'ebayapi'

# your API details
appId = 'RobinWat-xxxx-xxxx-a9a5-b2a1e596xxxx'
devId = 'a696b358-xxxx-xxxx-b2e0-100b3fa8xxxx'
certId = '0c2d9022-xxxx-xxxx-9684-9082e9a2xxxx'
authToken = ''     # not needed for this call

# I had to use a sandbox test user here
username = 'testuser_xxx1'
password = 'xxxxxx'

accepturl = 'https://www.example.com/accept'
rejecturl = 'https://www.example.com/reject'
runame = 'developer-appname-auth'
action = 'Add'       # or 'Update'
application = 'yourappname'					

########################

ebay = EBay::API.new(authToken, devId, appId, certId, :sandbox => true)
ebay.debug = true

class EBay::RequesterCredentialsHandler
  Username = XSD::QName.new(nil, 'n1:Username')
  Password = XSD::QName.new(nil, 'n1:Password')

  def on_simple_outbound
    { EbayAuthToken => @token,
      Credentials => { DevId => @devId, AppId => @appId, AuthCert => @cert, Username => @username, Password => @password } }
  end
end

ebay.instance_eval do
  @header_handler.instance_eval { @username, @password = username, password }
end

ebay.SetReturnURL(
  :AuthenticationEntry => EBay.AuthenticationEntry({
    :AcceptURL => accepturl,
    :RejectURL => rejecturl,
    :PrivacyPolicyURL => nil,
    :RuName => runame,
    :TokenReturnMethod => 'FetchToken'}),
  :Action => action,
  :ApplicationDisplayName => application
)

Modal dialog windows for JavaScript

Carefully implemented, modal dialog windows can dramatically improve a user interface. There are a number of libraries which offer such a system, but many have fundamental differences in design, or require certain external JS libraries, and finding the right one for me has proven a bit challenging.

My requirements: compatibility with JQuery, and importantly, the ability to degrade gracefully for those users who disable javascript. Unfortunately, this last point is where Thickbox, otherwise the leading candidate for JQuery, falls down.

The solution could well be iBox. Independent of all external javascript libraries, it is nevertheless lightweight (7kb compressed), works first time out of the box - no pun intended - and since it doesn’t hijack the HREF tag, it degrades as nicely as you could wish for.

http://www.ibegin.com/labs/ibox/