<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>ScottRu &#187; Rails</title>
	<atom:link href="http://scottru.com/category/rails/feed/" rel="self" type="application/rss+xml" />
	<link>http://scottru.com</link>
	<description></description>
	<lastBuildDate>Thu, 19 May 2011 03:05:09 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.0</generator>
		<item>
		<title>Lazy Testing your URLs</title>
		<link>http://scottru.com/2010/07/23/lazy-testing-your-urls/</link>
		<comments>http://scottru.com/2010/07/23/lazy-testing-your-urls/#comments</comments>
		<pubDate>Fri, 23 Jul 2010 19:49:13 +0000</pubDate>
		<dc:creator>scottru</dc:creator>
				<category><![CDATA[Programming]]></category>
		<category><![CDATA[Rails]]></category>

		<guid isPermaLink="false">http://scottru.com/?p=80</guid>
		<description><![CDATA[So I have a Rails app that&#8217;s broad but not very deep: there are a lot of different types of URLs and thousands of pages, generated dynamically or built through a CMS. No one page is that complicated, but there&#8217;s a fair amount of shared code and thus some tentacles throughout. Yes, I should have [...]]]></description>
			<content:encoded><![CDATA[<p>So I have a Rails app that&#8217;s broad but not very deep: there are a lot of different types of URLs and thousands of pages, generated dynamically or built through a CMS. No one page is that complicated, but there&#8217;s a fair amount of shared code and thus some tentacles throughout. Yes, I should have written behavior-level and unit-level tests from the beginning, but I didn&#8217;t, don&#8217;t judge me.</p>
<p>Anyway, after I broke the site yet again, I realized what I really wanted was a post-release test suite &#8211; I wanted to test a whole bunch of pages in production and make sure they&#8217;re still rendering.</p>
<p>Stealing from the <a href="http://www.ensta.fr/~diam/ruby/online/ruby-doc-stdlib/libdoc/net/http/rdoc/classes/Net/HTTP.html">Net::HTTP canonical examples</a>, then, I wrote a standalone script:</p>
<div class="code">
require &#8216;net/http&#8217;</p>
<p>URIs = ['http://example.com/', 'http://example.com/page/2']</p>
<p>puts &#8220;Running URL Test Suite&#8230;&#8221;<br />
URIs.each do |uri|<br />
&nbsp;&nbsp;url = URI.parse(uri)<br />
&nbsp;&nbsp;req = Net::HTTP::Get.new(url.path)<br />
&nbsp;&nbsp;res = Net::HTTP.start(url.host, url.port) { |http| http.request(req) }<br />
&nbsp;&nbsp;unless res.code == &#8217;200&#8242;<br />
&nbsp;&nbsp;&nbsp;&nbsp;puts &#8220;ERROR: #{uri} #{res.code}&#8221;<br />
&nbsp;&nbsp;end<br />
end<br />
puts &#8220;Test Suite Complete!&#8221;
</p></div>
<p>Then, since I <a href="http://philsturgeon.co.uk/news/2010/02/Deploying-websites-with-Git">deploy directly with git</a>, I added a call to this script in my post-receive hook. As long as I watch the deployment (which I do anyway), I&#8217;ll see if there&#8217;s a problem and fix it immediately. (I can handle a few minutes of downtime or just roll back.)</p>
<p>There are obvious improvements to this (like not storing the URLs in the file), and this doesn&#8217;t handle redirect, workflow, or authentication scenarios, but it&#8217;s a perfectly acceptable 99% case for a content site.</p>
<p>Note that if you are doing Rails development and you&#8217;ve built a custom 404 page, you&#8217;ll want to make sure that you&#8217;re actually returning a 404 status code, or this won&#8217;t catch errors: you can <a href="http://web-sniffer.net/">test your status codes</a>, and if you aren&#8217;t, you can <a href="http://stackoverflow.com/questions/943138/how-does-one-implement-dynamic-404-500-etc-error-pages-in-rails/943762#943762">add code in your application controller</a> to do the right thing.</p>
]]></content:encoded>
			<wfw:commentRss>http://scottru.com/2010/07/23/lazy-testing-your-urls/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Vaporbase micro-CMS: Performance Improvement</title>
		<link>http://scottru.com/2008/09/26/vaporbase-micro-cms-performance-improvement/</link>
		<comments>http://scottru.com/2008/09/26/vaporbase-micro-cms-performance-improvement/#comments</comments>
		<pubDate>Fri, 26 Sep 2008 15:02:05 +0000</pubDate>
		<dc:creator>scottru</dc:creator>
				<category><![CDATA[Programming]]></category>
		<category><![CDATA[Rails]]></category>
		<category><![CDATA[Technology]]></category>

		<guid isPermaLink="false">http://scottru.com/?p=20</guid>
		<description><![CDATA[(Warning: code talk ahead.) When I started building the app I&#8217;m working on, I needed a quick CMS system that didn&#8217;t impose its own parsing language, and I was just learning RoR, so I implemented the Vaporbase micro-CMS based on this great tutorial. While you wouldn&#8217;t confuse this with a pro-grade CMS system, it works [...]]]></description>
			<content:encoded><![CDATA[<p>(Warning: code talk ahead.)</p>
<p>When I started building the app I&#8217;m working on, I needed a quick CMS system that didn&#8217;t impose its own parsing language, and I was just learning RoR, so I implemented the Vaporbase micro-CMS based on <a href="http://www.vaporbase.com/postings/A_Micro-CMS_in_Rails">this great tutorial</a>. While you wouldn&#8217;t confuse this with a pro-grade CMS system, it works just fine for the most part, and doesn&#8217;t require you to learn a number of new things.</p>
<p>Since implementing it, I&#8217;d made a few minor cleanups, but nothing significant, until I had 60 pages in the CMS, and saw a problem: the list of pages was taking a very long time to load (21sec on avg on my dev machine).</p>
<p>Sure enough, there&#8217;s a problem: in the <strong>Edit and Show Tree Hierarchy </strong>section, here&#8217;s a line that says</p>
<div class="code">
<% unless index_item.children.nil? %>
</div>
<p>Looks innocuous, right? Not exactly: for every single page in the tree, this does a separate SQL query (which is a full table scan, though likely on a tiny table) to find out if that item has any children. So creating the page is O(# pages in table), and while the queries itself aren&#8217;t that expensive, building the page just takes a while. If your tree is mostly flat &#8211; almost certainly the case for this kind of CMS &#8211; you&#8217;re wasting a lot of time.</p>
<p>Fortunately, there&#8217;s an easy solution: when you get the list of pages before creating the tree, figure out which pages have children, and then store that list to the side. It adds a bit of code, but not a lot.</p>
<div class="code">
# Original: from the index action in the controller<br />
# This gets just the root nodes and then recurs down the tree<br />
@pages = Page.find( :all, :conditions => ['parent_id IS NULL'], <img src='http://scottru.com/wp-includes/images/smilies/icon_surprised.gif' alt=':o' class='wp-smiley' /> rder => :position)
</div>
<div class="code">
# Replacement:<br />
# build two arrays &#8211;<br />
# @pages consists of all of the root nodes (since the view walks down the tree)<br />
# @pageIDs_with_children consists of all pageIDs which are the parent for >=1 page </p>
<p>@pages = []<br />
@pageIDs_with_children = []</p>
<p>@all_pages = Page.find(:all)<br />
@all_pages.each do |page|<br />
if (page.parent_id.nil?)<br />
   @pages << page<br />
else<br />
   @pageIDs_with_children << page.parent_id<br />
end
</div>
<p>(Note that the list might have duplicates, but that doesn&#8217;t matter. If that makes you unhappy, check for existence in the else clause.)<br />
Then replace the view line above with</p>
<div class="code">
<% if @pageIDs_with_children.index(index_item.id) %>
</div>
<p>I saw a >80X performance improvement on this page with this change in development (from >20sec to ~0.25sec with 60 pages), and you&#8217;ve just replaced an expensive linear scaling step with a very inexpensive one.</p>
]]></content:encoded>
			<wfw:commentRss>http://scottru.com/2008/09/26/vaporbase-micro-cms-performance-improvement/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

