Saturday, May 16, 2009

Between Years

‹prev | My Chain | next›

Up next in the browsing meals by year scenario is navigating between years:



Nice! That step is easy to implement thanks to webrat:
When /^I follow the link to the list of meals in 2008$/ do
click_link "2008"
end
That fails, of course, because I have yet to add links to previous / next years. So let's do that (and account for boundary conditions while we're at it). Into the code...

When the user is looking at 2008 meals, the application needs a count of the meals in 2007 and 2009 to whether or not to link to them. I could load in all the meals from both years using the same view that lists all meals in a given year and then do a count on the results or I can just ask CouchDB to do the count itself:
    "count_by_year": {
"map": "function (doc) {
if (doc['type'] == 'Meal') {
emit(doc['date'].substring(0, 4), 1);
}
}",
"reduce": "function(keys, values, rereduce) { return sum(values); }"
}
Describing how the /meals/YYYY action will use this view:
      it "should ask CouchDB how many meals by year" do
RestClient.
should_receive(:get).
with(/meals.+count_by_year/).
and_return('{"rows": [] }')

get "/meals/2009"
end
To use the results of the view to display links to the next / previous years' worth of meals, I will use a helper. Getting my BDD on:
describe "link_to_next_year" do
before(:each) do
@count_by_year = [{"key" => "2008", "value" => 3},
{"key" => "2009", "value" => 3}]
end
it "should link to the next year after the current one" do
link_to_next_year(@current_year, 2008).
should have_selector("a",
:href => "/meals/2009")
end
end
I can get this example passing by detecting the next year after the current one:
    def link_to_next_year(current, couch_view)
next_result = couch_view.detect do |result|
result['key'].to_i > current
end
%Q|<a href="/meals/#{next_result['key']}">#{next_result['key']}</a>|
end
Accounting for boundary conditions, when there are no more results, no link should be rendered:
  it "should return empty if there are no more years" do
link_to_next_year(2009, @count_by_year).
should == ""
end
This example can be made to pass by adding a conditional to the earlier definition of link_to_next_year:
    def link_to_next_year(current, couch_view)
next_result = couch_view.detect do |result|
result['key'].to_i > current.to_i
end
if next_result
%Q|<a href="/meals/#{next_result['key']}">#{next_result['key']}</a>|
else
""
end
end
That is a good stopping point for tonight. I will work my way back out to the feature tomorrow.

No comments:

Post a Comment