Thursday, February 7, 2008

Andrzej's Rails tips #4

will_paginate in other languages

The default labels for the will_paginate are 'Next' and 'previous'. It's trivial to change them like that:

<%= will_paginate :prev_label => 'Wstecz', :next_label => 'Dalej'%>

Rails plugins, Piston and URLs

I use piston for plugins management. It's a nice tool that allows you to call 'piston up' on any of the plugins, at any time to update. What it does worse than 'script/plugin' command is managing different repositories. With the 'plugin' command you can say:
script/plugin source URL
and it adds the URL to the list of known repositories.

What I use with Piston instead, is storing the urls as environment variables. Here is an excerpt of my ~/.bash_login file:

export ATTACHMENT_FU=http://svn.techno-weenie.net/projects/plugins/attachment_fu/
export RESOURCE_CONTROLLER=http://svn.jamesgolick.com/resource_controller/tags/stable/
export ATTRIBUTE_FU=http://svn.jamesgolick.com/attribute_fu/tags/stable
export RESTFUL_AUTHENTICATION=http://svn.techno-weenie.net/projects/plugins/restful_authentication/
export RSPEC=http://rspec.rubyforge.org/svn/tags/CURRENT/rspec
export RSPEC_ON_RAILS=http://rspec.rubyforge.org/svn/tags/CURRENT/rspec_on_rails

So I just type 'piston import $ATTA', press TAB, and the shell autocompletion does it for me.

Wednesday, February 6, 2008

Andrzej's Rails tips #3

Multi-model forms with attribute_fu

I've used attribute_fu in two of my projects now. In one of them I use it in three different places. It simplifies your code a lot, when you want to edit many models in one form. Strongly recommended!

attribute_fu

Gradual switch to resource_controller

resource_controller is a plugin that allows your controller's code to ... disappear :-)
A great thing with this plugin is that you can introduce it gradually. Just install it, and make one controller a resource controller. See how it goes, and then decide whether it was worth it. I did it like that, and now I'm switching to it wherever I can.

BTW, both attribute_fu and resource_controller are made by James Golick. Thanks, James!

restful_authentication with RSpec

I didn't know it before, but Bartosz Blimke discovered that, when you have a spec directory in your Rails app and you generate some resources using restful_authentication, then it will generate Rspec specs instead of unit tests. Cool! I'm not a big fan of code generation/scaffolding, but when they also provide good specs then it easies the pain.

Tuesday, February 5, 2008

Remote pair programming

This article describes my experience with remote pair programming, why I chose remote pair programming for one of the projects, how it works and what tools we use.

One of the projects I'm working on is a Rails application. We work on that together with my colleague, Marcin. There's nothing really innovative in this application. I've got enough experience with Rails and IT in general to know that it can be finished in a given time. The interesting bit is, that both me an Marcin live in different cities. Even better, both of us travel a lot and very often we are in different countries.

A distributed team is nothing new in today's IT world. One of the most common approaches to this problem is to divide the system and responsibilities across different people/teams/locations. It can work, I was involved in many such projects. The problem is that it requires a lot of trust, patience and really good skills to know how to split the project. In my opinion, it's a very risky approach, and it's easy to do it wrong. Chad Fowler describes it perfectly in his book: "My job went to India".

Traditional pair programming is a great practice. I know it's still controversial, and I agree that it doesn't have to work for all software developers and all projects, but I've seen it successful often enough to know that there are many benefits of pair programming. The benefits that I find important are:
  • Focus on the task
  • Sharing knowledge
  • Increasing trust
  • Fun
  • Speed of development
In our case, I think all of the factors are important. As always, time is a constraint, so it's important to focus on the most important tasks first. We have different skills - while I'm a little bit more experienced with Rails and TDD, Marcin is my guru when it comes to html/css. He worked on many different IT projects, so his general experience and intuition is very important for me. It means, we both gain a lot from this kind of cooperation. Fun of development is also an important factor here :-) From the remote pair programming sessions we've had so far I can say that I'm also very glad of our efficiency.

The tools we use are nothing new. We use vim + screen + skype. We both login to a development server as the same user. There is a screen session already open, so we just 'screen -x' to it, and now we see the same things at the same time. It's fun to watch, when Marcin is typing something, explaining it using skype, and I see it immediately in my vim. At any point, I can grab the keyboard and just start typing. Cool! I can't imagine working like that without a skype session, though. Using IM is just too slow.

I'm strongly recommending this kind of cooperation. I'm aware of the limitations here. The application must be possible to build on a Linux/Unix machine, but even if it can't, I can imagine some work-arounds to this problem. Different timezones might be an issue here. I don't think the whole project must be built like that. However, planning some remote pair programming sessions may increase the quality of your software.

I like this way of working so much, that I even consider doing it more often. Would anyone be interested in a Rails coaching session like that? All you need is skype and an SSH client.

The articles I found useful when preparing to remote pair programming:

http://blog.lathi.net/articles/2007/10/09/remote-pair-programming

http://mikeburnscoder.wordpress.com/2007/06/21/my-rails-development-environment-version-1-vim-and-screen/

Andrzej's Rails tips #2

Changing month names in date_select

Sometimes you may need to change the month names that appear in the date_select (or anywhere in your application). One way of doing it is the following (setting Polish months names):

class Date
MONTHNAMES = %w{Styczeń Luty Marzec Kwiecień
Maj Czerwiec Lipiec Sierpień
Wrzesień Październik Listopad Grudzień}
end
RSpec Stories, steps with parameters

There is an easy way of reusing steps in RSpec stories.
Let's say you had a following step:


Given a search for chess


which was implemented with a hardcoded value like that:

Given "a search for chess" do
@search_term = 'chess'
end


And now you'd like to add another, very similar scenario:

