Tuesday, September 1, 2009

Links Between Mini-Months

‹prev | My Chain | next›

Yesterday, I was able to get my mini-calendar working. It displays the month with the most recent meal and links to other meals within that month. Up tonight are links to other months:



I already have all of the information that I need in the mini-calendar Sinatra action, so work begins with the RSpec specification for the mini-calendar Haml template. The main specification block assigns the month instance variable to a value of "2009-08":
  before(:each) do
assigns[:month] = "2009-08"
assigns[:meals_by_date] = {"2009-08-08" => "Meal Title"}
end
I will also need the count of meals per month:
  before(:each) do
assigns[:month] = "2009-08"
assigns[:meals_by_date] = {"2009-08-08" => "Meal Title"}
assigns[:count_by_month] = [{"key" => "2009-07", "value" => 3},
{"key" => "2009-08", "value" => 3}]

end
Since August is currently shown, there should be a link to July:
  it "should link to the previous month" do
render("views/mini_calendar.haml")
response.should have_selector("a",
:href => "/meals/2009/07",
:content => "<")
end
Happily, I already have a helper for that. This Haml code makes the example pass:
  .previous
=link_to_adjacent_view_date(@month, @count_by_month, :previous => true) { |d, v| %Q|<a href="/meals/#{d.gsub(/-/, '/')}">&lt;&</a>| }
That helper signature has not improved in prettiness since last I saw it. I can still grok it after a bit (given a current date and a CouchDB reduced list, find the previous entry on the list and generate the HTML in the block). I need to clean that up soon. For now, though, it passes.

Since my before block does not include anything after August in the count by month list, I do not expect that there should be a link to the next month:
  it "should not link to the next month" do
render("views/mini_calendar.haml")
response.should_not have_selector("a",
:content => ">")
end
That passes without any changes (because I have done nothing that would insert a ">" anywhere in the web page). It is something of a useless example of this point, but still good to have. I would like the next month indicator to be present, but not active:
  it "should the next month indicator should not be a link" do
render("views/mini_calendar.haml")
response.should have_selector(".next",
:content => ">")
end
Simplistically, I can get this passing with:
  %span.next
&gt;
That is not going to be helpful when there ought to be links, but I will drive that with a different context (one in which there is a next month) and a separate example:
  context "meals in next month, but not previous" do
before(:each) do
assigns[:count_by_month] = [{"key" => "2009-08", "value" => 3},
{"key" => "2009-09", "value" => 3}]
end
it "should link to the next month" do
render("views/mini_calendar.haml")
response.should have_selector("a",
:href => "/meals/2009/09",
:content => ">")
end
end
As expected that fails because the &gt; is just text, not a link:
cstrom@jaynestown:~/repos/eee-code$ spec ./spec/views/mini_calendar.haml_spec.rb
...........F

1)
'mini_calendar.haml meals in next month, but not previous should link to the next month' FAILED
expected following output to contain a <a href='/meals/2009/09'>></a> tag:
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" "http://www.w3.org/TR/REC-html40/loose.dtd">
<html><body>
<h1>
<span class="previous">

</span>
August 2009
<span class="next">
>
</span>
</h1>
...
I can get that passing with this Haml:
  %span.next
= link_to_adjacent_view_date(@month, @count_by_month) { |d, v| %Q|<a href="/meals/#{d.gsub(/-/, '/')}">></a>| } || "&gt;"
That example passes, but the previous example expecting the non-link &gt; text is no longer passing. I resolve that with a simple OR operator:
  %span.next
= link_to_adjacent_view_date(@month, @count_by_month) { |d, v| %Q|<a href="/meals/#{d.gsub(/-/, '/')}">></a>| } || "&gt;"
After driving similar behavior for links to previous months, I am ready to move back out to my Cucumber scenario to mark the links to previous / next months scenario as complete:
Then /^there should not be a link to the next month$/ do
response.should_not have_selector("a", :content => ">")
end

When /^I click on the link to the previous month$/ do
click_link "<"
end
At this point, following the links have no effect—the more recent month with meals always displays. The rest of the scenario describes the actual navigation, which I will pick up tomorrow.

No comments:

Post a Comment