Saturday, May 23, 2009

I Already Did That?

‹prev | My Chain | next›

The last spec in the meals-by-month Haml spec is:
  it "should include recipe titles in the menu items"
Recipes are included in meal items (or anywhere in the text of meals and recipes) in a wiki format:
[recipe:2009/05/23/lemon_dressing]
Specifying how this will work:
  it "should include recipe titles in the menu items" do
assigns[:meals]['rows'][0]['value'][0]["menu"] =
[" Salad with [recipe:2009/05/23/lemon_dressing] "]

render("/views/meal_by_month.haml")
response.should have_selector(".menu",
:content => "Salad with Lemon Dressing")
end
In that example, I add a menu item that contains a wiki recipe link. After rendering the template, I expect that the title of that recipe will be included in the menu section of the output.

That spec has no chance of working right now because I have yet to even supply the recipe with the appropriate title. I need to figure out how I am going to supply that to the template. Them's implementation details, so let's have a look at how the rest of the wikifying code is implemented so far:
    def wiki(original)
text = (original || '').dup
text.gsub!(/\b(\d+)F/, "\\1° F")
text.gsub!(/\[kid:(\w+)\]/m) { |kid| kid_nicknames[$1] }
text.gsub!(/\[recipe:(\S+)\]/m) { |r| recipe_link($1) }
RedCloth.new(text).to_html
end
Hey, what's that recipe_link line in there? That looks exactly like what I wanted to implement. Turns out, I already did implement it:
    def recipe_link(permalink)
recipe = JSON.parse(RestClient.get("#{_db}/#{permalink}"))
%Q|<a href="/recipes/#{recipe['_id']}">#{recipe['title']}</a>|
end
Weird that I forgot doing that. It seems that implementing and re-implementing this application over-and-over may be finally catching up with me.

At any rate, if I stub out that RestClient call to return a recipe with a title, this spec may already be working! The spec with the RestClient stub:
  it "should include recipe titles in the menu items" do
assigns[:meals]['rows'][0]['value'][0]["menu"] =
[" Salad with [recipe:2009/05/23/lemon_dressing] "]

self.stub!(:_db).and_return("")

RestClient.
stub!(:get).
and_return('{"title":"Lemon Dressing"}')

render("/views/meal_by_month.haml")
response.should have_selector(".menu",
:content => "Salad with Lemon Dressing")
end
That :_db stub is another implementation detail, mostly owing to the way that I implemented my Sinatra / RSpec setup. With those two additions, the spec passes. Nice! No new code and I have the last meals-by-month Haml spec passing.

Since I did not have to add new code, but I do recall a use case that I overlooked in the original implementation, it can't hurt to do so now, while I am in the code already. Recipe wiki text of the form [recipe:2009/05/23/lemon_dressing Salad Dressing] should contain the supplied text, "Salad Dressing". The example describing this behavior:
    it "should wikify recipe URIs, using supplied text for the link" do
RestClient.stub!(:get).
and_return('{"_id":"id-123","title":"Title"}')

wiki("[recipe:id-123 Different Title]").
should have_selector("a",
:href => "/recipes/id-123",
:content => "Different Title")
end
I implement that with a non-greedy RegExp match (so that other text doesn't accidentally get slurped in):
      text.gsub!(/\[recipe:(\S+)\s(.+?)\]/m) { |r| recipe_link($1, $2) }
That changes the arity of recipe_link. So that it works with or without the title, I update the recipe_link helper thusly:
    def recipe_link(permalink, title=nil)
recipe = JSON.parse(RestClient.get("#{_db}/#{permalink}"))
%Q|<a href="/recipes/#{recipe['_id']}">#{title || recipe['title']}</a>|
end
So now I am ready to move on back out to the Cucumber scenario. Tomorrow.

No comments:

Post a Comment