Given a search for bridge

You can reuse the previously implemented step by changing the implementation to:

Given "a search for $term" do |term|
@search_term = term
end


Thanks to that, you can now reuse this step in as many scenarios as you want.

You can find a nice explanation of RSpec stories on Edd Dumbill's blog.

Monday, February 4, 2008

Andrzej's Rails tips #1

has_many :through, :uniq=>true

It's quite common that when you need to use has_many :through, you actually want to see unique objects. Today, I had a need to display a list of producers based on an order.

In my design I have:

Order.has_many :line_items
LineItem.belongs_to :producer
Order.has_many :producers,
:through => :line_items

With this in place, if an order has two products, each of them belonging to the same producer, then order.producers lists the same producer twice.
Adding :uniq => true solves the problem:

Order.has_many :producers,
:through => :line_items,
:uniq => true


More information about it on John Susser's blog.

RESTful routes and pdf

If you have an action that responds to many formats (html, rss, pdf), you can still use a RESTful route with a 'formatted' prefix:

link_to "PDF format",
formatted_order_path(@order, :pdf)

Found on Railscast #78.

Monday, January 21, 2008

What do I gain from TDD or BDD?

The question what do I gain from doing TDD/BDD is asked quite often. I understand the reasons people ask for that. I have practised TDD since 2001. This post is an explanation of why I TDD/BDD and what I gain from it.

Why do I BDD?

BDD helps me with 3 aspects of software development: Design, Defense, Documentation.
  • Design
    • When I write the specifications(tests) first, I see that my design is simpler (as compared to write the code first) for given requirements, thus better.
      • I know it's not very intuitive, you just have to try it.
    • When you start with tests, your design is more testable.
      • It makes debugging easier.
    • TDD doesn't replace drawing diagrams.
      • It's just an additional design technique.
      • I still enjoy drawing UML-like diagrams!
  • Defense
    • I feel much safer having my application covered with tests, .
      • Thanks to that, I can do some refactoring when I feel it's needed, run the tests, and if it's 'green' I just check it in.
    • Whenever some of my users find any bug, I prepare a test that covers it.
      • Only then I fix the bug and release the change.
      • There's nothing worse than having a bug that reappears again (after fixing it) in the application.
  • Documentation
    • I'm not a fan of big Word documents that describe all details of the requirements.
      • It's just too difficult to synchronize this document with reality after every requirements change
        • Changes are inevitable.
      • There was one large project I was working on, where nobody from the team (including the project manager) knew what all the requirements were!
        • Yes, it is pathological.
    • I store all of the requirements as executable stories/tests.
      • Before releasing any change I run all the stories.
      • When there is a requirement change I just find the story responsible for that, change it appropriately and change the code.
        • Changes are inevitable.
Do I have to TDD/BDD in order to be successful?

Well... No.

I know some very good developers that don't write any tests and are successful. There are other ways of ensuring good design or documentation. As for defense, you may have a very fast testing department that makes sure you didn't break anything. Or maybe you just prefer to manually go through your application. For me it's just too slow,
I prefer an immediate response that is free of any human mistakes. Chances are, you are just so perfect that you don't introduce any breaking changes. Lucky you!

It's also possible that you separate the analysis, design and implementation phases so strongly, that there is no way of changing anything during the implementation phase. I'm not a big fan of this approach but I know that many people are successful with that. I believe that even in this case you can gain a lot from writing acceptance tests (executable stories). Writing unit tests for your classes is also a good thing. I'll try to cover the topic of testing on different levels (acceptance, units) in a separate post.


But it's difficult and expensive, isn't it?

Yes, it is. All I gain doesn't come for free.

First of all, it requires discipline. It takes some time to get used to write tests first.
Also, it takes some time to learn how to do correct TDD/BDD. The good news is that you can start introducing it gradually.

Another thing is that after creating a lot of tests for your applications the whole suite may take some time to run. It's a problem that is not easy to solve, but believe me you'd prefer this kind of problems than a 5-days debugging session.

Is it fun?

Yes, it's a lot of fun!
Again, you have to try it before you know, what I'm talking about. If you're still new to TDD, look around, maybe there is someone experienced nearby who can show you a quick demo.

What next?

Find some TDD tools for your technology. I believe they exist for every programming language. Find a place in your application where you'd like to start testing. Start with something simple. Maybe assuring that a request to a given page is successful? Or maybe asserting that all the values in the Order class are calculated correctly? Make sure you run those tests after every change of your application.

Feel free to ask me questions about TDD or BDD. I have practised it with Java, C#, IronPython and Ruby. The technology doesn't matter too much in this case. You can use comments for that or simply email me at andrzejkrzywda at gmail.com.

Thursday, January 17, 2008

RSpec User Story example

Today, just a quick example showing what kind of wonderful things you can do with the new RSpec and its support for executable User Stories, a feature I was dreaming about for years...

Specification as a user story:



Story: Creating an order

Scenario: admin user creates an order
Given an admin user
And some orders
And some customers

When he creates an order

Then a new order is created
And a new customer is created

Implementation of the user story



Given "an admin user" do
login_as_admin
end

Given "some orders" do
@orders_count = Order.count
end

Given "some customers" do
@customers_count = Customer.count
end

When "he creates an order" do
post '/orders/create',
"order"=>{"address_attributes"=> {"name"=>"Customer 1"}}
end

Then "a new order is created" do
Order.count.should == @orders_count + 1
end

Then "a new customer is created" do
Customer.count.should == @customers_count + 1
end

The output when the user story is run:



Running 1 scenarios

Story: Creating an order

Scenario: admin user creates an order

Given an admin user
And some orders
And some customers

When he creates an order

Then a new order is created
And a new customer is created

1 scenarios: 1 succeeded, 0 failed, 0 pending