I pick up with adding the 10 most recent meals to the site's RSS feed. First, I have to pull back the list of the 10 most recent IDs from CouchDB. Thankfully, I did something similar for the homepage, so I can re-use here:
it "should request the 10 most recent meals from CouchDB" doTo implement, I add this to the
RestClient.
should_receive(:get).
with(/by_date.+limit=10/).
and_return('{"rows": [] }')
get "/main.rss"
end
get '/main.rss'
Sinatra application:url = "#{@@db}/_design/meals/_view/by_date?limit=10&descending=true"With that example safely passing, I need to ensure that the full details are pulled back for those 10 meals. Again, I copy from the site's home page example to stub out the
data = RestClient.get url
@meal_view = JSON.parse(data)['rows']
RestClient
call that pulls back the 10 meal IDs. Then I specify that those 10 IDs need to be used to look up the full meal details for each corresponding meal. This leads to something of a longish example:it "should pull back full details for the 10 meals" doTo get that example to pass, still using earlier RSS-specific examples, I use this code:
RestClient.
stub!(:get).
and_return('{"rows": [' +
'{"key":"2009-06-10","value":["2009-06-10","Foo"]},' +
'{"key":"2009-06-09","value":["2009-06-09","Foo"]},' +
'{"key":"2009-06-08","value":["2009-06-08","Foo"]},' +
'{"key":"2009-06-07","value":["2009-06-07","Foo"]},' +
'{"key":"2009-06-06","value":["2009-06-06","Foo"]},' +
'{"key":"2009-06-05","value":["2009-06-05","Foo"]},' +
'{"key":"2009-06-04","value":["2009-06-04","Foo"]},' +
'{"key":"2009-06-03","value":["2009-06-03","Foo"]},' +
'{"key":"2009-06-02","value":["2009-06-02","Foo"]},' +
'{"key":"2009-06-01","value":["2009-06-01","Foo"]}' +
']}')
RestClient.
should_receive(:get).
with(/2009-06-/).
exactly(10).times.
and_return('{"title":"foo",' +
'"date":"2009-06-17",' +
'"summary":"foo summary",' +
'"menu":[]}')
get "/main.rss"
end
end
get '/main.rss' doRather than driving the complete RSS implementation via RSpec examples, at this point I am going to move back to the Cucumber scenario so that I can use real data with the complete stack.
content_type "application/rss+xml"
url = "#{@@db}/_design/meals/_view/by_date?limit=10&descending=true"
data = RestClient.get url
@meal_view = JSON.parse(data)['rows']
rss = RSS::Maker.make("2.0") do |maker|
maker.channel.title = "EEE Cooks: Meals"
maker.channel.link = ROOT_URL
maker.channel.description = "Meals from a Family Cookbook"
@meal_view.each do |couch_rec|
data = RestClient.get "#{@@db}/#{couch_rec['key']}"
meal = JSON.parse(data)
maker.items.new_item do |item|
item.title = meal['title']
end
end
end
rss.to_s
end
Recall the Cucumber scenario so far:
I implement the visit the feed URL with a simple Webrat
visit
:When /^I access the meal RSS feed$/ doThat passes without any changes thanks to the RSpec driven work inside the Sinatra application.
visit('/main.rss')
response.should be_ok
end
To verify complete implementation of the next step, that the 10 most recent meals should be included in the RSS feed, I first check the old feed on the legacy Rails site:
<?xml version="1.0" encoding="UTF-8"?>First, up, there should be 10
<rss version="2.0">
<channel>
<title>EEE Cooks: Meals</title>
<link>http://www.eeecooks.com/meals/rss</link>
<description>Meals from a Family Cookbook</description>
<language>en-us</language>
<item>
<title>Star Wars: The Dinner</title>
<description><p>Inspired by one of the many <a href="http://www.cooksillustrated.com/">magazines</a> that Robin reads, we do a little grilling today. It’s been a while, so we were pleasantly surprised that the grill even started up, let alone that we were able to cook up such yummy food.</p></description>
<pubDate>Sun, 13 Jul 2008 00:00:00 +0000</pubDate>
<link>http://www.eeecooks.com/meals/2008/07/13</link>
<guid>http://www.eeecooks.com/meals/2008/07/13</guid>
</item>
<item>
<title>You Each Take a Side</title>
...
<item>
children of <channel>
, each with a <title>
child. I should also verify that the RSS item titles contain the expected values (e.g. "Meal 0", "Meal 1", etc). I can specify this in the example with:Then /^I should see the 10 most recent meals$/ doNext, I implement the see-the-summary-in-the-RSS feed step with:
response.
should have_selector("channel > item > title",
:count => 10)
response.
should have_selector("channel > item > title",
:content => "Meal 0")
end
Then /^I should see the summary of each meal$/ doThat fails initially because I did not have that attribute added to the
response.
should have_selector("channel > item > description",
:content => "meal summary")
end
RSS::Maker call, so I add it: rss = RSS::Maker.make("2.0") do |maker|
maker.channel.title = "EEE Cooks: Meals"
maker.channel.link = ROOT_URL
maker.channel.description = "Meals from a Family Cookbook"
@meal_view.each do |couch_rec|
data = RestClient.get "#{@@db}/#{couch_rec['key']}"
meal = JSON.parse(data)
maker.items.new_item do |item|
item.title = meal['title']
item.description = meal['summary']
end
end
To get the remaining attributes added to the RSS feed, I add two steps: And I should see a meal link
And I should see a meal published date
I will get those last two steps working tomorrow.