<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/atom10full.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.feedburner.com/~d/styles/itemcontent.css"?><feed xmlns="http://www.w3.org/2005/Atom" xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" xml:lang="en-US">
  <title>Rail Spikes - Home</title>
  <id>tag:railspikes.com,2009:mephisto/</id>
  <generator version="0.8.0" uri="http://mephistoblog.com">Mephisto Drax</generator>
  
  <link href="http://railspikes.com/" rel="alternate" type="text/html" />
  <updated>2009-11-09T06:09:05Z</updated>
  <link rel="self" href="http://feeds.feedburner.com/RailSpikes" type="application/atom+xml" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com" /><entry xml:base="http://railspikes.com/">
    <author>
      <name>Luke Francl</name>
    </author>
    <id>tag:railspikes.com,2009-11-09:2038</id>
    <published>2009-11-09T06:07:00Z</published>
    <updated>2009-11-09T06:09:05Z</updated>
    <category term="ycombinator" />
    <link href="http://feedproxy.google.com/~r/RailSpikes/~3/ca-KTmNCN3k/y-combinator-interview-advice" rel="alternate" type="text/html" />
    <title>Y Combinator Interview Advice </title>
<content type="html">
            &lt;p&gt;Paul Graham emailed YC co-founders to share their interview stories for those who were asked to interview for the W10 batch. Here’s my take.&lt;/p&gt;

&lt;p&gt;First off, congratulations! You’re probably wondering what to do next, depending on the outcome of the interviews. I’m not going to tell you not to be nervous, because that won’t help. But keep perspective – YC’s not the end-all of the startup world. If you’re dedicated, you can make your company happen (startups did exist before YC, believe it or not). I know one team that got rejected, but decided to move to Silicon Valley anyway. They got funded by a major VC before most of the companies in the Summer 2009 batch!&lt;/p&gt;

&lt;p&gt;That said, Y Combinator is an…&lt;em&gt;intense&lt;/em&gt; experience and you should try your hardest to get in. &lt;/p&gt;

&lt;h2&gt;What to expect&lt;/h2&gt;

&lt;p&gt;I can’t say what to expect better than Paul, so be sure to read &lt;a href="http://ycombinator.com/prepare.html"&gt;Y Combinator’s advice&lt;/a&gt;. There’s also been a number of YC alumni sharing their stories – check the bottom of that link. I’ll especially call out &lt;a href="http://myoung8.posterous.com/advice-for-your-yc-interview"&gt;Michael Young’s experience&lt;/a&gt; because he &lt;em&gt;didn’t&lt;/em&gt; get accepted…then joined a team that did, so he’s seen both sides.&lt;/p&gt;

&lt;p&gt;The interview setup itself is intimidating: you and your co-founders are sitting face-to-face with the Y Combinator partners (Paul, Jessica, Trevor, and Robert) across a ridiculously narrow table. In our interview, that tension was quickly broken as everyone crowded around to see our demo. Paul thinks big, so if he likes your idea, be prepared for him to rattle off about 2 years worth of work for you to do – new features, new markets, a different direction, etc.&lt;/p&gt;

&lt;p&gt;However, it’s not all about the idea. Some teams get roughed up in the interview and are surprised to be accepted. The Y Combinator partners are looking for teams to fund. Lots of YC startups end up doing a totally different thing before Demo Day.&lt;/p&gt;

&lt;p&gt;After the interview, be prepared for some of the longest hours of your life as you wait for the email (rejected) or phone call (accepted).&lt;/p&gt;

&lt;h2&gt;Getting Ready&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;“What are you going to do?”&lt;/strong&gt; This is the number one question to have an answer for. One sentence. Two tops. I made my co-founder repeat our answer ad nauseam for practice. You know how hard it was to boil your idea down into the 1 minute video for your application. Now it’s time to distill it even further. This is your first elevator pitch. Also be ready to talk about your competitors and how you’re going to make money. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Your demo.&lt;/strong&gt; You are going to show your demo. You’ve got some time: &lt;em&gt;polish it up!&lt;/em&gt; Fix rough edges, improve the UI, add the cool new feature you’ve been thinking about, test the critical paths. Could you sign up a paying customer before the interview? That’s impressive.&lt;/p&gt;

&lt;p&gt;I was in charge of giving the demo. I decided to do it as a series of browser tabs showing different features, because then I wouldn’t have to worry about the internet connection or anything breaking. I practiced it relentlessly and got it down to about a 2 minute spiel. When I actually showed the YC partners, I got interrupted and had to explain things here and there but I knew the material and was able to carry on.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Mock interviews.&lt;/strong&gt; We set up some mock interviews with entrepreneurs to practice. We wanted people who had run successful startups to test us and see where the weakness in our company and idea were. &lt;/p&gt;

&lt;p&gt;Scott Wheeler of Direct Edge &lt;a href="http://blog.directededge.com/2009/11/05/the-interview-with-y-combinator-thats-not/"&gt;writes about something similar they did&lt;/a&gt;:&lt;/p&gt;

&lt;blockquote&gt;
    &lt;p&gt;We brainstormed a big list of questions that I can’t find anymore that we thought might come up and talked through answers to all of them. We came up with a list of points that we wanted to be sure to mention and even practiced transitions from other topics to those.&lt;/p&gt;
    
    &lt;p&gt;All of that, however, turned out to be useless.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Our mock interviews turned out nothing like the real one. But I disagree with Scott. It wasn’t useless, because it made us more prepared. &lt;/p&gt;

&lt;p&gt;If you’re prepared, you’ll be more relaxed, and can focus on presenting your idea.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Talk to alumni.&lt;/strong&gt; You probably know some YC alumni. Email them and see try to set up a phone call about what to expect. I think you’ll find most will be happy to give you some time to ask questions.&lt;/p&gt;

&lt;h2&gt;Good luck&lt;/h2&gt;

&lt;p&gt;That’s it for now. Maybe someday I’ll tell the full story of our YC interview (which includes nearly missing it due to a Murphy-worthy series of screwups) but for now I wanted to get the solid advice out of the way. &lt;/p&gt;

&lt;p&gt;Not everyone is going to get in, but if you focus on &lt;em&gt;“What are you going to do?”&lt;/em&gt; and &lt;em&gt;getting your demo down cold&lt;/em&gt;, you can maximize your odds.&lt;/p&gt;
          &lt;img src="http://feeds.feedburner.com/~r/RailSpikes/~4/ca-KTmNCN3k" height="1" width="1"/&gt;</content>  <feedburner:origLink>http://railspikes.com/2009/11/9/y-combinator-interview-advice</feedburner:origLink></entry>
  <entry xml:base="http://railspikes.com/">
    <author>
      <name>Jon</name>
    </author>
    <id>tag:railspikes.com,2009-10-29:2033</id>
    <published>2009-10-29T17:06:00Z</published>
    <updated>2009-10-29T21:17:38Z</updated>
    <category term="testing" />
    <link href="http://feedproxy.google.com/~r/RailSpikes/~3/8vuia0PgjwA/human-testing" rel="alternate" type="text/html" />
    <title>Let a human test your app, not (just) unit tests</title>
<content type="html">
            &lt;p&gt;&lt;img src="http://www.billionswithzeroknowledge.com/wp-content/uploads/2009/04/failwhale.jpg" width="300px" /&gt;
I’m a big believer in unit testing. We unit test our Rails apps extensively, and we’ve done so for years. On some projects, we do both unit testing and integration testing using &lt;a href="http://cukes.info/"&gt;Cucumber&lt;/a&gt;. I preach unit testing to everyone I can. I’d probably turn down a project if the client wouldn’t let us write tests (though this has never come up, and I don’t think it would be a hard sell).&lt;/p&gt;


	&lt;p&gt;But for a long time, that’s all I did on my projects. Our clients and users would find the bugs that got past the developers. They were, in effect, our QA testers. (I think a lot of small/agile teams are the same way; based on my experience, I’d be surprised if more than 20% of Rails projects were comprehensively tested by a human.)&lt;/p&gt;


	&lt;p&gt;This is not right. A good QA tester is worth the surprisingly modest expense.&lt;/p&gt;


	&lt;h4&gt;If I unit test, do I really need to hire a QA tester?&lt;/h4&gt;


	&lt;p&gt;Keep on writing unit tests. But unit tests and human testing are two completely different things. They both aim to increase code quality and decrease bugs, but they do this in different ways.&lt;/p&gt;


	&lt;p&gt;Developer (unit) testing has three benefits. It:&lt;/p&gt;


	&lt;ul&gt;
	&lt;li&gt;&lt;strong&gt;Makes refactoring possible.&lt;/strong&gt; Don’t even try to refactor a large app without a test suite.&lt;/li&gt;
	&lt;/ul&gt;


	&lt;ul&gt;
	&lt;li&gt;&lt;strong&gt;Speeds up development.&lt;/strong&gt; I know there are some haters who deny this, but they’ve either never really given unit testing a chance, or their experience has been 180º different than mine.&lt;/li&gt;
	&lt;/ul&gt;


	&lt;ul&gt;
	&lt;li&gt;&lt;strong&gt;Eliminates some bugs.&lt;/strong&gt; Not all, but some.&lt;/li&gt;
	&lt;/ul&gt;


	&lt;p&gt;Human testing has related, but somewhat different, benefits. It:&lt;/p&gt;


	&lt;ul&gt;
	&lt;li&gt;&lt;strong&gt;Eliminates other bugs.&lt;/strong&gt; Unit tests are great for certain categories of bugs, but not for others. When a human walks through an application with the express purpose of making things break, they’re going to find things that developer-written unit tests won’t find.&lt;/li&gt;
	&lt;/ul&gt;


	&lt;ul&gt;
	&lt;li&gt;&lt;strong&gt;Acts as a “practice run”.&lt;/strong&gt; Before letting a client, boss, or user see a change, let a QA tester see it. You’d be surprised how many 500 errors and IE incompatibilities you can avoid.&lt;/li&gt;
	&lt;/ul&gt;


	&lt;ul&gt;
	&lt;li&gt;&lt;strong&gt;Gives you confidence before you deploy.&lt;/strong&gt; After working with good QA testers, I can’t imagine deploying an app to production without having a QA tester walk through it.&lt;/li&gt;
	&lt;/ul&gt;


	&lt;ul&gt;
	&lt;li&gt;&lt;strong&gt;Saves you time.&lt;/strong&gt; If you don’t have a QA role on your project, your developers will be defacto testers. They probably won’t do a good job at this, since they’ll be hoping things succeed (rather than making them fail). And their time is probably more expensive than a good tester’s time.&lt;/li&gt;
	&lt;/ul&gt;


	&lt;h4&gt;How to use a QA tester in an agile project&lt;/h4&gt;


	&lt;p&gt;Agile testers should do four things.&lt;/p&gt;


	&lt;p&gt;First, they should verify or reject each story that is completed. Every time a developer indicates that a feature or bug is completed, whether you use a story tracker or index cards, a QA tester should verify this. Don’t deploy to production until the tester gives it a thumbs-up.&lt;/p&gt;


	&lt;p&gt;Second, they should do exploratory testing after every deploy. A few minutes clicking around in production can sniff out a lot of potential errors.&lt;/p&gt;


	&lt;p&gt;Third, they should test edge cases. What happens if a user types in a username that is 300 characters long? What they try to delete an item that is still processing? What if they upload a &lt;span class="caps"&gt;PDF&lt;/span&gt; file as an avatar? Testers are great at this sort of thing.&lt;/p&gt;


	&lt;p&gt;Fourth, they should test integrations. Unit tests can’t (and shouldn’t) test multi-step processes. Integration testing tools like Cucumber are OK, but don’t catch everything. Identify the main multi-step processes on your site, and have a human verify them every time they change.&lt;/p&gt;


	&lt;p&gt;Expect a tester to increase your development costs by 5%-10%. We find that 1 hour of testing for every 6 hours of developer time is a reasonable estimate. Our testers cost about 40% less than our developers. So on a typical invoice, testing services are about 10% of development services.&lt;/p&gt;


	&lt;p&gt;Bill separately for testing. Don’t just roll it into your developer rate. Clients are more likely to object to a 10% increase in your main hourly rate than a separate, lower testing line item.&lt;/p&gt;


	&lt;h4&gt;Finding a good tester&lt;/h4&gt;


	&lt;p&gt;There are two main ways to find a tester.&lt;/p&gt;


	&lt;p&gt;First, you can train one. Tech-savvy folks who aren’t programmers are a good option. They understand enough to fit in with your development process, but are happy testing and not coding. If you find the right person, they can be testing in no time, and won’t cost a ton of money.&lt;/p&gt;


	&lt;p&gt;Second, find one that understands agile development. There are plenty of professional testers out there, but most of them do waterfall testing: spend 3 weeks writing test cases, get release from developers, and spend 3 weeks testing. I can say, without hyperbole, that this is how exactly 0% of Rails development projects work. Look for the small number of testers that actually have experience with iterative development, flexible scope, and rapid turnaround. You can sometimes find these people at agile events (conferences or user groups). Otherwise, ask other developers. I found one via referral, and I’ve since referred him to others. This second category will probably be more expensive than the first, but if you want to ship the best code you can, go with this route.&lt;/p&gt;
          &lt;img src="http://feeds.feedburner.com/~r/RailSpikes/~4/8vuia0PgjwA" height="1" width="1"/&gt;</content>  <feedburner:origLink>http://railspikes.com/2009/10/29/human-testing</feedburner:origLink></entry>
  <entry xml:base="http://railspikes.com/">
    <author>
      <name>Jon</name>
    </author>
    <id>tag:railspikes.com,2009-08-28:2028</id>
    <published>2009-08-28T15:00:00Z</published>
    <updated>2009-08-29T14:48:48Z</updated>
    <category term="zencoder" />
    <link href="http://feedproxy.google.com/~r/RailSpikes/~3/wNpuUdd3sAM/buiding-a-video-distribution-in-48-hours" rel="alternate" type="text/html" />
    <title>Building a Video Delivery Network in 48 hours</title>
<content type="html">
            &lt;p&gt;Last weekend, I participated in my first Rails Rumble. Rails Rumble is a 48-hour app building contest. We started from scratch Friday evening – you can have concepts and notes on paper, but no code or digital UI assets – and stopped Sunday evening, after 48 hours. You can use open-source code and public web services, and we made liberal use of both.&lt;img src="http://railspikes.com/assets/2009/8/28/zenvdn.png" /&gt;&lt;/p&gt;


	&lt;p&gt;Our team consisted of &lt;a href="http://twitter.com/jondahl"&gt;myself&lt;/a&gt; and three of the &lt;a href="http://sevenwire.com"&gt;Sevenwire&lt;/a&gt; crew: &lt;a href="http://twitter.com/fowlduck"&gt;@fowlduck&lt;/a&gt;, &lt;a href="http://twitter.com/brandonarbini"&gt;@brandonarbini&lt;/a&gt;, and &lt;a href="http://twitter.com/steveheffernan"&gt;@steveheffernan&lt;/a&gt;. That’s two developers (Nate and myself), one developer/UI combo (Brandon), and one UI guy (Steve). All in all, a really good mix for the app. We’re also the team behind &lt;a href="http://zencoder.tv"&gt;Zencoder&lt;/a&gt;, and partners in &lt;a href="http://flixcloud.com"&gt;FlixCloud&lt;/a&gt;.&lt;/p&gt;


	&lt;p&gt;Check out &lt;a href="http://zenvdn.com"&gt;our app&lt;/a&gt; (and the 21 other great finalists) and vote at &lt;a href="http://r09.railsrumble.com/entries"&gt;http://r09.railsrumble.com/entries&lt;/a&gt;. Voting ends this weekend, so do it soon.&lt;/p&gt;


	&lt;h3&gt;The App&lt;/h3&gt;


	&lt;p&gt;Our project was &lt;a href="http://zenvdn.com"&gt;ZenVDN&lt;/a&gt;, a video distribution network. In other words, a place to upload video that you want to publish, i.e. via your blog or website. Upload one or more videos, and they’re transcoded into web and mobile formats, and sent to a Content Delivery Network for distribution.&lt;/p&gt;


	&lt;p&gt;After that, you’re given a page to manage each video, with &lt;span class="caps"&gt;HTML&lt;/span&gt; embed code to plug the video directly into your blog or website. You can also link directly to the videos, if you want to use your own player. And finally, each video has a &lt;a href="http://zenvdn.com/v/902d4766bf0b3f364266166150e1195aba043d91"&gt;public page&lt;/a&gt; on the ZenVDN site if you want to share the video directly.&lt;/p&gt;


	&lt;p&gt;So it’s a complete start-to-finish video publishing platform. Let’s say you’re &lt;a href="http://railscasts.com/"&gt;Ryan Bates&lt;/a&gt; of RailsCasts. You can compress, upload, and host your own video files manually, or you can use a service like ZenVDN to do that for you. (I emailed Ryan about this, by the way, and he prefers the manual route. ;)&lt;/p&gt;


	&lt;p&gt;Another way to look at it: a better YouTube for video publishers. YouTube and its peers were designed for wide-scale video sharing, not for video producers and content owners. If you don’t mind YouTube’s quality and watermark, and you don’t mind your video being shared publicly on YouTube, ZenVDN probably isn’t for you. But if you want better quality and to own distribution of your videos, check us out.&lt;/p&gt;


	&lt;p&gt;What’s cool? A multi-file uploader with progress; direct uploads to our &lt;span class="caps"&gt;CDN&lt;/span&gt;, for speed and scalability; video watermarking; video thumbnails; wide input video support; a &lt;a href="http://flowplayer.org"&gt;Flash Player&lt;/a&gt; integrated into the embed code; and detailed statistics (by video, by date, by format).&lt;/p&gt;


	&lt;p&gt;What’s missing? Again, it’s a working end-to-end product, but we’d like to do a lot more. Examples: Ogg support (for &lt;span class="caps"&gt;HTML 5&lt;/span&gt;), an &lt;span class="caps"&gt;RSS&lt;/span&gt; feed for videos, more public/sales information, and better privacy controls.&lt;/p&gt;


	&lt;p&gt;And, of course, paid subscriptions. We hoped to get e-commerce done during the Rumble, probably using &lt;a href="http://spreedly.com"&gt;Spreedly&lt;/a&gt;, but we ran out of time. Maybe in a 72 hour Rumble. In the meantime, our Free level limits the number of videos you can upload, and the amount of video you can stream. A paid level would increase these limits and let you use your own watermark (instead of the ZenVDN watermark on free accounts).&lt;/p&gt;


	&lt;p&gt;All in all, we’re really happy with where we ended up. I’m proud to say that &lt;a href="http://blog.obiefernandez.com/"&gt;Obie&lt;/a&gt; &lt;a href="http://r09.railsrumble.com/teams/zencoder#comments"&gt;briefly questioned&lt;/a&gt; whether we could build the whole thing in a weekend. That’s praise.&lt;/p&gt;


	&lt;h3&gt;The experience&lt;/h3&gt;


	&lt;p&gt;The Rumble was &lt;em&gt;way&lt;/em&gt; more fun than I expected. I had just worked a hard week, and a part of me was dreading the prospect of a long weekend of work. But it was actually a blast.&lt;/p&gt;


	&lt;p&gt;Why? Development flow, I think. Development flow is a really fun experience. It’s probably why most of us are developers, after all. We like to build things; we like to solve problems; and we like to work effectively. I’ll sometimes go days, or even  weeks, without experiencing concentrated development flow like I did during the Rumble. (Stupid meetings.) So the Rumble was a really great experience.&lt;/p&gt;


	&lt;p&gt;Our team really clicked. We had a great mix of skills: across the four of us, we had one designer, two front-end coders, and three back-end coders. Besides the initial design concepts, every task could have been handled by more than one person, so tasks rarely sat in the queue for long.&lt;/p&gt;


	&lt;p&gt;We tried really hard to avoid rushing at the end. We stopped development with 3 hours to go, and two of us started testing, while two others recorded the screencast for the homepage. But it didn’t work out quite so smoothly. The screencast wasn’t done until about T-30 minutes, and we were checking in fixes and refinements until about 6:45. Then a minor Git snafu, and panic ensued. Our final submission came down to the wire.&lt;/p&gt;


	&lt;p&gt;Finally: sleep and breaks. Call me weak, but I like to sleep. I got 8 hours/night during the Rumble, which definitely improved my experience (and the quality of my code). We ate lunch at our desks, but took a 90-minute dinner break on Saturday, and stopped several times for a game of darts.&lt;/p&gt;


	&lt;h3&gt;Lessons learned&lt;/h3&gt;


	&lt;p&gt;1. Blitzes can be fun and effective. I’m inclined to try a Rumble-like iteration every few months, to avoid project monotony, and to ship stuff quickly when necessary. I did ~3-4 days of work during the Rumble, so I figure a 3 day Rumble plus 2 days of vacation evens out to about a week of work.&lt;/p&gt;


	&lt;p&gt;2. Focus is essential. If I had three 30-minute meetings during the Rumble, my contribution would have been cut in half. Good reminder of &lt;a href="http://www.paulgraham.com/makersschedule.html"&gt;makers’ schedules&lt;/a&gt;.&lt;/p&gt;


	&lt;p&gt;3. Don’t rush at the end. We left three hours for testing and padding. We should have left six.&lt;/p&gt;


	&lt;p&gt;4. Prioritize well. If we had tackled e-commerce on Day 2 (as I almost did), we wouldn’t have finished our core product. Build the Minimum Viable Product first, and then move on to concentric circles of improvement.&lt;/p&gt;


	&lt;p&gt;5. Small projects can work. I have a bias against small projects; 3 month gigs feel so much more comfortable to me as a consultant than 3 week gigs. But done properly, shorter projects can work fine. We did ~$15,000 worth of work over the course of the weekend. No reason that experience couldn’t translate into a client project.&lt;/p&gt;


	&lt;h3&gt;Next steps&lt;/h3&gt;


	&lt;p&gt;So what’s next for ZenVDN? We’d really like to get a few video publishers using it. (Talk to me if you want to be a beta customer.)&lt;/p&gt;


	&lt;p&gt;And we want to monetize the site, of course.&lt;/p&gt;


	&lt;p&gt;We think it complements our suite of video-related products well – &lt;a href="http://zencoder.tv"&gt;Zencoder&lt;/a&gt; is the core software; &lt;a href="http://flixcloud.com"&gt;FlixCloud&lt;/a&gt; makes it an easy web service; and &lt;a href="http://zenvdn.com"&gt;ZenVDN&lt;/a&gt; brings video publishing one step closer to the producers.&lt;/p&gt;


	&lt;p&gt;We have some other ideas for ZenVDN. But if you have an interest in online video, or are a publisher/producer yourself, we’d love to talk more!&lt;/p&gt;
          &lt;img src="http://feeds.feedburner.com/~r/RailSpikes/~4/wNpuUdd3sAM" height="1" width="1"/&gt;</content>  <feedburner:origLink>http://railspikes.com/2009/8/28/buiding-a-video-distribution-in-48-hours</feedburner:origLink></entry>
  <entry xml:base="http://railspikes.com/">
    <author>
      <name>Jon</name>
    </author>
    <id>tag:railspikes.com,2009-08-19:2020</id>
    <published>2009-08-19T00:21:00Z</published>
    <updated>2009-08-19T00:22:51Z</updated>
    <category term="Programming" />
    <category term="activerecord" />
    <link href="http://feedproxy.google.com/~r/RailSpikes/~3/y1Nno8ZfSR0/activerecord-refererential-integrity-is-broken-let-s-fix-it" rel="alternate" type="text/html" />
    <title>ActiveRecord refererential integrity is broken. Let's fix it!</title>
<content type="html">
            &lt;p&gt;ActiveRecord supports cascading deletes to preserve referential integrity:&lt;/p&gt;


&lt;table class="CodeRay"&gt;&lt;tr&gt;
  &lt;td title="click to toggle" class="line_numbers"&gt;&lt;pre&gt;1&lt;tt&gt;
&lt;/tt&gt;2&lt;tt&gt;
&lt;/tt&gt;3&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class="code"&gt;&lt;pre&gt;&lt;span class="r"&gt;class&lt;/span&gt; &lt;span class="cl"&gt;User&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;  has_many &lt;span class="sy"&gt;:posts&lt;/span&gt;, &lt;span class="sy"&gt;:dependent&lt;/span&gt; =&amp;gt; &lt;span class="sy"&gt;:destroy&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;span class="r"&gt;end&lt;/span&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;


	&lt;p&gt;But you really only want cascading deletes about half the time. The other half, you want to actually &lt;a href="http://rails.uservoice.com/pages/10012-rails/suggestions/103508-support-dependent-restrict-and-dependent-nullify"&gt;&lt;em&gt;restrict&lt;/em&gt;&lt;/a&gt;
 deletion of a record with dependencies. ActiveRecord doesn’t support this.&lt;/p&gt;


	&lt;p&gt;Think of an e-commerce system where a user has many orders. Once an order has gone through, you shouldn’t be able to delete the user who placed the order. You need a record of the order and the user who placed it.&lt;/p&gt;


	&lt;p&gt;Or even more obvious, think of a lookup table. An Order might have several of these dependencies; OrderStatus, Currency, DiscountLevel, etc. In all of these cases, you want &lt;code&gt;ON DELETE restrict&lt;/code&gt;, not &lt;code&gt;ON DELETE cascade&lt;/code&gt;. But Rails doesn’t support this. That’s dumb.&lt;/p&gt;


	&lt;p&gt;If you agree, head on over to the Rails UserVoice site and make your opinion known! &lt;a href="http://rails.uservoice.com/pages/10012-rails/suggestions/103508-support-dependent-restrict-and-dependent-nullify"&gt;There is a ticket&lt;/a&gt; for this already. Vote it up if you think Rails should implement this.&lt;/p&gt;


	&lt;p&gt;The solution to the problem is really pretty simple. ActiveRecord just needs something like this:&lt;/p&gt;


&lt;table class="CodeRay"&gt;&lt;tr&gt;
  &lt;td title="click to toggle" class="line_numbers"&gt;&lt;pre&gt;1&lt;tt&gt;
&lt;/tt&gt;2&lt;tt&gt;
&lt;/tt&gt;3&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class="code"&gt;&lt;pre&gt;&lt;span class="r"&gt;class&lt;/span&gt; &lt;span class="cl"&gt;User&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;  has_many &lt;span class="sy"&gt;:posts&lt;/span&gt;, &lt;span class="sy"&gt;:dependent&lt;/span&gt; =&amp;gt; &lt;span class="sy"&gt;:restrict&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;span class="r"&gt;end&lt;/span&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;


	&lt;p&gt;In this case, if you try to destroy a user that has one or more posts, Rails should complain. You’ve told the app: “Don’t let me delete users who have posts!” The easiest way to do this is to have Rails throw an exception, and have your controller capture the exception and print a flash message. Other approaches could work too.&lt;/p&gt;


	&lt;p&gt;So why is this important?&lt;/p&gt;


	&lt;p&gt;1. It’s common. Every project should maintain referential integrity in some way, and :dependent =&amp;gt; :destroy isn’t always appropriate. Who wants to do a cascading delete from roles to users, or manufacturers to products, or order_statuses to orders? I don’t think I’ve ever worked on a project where cascading deletes were always appropriate. Any lookup table, at minimum, needs this feature. (I personally prefer to maintain referential integrity with foreign keys, but even still, I’d love to have an application-level check first, which would be easier to rescue. And some projects don’t use foreign keys.)&lt;/p&gt;


	&lt;p&gt;2. It fits with the Rails philosophy. Rails says “Let your application handle referential integrity, not the database”. But without :dependent =&amp;gt; :restrict, one of the most important pieces of referential integrity is missing.&lt;/p&gt;


	&lt;p&gt;3. It’s easy. 9 lines of code to add this to has_many. Check out this gist: &lt;a href="http://gist.github.com/170059"&gt;http://gist.github.com/170059&lt;/a&gt;.&lt;/p&gt;


	&lt;p&gt;Someone wrote a &lt;a href="http://github.com/scambra/dependent_protect/tree/master"&gt;plugin&lt;/a&gt; for this, but it has the distinct disadvantage of not working anymore. This should really be a core feature anyway, at least as long as &lt;code&gt;:dependent =&amp;gt; :destroy&lt;/code&gt; is a core feature.&lt;/p&gt;


	&lt;p&gt;The UserVoice suggestion for this is at &lt;a href="http://rails.uservoice.com/pages/10012-rails/suggestions/103508-support-dependent-restrict-and-dependent-nullify"&gt;http://rails.uservoice.com/pages/10012-rails/suggestions/103508-support-dependent-restrict-and-dependent-nullify&lt;/a&gt;.&lt;/p&gt;
          &lt;img src="http://feeds.feedburner.com/~r/RailSpikes/~4/y1Nno8ZfSR0" height="1" width="1"/&gt;</content>  <feedburner:origLink>http://railspikes.com/2009/8/19/activerecord-refererential-integrity-is-broken-let-s-fix-it</feedburner:origLink></entry>
  <entry xml:base="http://railspikes.com/">
    <author>
      <name>Luke Francl</name>
    </author>
    <id>tag:railspikes.com,2009-08-10:2018</id>
    <published>2009-08-10T06:21:00Z</published>
    <updated>2009-08-10T06:24:00Z</updated>
    <category term="gem" />
    <link href="http://feedproxy.google.com/~r/RailSpikes/~3/dje2MF31MFo/weird-gem-error" rel="alternate" type="text/html" />
    <title>Weird Gem Error</title>
<content type="html">
            &lt;p&gt;Talk about a hard problem to diagnose!&lt;/p&gt;


	&lt;p&gt;I canceled the installation of Rack 1.0 half way through because I realized I was running the wrong command (I didn’t use &lt;code&gt;sudo&lt;/code&gt; like I wanted to).&lt;/p&gt;


	&lt;p&gt;After that, I couldn’t load rack at all, even though I could see it in my gems directory and I could load other gems there. I got a LoadError, like this:&lt;/p&gt;


&lt;pre&gt;&lt;code&gt;irb(main):001:0&gt; require 'rubygems'
=&gt; true
irb(main):002:0&gt; require 'rack'
LoadError: no such file to load -- rack
from /usr/local/lib/site_ruby/1.8/rubygems/custom_require.rb:31:in `gem_original_require'
from /usr/local/lib/site_ruby/1.8/rubygems/custom_require.rb:31:in `require'
from (irb):2
&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;I tried downgrading Rails to the version that used Rack 0.9.1 and then I got an error saying Rails couldn’t activate Rack 0.9.1 because 1.0.0 was already active!&lt;/p&gt;


	&lt;p&gt;Finally figured it out—there was a gemspec for rack-1.0.0 in my &lt;code&gt;~/.gems&lt;/code&gt; directory, but no corresponding gem in the lib directory. Ugh!&lt;/p&gt;
          &lt;img src="http://feeds.feedburner.com/~r/RailSpikes/~4/dje2MF31MFo" height="1" width="1"/&gt;</content>  <feedburner:origLink>http://railspikes.com/2009/8/10/weird-gem-error</feedburner:origLink></entry>
  <entry xml:base="http://railspikes.com/">
    <author>
      <name>Jon</name>
    </author>
    <id>tag:railspikes.com,2009-07-29:2014</id>
    <published>2009-07-29T17:38:00Z</published>
    <updated>2009-07-29T17:38:43Z</updated>
    <category term="Programming" />
    <category term="rails2.3.3" />
    <link href="http://feedproxy.google.com/~r/RailSpikes/~3/NDD9jzPvby4/rails-2-3-3-upgrade-notes" rel="alternate" type="text/html" />
    <title>Rails 2.3.3 upgrade notes: rack, mocha, and _ids</title>
<content type="html">
            &lt;p&gt;I upgraded two apps to &lt;a href="http://weblog.rubyonrails.org/2009/7/20/rails-2-3-3-touching-faster-json-bug-fixes"&gt;Rails 2.3.3&lt;/a&gt; today. It’s a minor release, and there’s not much to report. But I did run into three minor problems.&lt;/p&gt;


	&lt;h4&gt;Mocha&lt;/h4&gt;


	&lt;p&gt;Mocha 0.9.5 started throwing an exception:&lt;/p&gt;


	&lt;p&gt;&lt;code&gt;NameError: uninitialized constant Mocha::Mockery::ImpersonatingAnyInstanceName&lt;/code&gt;&lt;/p&gt;


	&lt;p&gt;A quick update to Mocha 0.9.7 cleared this up.&lt;/p&gt;


	&lt;h4&gt;Array parameters in tests&lt;/h4&gt;


	&lt;p&gt;In functional tests with Test::Unit, passing an array to a parameter stopped working. Previously, I had something like this:&lt;/p&gt;


&lt;table class="CodeRay"&gt;&lt;tr&gt;
  &lt;td title="click to toggle" class="line_numbers"&gt;&lt;pre&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class="code"&gt;&lt;pre&gt;post &lt;span class="sy"&gt;:create&lt;/span&gt;, &lt;span class="sy"&gt;:user&lt;/span&gt; =&amp;gt; {&lt;span class="sy"&gt;:role_ids&lt;/span&gt; =&amp;gt; [&lt;span class="i"&gt;1&lt;/span&gt;,&lt;span class="i"&gt;2&lt;/span&gt;,&lt;span class="i"&gt;3&lt;/span&gt;]}&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;


	&lt;p&gt;This would post the following parameters:&lt;/p&gt;


&lt;table class="CodeRay"&gt;&lt;tr&gt;
  &lt;td title="click to toggle" class="line_numbers"&gt;&lt;pre&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class="code"&gt;&lt;pre&gt;&lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;role_ids&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;=&amp;gt;[&lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;1&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;, &lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;2&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;, &lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;3&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;]&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;


	&lt;p&gt;But after the 2.3.3 update, I started seeing an error:&lt;/p&gt;


	&lt;p&gt;&lt;code&gt;NoMethodError: undefined method `each' for 1:Fixnum&lt;/code&gt;&lt;/p&gt;


	&lt;p&gt;I’m not sure why this stopped working. (Anyone know?) Changing the integers to strings clears up the error:&lt;/p&gt;


&lt;table class="CodeRay"&gt;&lt;tr&gt;
  &lt;td title="click to toggle" class="line_numbers"&gt;&lt;pre&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class="code"&gt;&lt;pre&gt;post &lt;span class="sy"&gt;:create&lt;/span&gt;, &lt;span class="sy"&gt;:user&lt;/span&gt; =&amp;gt; {&lt;span class="sy"&gt;:role_ids&lt;/span&gt; =&amp;gt; [&lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;1&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;,&lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;2&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;,&lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;3&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;]}&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;


	&lt;p&gt;Or&lt;/p&gt;


&lt;table class="CodeRay"&gt;&lt;tr&gt;
  &lt;td title="click to toggle" class="line_numbers"&gt;&lt;pre&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class="code"&gt;&lt;pre&gt;post &lt;span class="sy"&gt;:create&lt;/span&gt;, &lt;span class="sy"&gt;:user&lt;/span&gt; =&amp;gt; {&lt;span class="sy"&gt;:role_ids&lt;/span&gt; =&amp;gt; [&lt;span class="i"&gt;1&lt;/span&gt;.to_s,&lt;span class="i"&gt;2&lt;/span&gt;.to_s,&lt;span class="i"&gt;3&lt;/span&gt;.to_s]}&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;


	&lt;h4&gt;Rack&lt;/h4&gt;


	&lt;p&gt;Rack apparently no longer comes bundled with Rails. Or at least deployment failed on cap deploy: &lt;code&gt;RubyGem version error: rack(0.4.0 not ~&amp;gt; 1.0.0)&lt;/code&gt;.&lt;/p&gt;


	&lt;p&gt;The solution was simple: install (or vendor) Rack 1.0.0.&lt;/p&gt;


&lt;table class="CodeRay"&gt;&lt;tr&gt;
  &lt;td title="click to toggle" class="line_numbers"&gt;&lt;pre&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class="code"&gt;&lt;pre&gt;config.gem &lt;span class="s"&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="k"&gt;rack&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;/span&gt;, &lt;span class="sy"&gt;:version&lt;/span&gt; =&amp;gt; &lt;span class="s"&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="k"&gt;&amp;gt;= 1.0.0&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;
          &lt;img src="http://feeds.feedburner.com/~r/RailSpikes/~4/NDD9jzPvby4" height="1" width="1"/&gt;</content>  <feedburner:origLink>http://railspikes.com/2009/7/29/rails-2-3-3-upgrade-notes</feedburner:origLink></entry>
  <entry xml:base="http://railspikes.com/">
    <author>
      <name>Luke Francl</name>
    </author>
    <id>tag:railspikes.com,2009-07-20:2011</id>
    <published>2009-07-20T04:28:00Z</published>
    <updated>2009-07-20T04:30:04Z</updated>
    <category term="tips" />
    <link href="http://feedproxy.google.com/~r/RailSpikes/~3/x6i3xoMxuSo/validates_length_of-gotcha" rel="alternate" type="text/html" />
    <title>validates_length_of byte counting gotcha </title>
<content type="html">
            &lt;p&gt;Watch out for &lt;code&gt;validates_length_of&lt;/code&gt; if you need to make sure a string is a certain number of &lt;em&gt;bytes&lt;/em&gt; long. For example, &lt;span class="caps"&gt;SMS&lt;/span&gt; messages can be no longer than 160 bytes in length. I recently got bit by this because some unicode “curly” quotes slipped into a reply message, but they weren’t detected by the validation.&lt;/p&gt;


	&lt;p&gt;Here’s the problem.&lt;/p&gt;


	&lt;p&gt;Consider this string:&lt;/p&gt;


	&lt;p&gt;&lt;code&gt;str = "€"&lt;/code&gt;&lt;/p&gt;


	&lt;p&gt;It is 3 bytes long:&lt;/p&gt;


	&lt;p&gt;&lt;code&gt;str.size =&amp;gt; 3&lt;/code&gt;&lt;/p&gt;


	&lt;p&gt;However, ActiveRecord’s &lt;code&gt;validates_length_of&lt;/code&gt; records this as only one character, because it uses &lt;code&gt;str.split(//).size&lt;/code&gt; to measure the size.&lt;/p&gt;


	&lt;p&gt;If you &lt;span class="caps"&gt;NEED&lt;/span&gt; to be certain that a string is less than a certain number of bytes, you’ll need to override the default behavior of &lt;code&gt;validate_length_of&lt;/code&gt;.&lt;/p&gt;


	&lt;p&gt;Fortunately, you can supply your own tokenizer, which makes this easy. The tokenizer is called, and &lt;code&gt;size&lt;/code&gt; is called on its return value to find out how many tokens there are. Since &lt;code&gt;String&lt;/code&gt; responds to &lt;code&gt;size&lt;/code&gt; which returns the number of bytes, you can simply return the attribute value itself as the tokenizer, like this:&lt;/p&gt;


	&lt;p&gt;&lt;code&gt;validates_length_of :message, :maximum =&amp;gt; 160, :tokenizer =&amp;gt; lambda { |str| str }&lt;/code&gt;&lt;/p&gt;


	&lt;p&gt;Will this still work in Ruby 1.9? I’m not sure. I now have a test case which will warn me if it doesn’t…&lt;/p&gt;
          &lt;img src="http://feeds.feedburner.com/~r/RailSpikes/~4/x6i3xoMxuSo" height="1" width="1"/&gt;</content>  <feedburner:origLink>http://railspikes.com/2009/7/20/validates_length_of-gotcha</feedburner:origLink></entry>
  <entry xml:base="http://railspikes.com/">
    <author>
      <name>Luke Francl</name>
    </author>
    <id>tag:railspikes.com,2009-07-09:2006</id>
    <published>2009-07-09T04:28:00Z</published>
    <updated>2009-07-09T04:31:16Z</updated>
    <category term="conference" />
    <link href="http://feedproxy.google.com/~r/RailSpikes/~3/Sx-S_kWp7To/futureruby" rel="alternate" type="text/html" />
    <title>FutureRuby!</title>
<content type="html">
            &lt;p&gt;Jon and I will be at &lt;a href="http://futureruby.com"&gt;FutureRuby&lt;/a&gt; this weekend (actually, &lt;em&gt;I&lt;/em&gt; will be there, and &lt;em&gt;Jon&lt;/em&gt; will be &lt;a href="http://futureruby.com/speakers/"&gt;speaking&lt;/a&gt;).&lt;/p&gt;


	&lt;p&gt;Say “hi” if you see us. I’m flying into Toronto Thursday for FAILcamp.&lt;/p&gt;
          &lt;img src="http://feeds.feedburner.com/~r/RailSpikes/~4/Sx-S_kWp7To" height="1" width="1"/&gt;</content>  <feedburner:origLink>http://railspikes.com/2009/7/9/futureruby</feedburner:origLink></entry>
  <entry xml:base="http://railspikes.com/">
    <author>
      <name>Luke Francl</name>
    </author>
    <id>tag:railspikes.com,2009-07-01:2004</id>
    <published>2009-07-01T01:44:00Z</published>
    <updated>2009-07-01T01:44:29Z</updated>
    <category term="testing" />
    <category term="tips" />
    <link href="http://feedproxy.google.com/~r/RailSpikes/~3/OyM5ReRqqRY/testing-http-authentication" rel="alternate" type="text/html" />
    <title>Testing HTTP Authentication</title>
<content type="html">
            &lt;p&gt;If you ever need to test &lt;span class="caps"&gt;HTTP&lt;/span&gt; Authentication in your &lt;em&gt;functional&lt;/em&gt; tests, here is how you do it:&lt;/p&gt;


&lt;table class="CodeRay"&gt;&lt;tr&gt;
  &lt;td title="click to toggle" class="line_numbers"&gt;&lt;pre&gt;1&lt;tt&gt;
&lt;/tt&gt;2&lt;tt&gt;
&lt;/tt&gt;3&lt;tt&gt;
&lt;/tt&gt;4&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;5&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;6&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class="code"&gt;&lt;pre&gt;&lt;span class="r"&gt;def&lt;/span&gt; &lt;span class="fu"&gt;test_http_auth&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;  &lt;span class="iv"&gt;@request&lt;/span&gt;.env[&lt;span class="s"&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="k"&gt;HTTP_AUTHORIZATION&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;/span&gt;] = &lt;span class="co"&gt;ActionController&lt;/span&gt;::&lt;span class="co"&gt;HttpAuthentication&lt;/span&gt;::&lt;span class="co"&gt;Basic&lt;/span&gt;.encode_credentials(&lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;quentin&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;, &lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;password&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;)&lt;tt&gt;
&lt;/tt&gt;  get &lt;span class="sy"&gt;:show&lt;/span&gt;, &lt;span class="sy"&gt;:id&lt;/span&gt; =&amp;gt; &lt;span class="iv"&gt;@foobar&lt;/span&gt;.id&lt;tt&gt;
&lt;/tt&gt;&lt;tt&gt;
&lt;/tt&gt;  assert_response &lt;span class="sy"&gt;:success&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;span class="r"&gt;end&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;


	&lt;p&gt;This is much like &lt;a href="http://railspikes.com/2008/9/12/testing-ssl"&gt;testing &lt;span class="caps"&gt;SSL&lt;/span&gt;&lt;/a&gt;.&lt;/p&gt;


	&lt;p&gt;Hat tip: Philipp Führer for &lt;a href="http://flip.netzbeben.de/2008/06/functional-test-for-http-authentication-in-rails-2/"&gt;Functional test for &lt;span class="caps"&gt;HTTP&lt;/span&gt; Basic Authentication in Rails 2&lt;/a&gt;.&lt;/p&gt;
          &lt;img src="http://feeds.feedburner.com/~r/RailSpikes/~4/OyM5ReRqqRY" height="1" width="1"/&gt;</content>  <feedburner:origLink>http://railspikes.com/2009/7/1/testing-http-authentication</feedburner:origLink></entry>
  <entry xml:base="http://railspikes.com/">
    <author>
      <name>Luke Francl</name>
    </author>
    <id>tag:railspikes.com,2009-06-22:1999</id>
    <published>2009-06-22T22:25:00Z</published>
    <updated>2009-06-25T06:41:10Z</updated>
    <category term="routes" />
    <category term="testing" />
    <category term="tips" />
    <link href="http://feedproxy.google.com/~r/RailSpikes/~3/of6fyG4oAyk/adding-routes-for-tests" rel="alternate" type="text/html" />
    <title>Adding Routes for Tests</title>
<content type="html">
            &lt;p&gt;I like to be extremely judicious with use of routes. Fewer routes means less memory consumption and fewer confusing magical methods.&lt;/p&gt;


	&lt;p&gt;I always delete the default route &lt;code&gt;map.connect ':controller/:action/:id'&lt;/code&gt; (you should too, otherwise all your pretty RESTful routing is easily circumvented). Since Rails now has the ability to remove unneeded RESTful routes, I’ve been removing those, too.&lt;/p&gt;


	&lt;p&gt;However, this judiciousness recently painted me into a corner. I have a controller action that I would like to test and it’s wired up like this:&lt;/p&gt;


	&lt;p&gt;&lt;code&gt;map.logout '/logout', :controller =&amp;gt; 'user_sessions', :action =&amp;gt; 'destroy', :method =&amp;gt; 'delete'&lt;/code&gt;&lt;/p&gt;


	&lt;p&gt;I don’t have this mapped any other way, because why should I?&lt;/p&gt;


&lt;table class="CodeRay"&gt;&lt;tr&gt;
  &lt;td title="click to toggle" class="line_numbers"&gt;&lt;pre&gt;1&lt;tt&gt;
&lt;/tt&gt;2&lt;tt&gt;
&lt;/tt&gt;3&lt;tt&gt;
&lt;/tt&gt;4&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;5&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;6&lt;tt&gt;
&lt;/tt&gt;7&lt;tt&gt;
&lt;/tt&gt;8&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class="code"&gt;&lt;pre&gt;&lt;span class="r"&gt;def&lt;/span&gt; &lt;span class="fu"&gt;test_logout_should_redirect_to_root_path&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;  &lt;span class="co"&gt;UserSession&lt;/span&gt;.create(&lt;span class="co"&gt;User&lt;/span&gt;.first)&lt;tt&gt;
&lt;/tt&gt;&lt;tt&gt;
&lt;/tt&gt;  delete &lt;span class="sy"&gt;:destroy&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;tt&gt;
&lt;/tt&gt;  assert_match &lt;span class="rx"&gt;&lt;span class="dl"&gt;/&lt;/span&gt;&lt;span class="k"&gt;logged out&lt;/span&gt;&lt;span class="dl"&gt;/&lt;/span&gt;&lt;/span&gt;, flash[&lt;span class="sy"&gt;:notice&lt;/span&gt;]&lt;tt&gt;
&lt;/tt&gt;  assert_redirected_to root_path&lt;tt&gt;
&lt;/tt&gt;&lt;span class="r"&gt;end&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;


	&lt;p&gt;Unfortunately, the test fails with &lt;code&gt;ActionController::RoutingError: No route matches {:action=&amp;gt;"destroy", :controller=&amp;gt;"user_sessions"}&lt;/code&gt;! Huh?&lt;/p&gt;


	&lt;p&gt;The problem is that the &lt;code&gt;delete&lt;/code&gt; (and &lt;code&gt;get&lt;/code&gt;, &lt;code&gt;post&lt;/code&gt;, etc.) method can’t find the route that I created.&lt;/p&gt;


	&lt;p&gt;Initially, I worked around this using &lt;code&gt;with_routing&lt;/code&gt; to define a whole new set of routes just for that test.&lt;/p&gt;


&lt;table class="CodeRay"&gt;&lt;tr&gt;
  &lt;td title="click to toggle" class="line_numbers"&gt;&lt;pre&gt;1&lt;tt&gt;
&lt;/tt&gt;2&lt;tt&gt;
&lt;/tt&gt;3&lt;tt&gt;
&lt;/tt&gt;4&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;5&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;6&lt;tt&gt;
&lt;/tt&gt;7&lt;tt&gt;
&lt;/tt&gt;8&lt;tt&gt;
&lt;/tt&gt;9&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;10&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;11&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class="code"&gt;&lt;pre&gt;with_routing &lt;span class="r"&gt;do&lt;/span&gt; |set|&lt;tt&gt;
&lt;/tt&gt;  set.draw &lt;span class="r"&gt;do&lt;/span&gt; |map|&lt;tt&gt;
&lt;/tt&gt;    map.resource &lt;span class="sy"&gt;:user_sessions&lt;/span&gt;, &lt;span class="sy"&gt;:only&lt;/span&gt; =&amp;gt; [&lt;span class="sy"&gt;:destroy&lt;/span&gt;]&lt;tt&gt;
&lt;/tt&gt;    map.root &lt;span class="sy"&gt;:controller&lt;/span&gt; =&amp;gt; &lt;span class="s"&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="k"&gt;foobars&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;/span&gt;, &lt;span class="sy"&gt;:action&lt;/span&gt; =&amp;gt; &lt;span class="s"&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="k"&gt;index&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;  &lt;span class="r"&gt;end&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;tt&gt;
&lt;/tt&gt;  delete &lt;span class="sy"&gt;:destroy&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;tt&gt;
&lt;/tt&gt;  assert_match &lt;span class="rx"&gt;&lt;span class="dl"&gt;/&lt;/span&gt;&lt;span class="k"&gt;logged out&lt;/span&gt;&lt;span class="dl"&gt;/&lt;/span&gt;&lt;/span&gt;, flash[&lt;span class="sy"&gt;:notice&lt;/span&gt;]&lt;tt&gt;
&lt;/tt&gt;  assert_redirected_to root_path&lt;tt&gt;
&lt;/tt&gt;&lt;span class="r"&gt;end&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;


	&lt;p&gt;But that was annoying. And after I had more than one route exhibiting this problem, it got &lt;em&gt;really&lt;/em&gt; annoying.&lt;/p&gt;


	&lt;p&gt;Fortunately, I found Sam Ruby’s post &lt;a href="http://intertwingly.net/blog/2009/05/15/Keeping-Up-With-Rails"&gt;Keeping Up With Rails&lt;/a&gt; about the challenge of Rails’ minor, quasi-documented &lt;span class="caps"&gt;API&lt;/span&gt; changes. Sam’s post has a bit about how you can add new routes without clearing the existing routes in Rails 2.3.2, which I knew was possible. Following Sam’s link to &lt;a href="http://github.com/rails/rails/commit/40b40c487040d9c721d486e8ec8cfbc53a8cd79a"&gt;the commit&lt;/a&gt; (there’s no docs for this) showed how to do it.&lt;/p&gt;


	&lt;p&gt;Now, I’ve added this to &lt;code&gt;test_helper.rb&lt;/code&gt;:&lt;/p&gt;


&lt;table class="CodeRay"&gt;&lt;tr&gt;
  &lt;td title="click to toggle" class="line_numbers"&gt;&lt;pre&gt;1&lt;tt&gt;
&lt;/tt&gt;2&lt;tt&gt;
&lt;/tt&gt;3&lt;tt&gt;
&lt;/tt&gt;4&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class="code"&gt;&lt;pre&gt;&lt;span class="r"&gt;class&lt;/span&gt; &lt;span class="cl"&gt;ActionController::TestCase&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;  &lt;span class="c"&gt;# add a catch-all route for the tests only.&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt; &lt;span class="co"&gt;ActionController&lt;/span&gt;::&lt;span class="co"&gt;Routing&lt;/span&gt;::&lt;span class="co"&gt;Routes&lt;/span&gt;.draw { |map| map.connect &lt;span class="s"&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="k"&gt;:controller/:action/:id&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;/span&gt; }&lt;tt&gt;
&lt;/tt&gt;&lt;span class="r"&gt;end&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;


	&lt;p&gt;The downside to this is that real problems with broken routes may get swept under the rug. You could be more restrictive with the routes you are adding just for tests to overcome that problem.&lt;/p&gt;


	&lt;p&gt;&lt;strong&gt;Update:&lt;/strong&gt; Thanks to Adam Cigánek in the comments for pointing out my error in why the route didn’t get picked up in the tests. &lt;em&gt;I had the condition hash wrong!&lt;/em&gt;&lt;/p&gt;


	&lt;p&gt;Instead of:&lt;/p&gt;


	&lt;p&gt;&lt;code&gt;map.logout '/logout', :controller =&amp;gt; 'user_sessions', :action =&amp;gt; 'destroy', :method =&amp;gt; 'delete'&lt;/code&gt;&lt;/p&gt;


	&lt;p&gt;It should be:&lt;/p&gt;


	&lt;p&gt;&lt;code&gt;map.logout '/logout', :controller =&amp;gt; 'user_sessions', :action =&amp;gt; 'destroy', :conditions =&amp;gt; {:method =&amp;gt; :delete}&lt;/code&gt;&lt;/p&gt;


	&lt;p&gt;The first way I had worked correctly when testing manually, but only because without &lt;code&gt;:method&lt;/code&gt;, the route responds to all &lt;span class="caps"&gt;HTTP&lt;/span&gt; methods (still no clue why my test didn’t pick it up, though).&lt;/p&gt;


	&lt;p&gt;Interestingly enough, there’s another gotcha here. Notice that I specified &lt;code&gt;:method =&amp;gt; 'delete'&lt;/code&gt;. Even when put into the &lt;code&gt;:conditions&lt;/code&gt; hash, that doesn’t work. You &lt;span class="caps"&gt;MUST&lt;/span&gt; pass a symbol (&lt;code&gt;:delete&lt;/code&gt;) for the &lt;span class="caps"&gt;HTTP&lt;/span&gt; method.&lt;/p&gt;


	&lt;p&gt;This fixed my problem, but if I ever do need to add routes for tests, now I know how…&lt;/p&gt;
          &lt;img src="http://feeds.feedburner.com/~r/RailSpikes/~4/of6fyG4oAyk" height="1" width="1"/&gt;</content>  <feedburner:origLink>http://railspikes.com/2009/6/22/adding-routes-for-tests</feedburner:origLink></entry>
  <entry xml:base="http://railspikes.com/">
    <author>
      <name>Luke Francl</name>
    </author>
    <id>tag:railspikes.com,2009-06-17:1989</id>
    <published>2009-06-17T20:51:00Z</published>
    <updated>2009-06-17T20:54:57Z</updated>
    <category term="javascript" />
    <category term="tips" />
    <link href="http://feedproxy.google.com/~r/RailSpikes/~3/DScbpAz3dIw/javascript-gotcha-storing-objects-in-an-associative-array" rel="alternate" type="text/html" />
    <title>JavaScript gotcha: storing objects in an associative array</title>
<content type="html">
            &lt;p&gt;I just ran into a tricky gotcha in JavaScript.&lt;/p&gt;


	&lt;p&gt;I was trying to store some objects in an associative array. Based on my experience with Java, Ruby, and other languages, I expected that given code like this:&lt;/p&gt;


&lt;table class="CodeRay"&gt;&lt;tr&gt;
  &lt;td title="click to toggle" class="line_numbers"&gt;&lt;pre&gt;1&lt;tt&gt;
&lt;/tt&gt;2&lt;tt&gt;
&lt;/tt&gt;3&lt;tt&gt;
&lt;/tt&gt;4&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;5&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;6&lt;tt&gt;
&lt;/tt&gt;7&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class="code"&gt;&lt;pre&gt;&lt;span class="r"&gt;var&lt;/span&gt; dictionary = {};&lt;tt&gt;
&lt;/tt&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;span class="r"&gt;var&lt;/span&gt; obj1 = {}; &lt;tt&gt;
&lt;/tt&gt;&lt;span class="r"&gt;var&lt;/span&gt; obj2 = {};&lt;tt&gt;
&lt;/tt&gt;&lt;tt&gt;
&lt;/tt&gt;dictionary[obj1] = &lt;span class="s"&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="k"&gt;foo&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;dictionary[obj2] = &lt;span class="s"&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="k"&gt;bar&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;


	&lt;p&gt;The result of &lt;code&gt;dictionary[obj1]&lt;/code&gt; would be ‘foo’ and &lt;code&gt;dictionary[obj2]&lt;/code&gt; would be ‘bar’.&lt;/p&gt;


	&lt;p&gt;This is not the case!&lt;/p&gt;


	&lt;p&gt;The problem is that JavaScript objects are not really hash tables. They’re associative arrays, and the key can &lt;em&gt;only&lt;/em&gt; be a String. When you insert an object into a associative array, &lt;code&gt;toString()&lt;/code&gt; is called and that is used as the key. Unfortunately, the default &lt;code&gt;toString&lt;/code&gt; implementation for JavaScript objects returns “[object Object]”...which is not only very unhelpful when debugging, but doesn’t provide you with a unique key for your associative array.&lt;/p&gt;


	&lt;p&gt;You can work around this problem by overriding &lt;code&gt;toString&lt;/code&gt;. Or you can figure out another way to associate your object with a value. D’oh!&lt;/p&gt;
          &lt;img src="http://feeds.feedburner.com/~r/RailSpikes/~4/DScbpAz3dIw" height="1" width="1"/&gt;</content>  <feedburner:origLink>http://railspikes.com/2009/6/17/javascript-gotcha-storing-objects-in-an-associative-array</feedburner:origLink></entry>
  <entry xml:base="http://railspikes.com/">
    <author>
      <name>Luke Francl</name>
    </author>
    <id>tag:railspikes.com,2009-06-04:1978</id>
    <published>2009-06-04T16:39:00Z</published>
    <updated>2009-06-04T16:42:50Z</updated>
    <category term="provisioning" />
    <category term="sprinkle" />
    <link href="http://feedproxy.google.com/~r/RailSpikes/~3/aTF68B6HJg8/sprinkle" rel="alternate" type="text/html" />
    <title>Sprinkle: the provisioning tool for people who don't have huge server clusters</title>
<content type="html">
            &lt;p&gt;I’ve recently been trying to find a good server automation tool that meets my needs. I looked at &lt;a href="http://wiki.opscode.com/display/chef/Home"&gt;Chef&lt;/a&gt; and &lt;a href="http://reductivelabs.com/trac/puppet/"&gt;Puppet&lt;/a&gt;.&lt;/p&gt;


	&lt;p&gt;They are both awesome for what they do, but what I don’t like is all the infrastructure I have to maintain to run Chef or Puppet. You need a server to host your server configuration on. But I only have one server![1] Chef does have a &lt;a href="http://wiki.opscode.com/display/chef/Chef+Solo"&gt;solo version&lt;/a&gt; which can download configuration from a web server and run it. That’s cool, but I don’t want to have a web server just for putting server configuration on.&lt;/p&gt;


	&lt;p&gt;When the time commitment to set up one of these tools up greatly exceeds how long it is for me to bring up a new slice and run through the standard Apache/DB/Passenger stack, I lose interest. In the end, these are great tools for managing a cluster of machines and bringing up a new app in the cluster quickly—and keeping it up to date automatically. If you have big infrastructure needs, they make sense. If you just want to set up a single slice…ugh.&lt;/p&gt;


	&lt;p&gt;After reading a bit about how Puppet and Chef work, what I really wanted was the ability to &lt;em&gt;push&lt;/em&gt; server provisioning recipes. I want to maintain the server config in my repository and then provision a new server with a command I run on my machine. Sort of like &lt;a href="http://deprec.failmode.com/"&gt;deprec&lt;/a&gt;, but understandable.&lt;/p&gt;


	&lt;p&gt;Fortunately, I found &lt;a href="http://github.com/crafterm/sprinkle/tree/master"&gt;Sprinkle&lt;/a&gt; and &lt;a href="http://benschwarz.github.com/passenger-stack/"&gt;passenger-stack&lt;/a&gt;.&lt;/p&gt;


	&lt;p&gt;Sprinkle lets me quickly define which packages I want installed and push it out to a server to run (via Capistrano, Vlad, or Net::SSH). Sprinkle makes it easy to install software using apt, gem, or source. And unlike a simple shell script, Sprinkle tests whether or not the software is installed before running, and has a concept of dependencies.&lt;/p&gt;


	&lt;p&gt;Passenger-stack removes the pain of writing my own rules for what to install. It comes with the standard stuff you’d need, and you can customize it from there.&lt;/p&gt;


	&lt;p&gt;Here’s how you install all the software you need for a fresh server, after downloading &lt;a href="http://benschwarz.github.com/passenger-stack/"&gt;passenger-stack&lt;/a&gt;:&lt;/p&gt;


	&lt;p&gt;&lt;code&gt;sprinkle -c -s config/install.rb&lt;/code&gt;&lt;/p&gt;


	&lt;p&gt;The best part is that you can run that command again, and it won’t do anything. So you can add new software to your stack, then run it against your server, and only the new software will get installed.&lt;/p&gt;


	&lt;p&gt;This gives you a great way to manage natively compiled gems and ensure that if you ever need to spin up a staging server or a demo server, everything you need gets installed.&lt;/p&gt;


	&lt;p&gt;Check out this screencast by Ben Schwartz, author of passenger-stack.&lt;/p&gt;


&amp;lt;object height="360" width="640"&gt;&amp;lt;param /&gt;&amp;lt;param /&gt;&amp;lt;param /&gt;&amp;lt;embed src="http://vimeo.com/moogaloop.swf?clip_id=2888665&amp;amp;amp;server=vimeo.com&amp;amp;amp;show_title=1&amp;amp;amp;show_byline=1&amp;amp;amp;show_portrait=0&amp;amp;amp;color=00ADEF&amp;amp;amp;fullscreen=1" height="360" width="640"&gt;&amp;lt;/embed&gt;&amp;lt;/object&gt;&lt;p&gt;&lt;a href="http://vimeo.com/2888665"&gt;Passenger-stack demo&lt;/a&gt; from &lt;a href="http://vimeo.com/user1015730"&gt;Ben Schwarz&lt;/a&gt; on &lt;a href="http://vimeo.com"&gt;Vimeo&lt;/a&gt;.&lt;/p&gt;

	&lt;p&gt;It’s not a smart as Chef and Puppet. It’s not transactional and servers don’t check for new software to install automatically. But it sure is easy. That’s why I call &lt;a href="http://github.com/crafterm/sprinkle/tree/master"&gt;Sprinkle&lt;/a&gt; “the provisioning tool for people who don’t have huge server clusters.”&lt;/p&gt;


	&lt;p&gt;&lt;sup&gt;1&lt;/sup&gt; Basically. I have many servers with many different applications on them. And I have a few servers that have multiple environments, but the same software. That’s my big driver for wanting a provisioning tool.&lt;/p&gt;
          &lt;img src="http://feeds.feedburner.com/~r/RailSpikes/~4/aTF68B6HJg8" height="1" width="1"/&gt;</content>  <feedburner:origLink>http://railspikes.com/2009/6/4/sprinkle</feedburner:origLink></entry>
  <entry xml:base="http://railspikes.com/">
    <author>
      <name>Jon</name>
    </author>
    <id>tag:railspikes.com,2009-06-02:1980</id>
    <published>2009-06-02T16:06:00Z</published>
    <updated>2009-06-02T16:27:48Z</updated>
    <category term="Business" />
    <category term="Programming" />
    <link href="http://feedproxy.google.com/~r/RailSpikes/~3/gl7KwwlhsUE/estimating-software-a-rule-of-thumb" rel="alternate" type="text/html" />
    <title>Estimating software: a rule of thumb</title>
<content type="html">
            &lt;p&gt;Estimating software is hard, but most of us have to do it – whether we’re estimating an entire project for a client, or a new feature for a boss, or  a change to one of our own projects.&lt;/p&gt;


	&lt;p&gt;I’ve found the following rule helpful when estimating software. This comes from about four years of estimating Rails projects to consulting clients, and moving from bad – dramatically underestimating fixed-bid projects – to pretty good – usually overestimating time &amp; materials projects slightly. (And more importantly, knowing when I can’t estimate, because the scope is too vague or too large.)&lt;/p&gt;


	&lt;h2&gt;Jon’s Law of Estimates&lt;/h2&gt;


	&lt;p&gt;Software difficulty is primarily determined by &lt;em&gt;volume&lt;/em&gt;, &lt;em&gt;logic&lt;/em&gt;, and &lt;em&gt;integration&lt;/em&gt;.&lt;/p&gt;


	&lt;h2&gt;Jon’s Law of Estimates, explained&lt;/h2&gt;


	&lt;p&gt;1. &lt;strong&gt;Volume&lt;/strong&gt; is easy to understand. If you’re building software that does more, it will require more work. So if you’re estimating a project that stores recipes, and you’re estimating another project that stores recipes &lt;span class="caps"&gt;AND&lt;/span&gt; shopping lists, you can expect that the second one will take more work (if everything else is equal).&lt;/p&gt;


	&lt;p&gt;2. &lt;strong&gt;Logic&lt;/strong&gt; refers to the rules or business logic behind a feature. The more rules there are, the more work there is. Imagine that our recipe system requires that recipes from some users are manually approved by an administrator, and checks to see that each ingredient in the recipe is present in the step-by-step instructions, and only allows a user to post 3 recipes per hour, and lets users propose alternative versions of a recipe, and lets an alternative version replace the regular version if it achieves a certain rating, etc. That’s more work than a recipe system that just lets users create and rate recipes, even though the volume of features may not be any larger.&lt;/p&gt;


	&lt;p&gt;Interestingly, a technology can make some logic trivial and some logic hard. &lt;a href="http://rails.uservoice.com/pages/rails3/suggestions/99641-nested-model-forms"&gt;Nested forms&lt;/a&gt; are a great example of this. Before Rails 2.3, Rails made it trivial to do &lt;span class="caps"&gt;CRUD&lt;/span&gt; on a single table at a time, but difficult handle multiple tables. Now it is (almost) trivial to do &lt;span class="caps"&gt;CRUD&lt;/span&gt; on multiple tables at a time.&lt;/p&gt;


	&lt;p&gt;3. &lt;strong&gt;Integration&lt;/strong&gt; points are usually deserving of special consideration in an estimate. This includes talking to a web services &lt;span class="caps"&gt;API&lt;/span&gt;, another local software system, a data feed, a complex library, etc. Not only do integration points often take time to get right, but they can become sinkholes of time when the documentation is inadequate or incorrect, the other system doesn’t play nice, or you can’t easily test the integration. And your estimate depends on something out of your control: the other system.&lt;/p&gt;


	&lt;h2&gt;External factors&lt;/h2&gt;


	&lt;p&gt;These rules only apply to the difficulty of the software. Several external factors are important as well. These include, most notably, the &lt;strong&gt;client&lt;/strong&gt; and the &lt;strong&gt;team&lt;/strong&gt;. The client can make a project easy, or they can make a project difficult. Similarly, the right team might be able to blaze through a project quickly, while the wrong team may never finish at all.&lt;/p&gt;


	&lt;h2&gt;The other side of estimating&lt;/h2&gt;


	&lt;p&gt;Here’s the thing about these rules: they’re relative, not absolute. There is no rule that says “Features take 5 days, and integration points take 10”. So estimating requires comparisons. This means that if you’ve never built a Rails app before, you’ll have trouble estimating a Rails project. But once you’ve built a few, you can compare the volume, logic, and integration points of a new project to volume, logic, and integration points of the previous ones.&lt;/p&gt;


	&lt;p&gt;So estimating requires intuition and experience as well as analysis (e.g. Jon’s Law of Estimates). The key to estimating is to combine analysis and intuition, and to let each side refine the other.&lt;/p&gt;
          &lt;img src="http://feeds.feedburner.com/~r/RailSpikes/~4/gl7KwwlhsUE" height="1" width="1"/&gt;</content>  <feedburner:origLink>http://railspikes.com/2009/6/2/estimating-software-a-rule-of-thumb</feedburner:origLink></entry>
  <entry xml:base="http://railspikes.com/">
    <author>
      <name>Luke Francl</name>
    </author>
    <id>tag:railspikes.com,2009-05-10:1972</id>
    <published>2009-05-10T20:07:00Z</published>
    <updated>2009-05-10T20:08:46Z</updated>
    <category term="twitter" />
    <link href="http://feedproxy.google.com/~r/RailSpikes/~3/M7sssUH-BB8/announcing-velotweets" rel="alternate" type="text/html" />
    <title>Announcing VeloTweets, Pulse of the Peloton</title>
<content type="html">
            &lt;p&gt;&lt;a href="http://velotweets.com"&gt;&lt;img src="http://img.skitch.com/20090510-1xh56ct6uya88idy4exf2gdmu9.png" height="" width=""&gt;&lt;/a&gt; I’m pleased to announce &lt;a href="http://velotweets.com"&gt;VeloTweets&lt;/a&gt;, the pulse of the peloton, a curated collection of professional cycling Twitter activity. The idea and driving force came from &lt;a href="http://www.thingelstad.com/"&gt;Jamie Thingelstad&lt;/a&gt;. I did most of the development, and &lt;a href="http://orstaddesign.com/"&gt;Norm Orstad&lt;/a&gt; designed the site. &lt;a href="http://twitter.com/mindtron"&gt;Chris Hatch&lt;/a&gt; helped a lot on the back end, providing a list of cyclists on Twitter, filling out profiles and affiliations, and doing research.&lt;/p&gt;


	&lt;h2&gt;What’s Different about VeloTweets?&lt;/h2&gt;


	&lt;p&gt;We wanted to make VeloTweets different than the other subject matter aggregators out there. We wanted a hook that would combine the immediacy of Twitter with pro cycling in a compelling way.&lt;/p&gt;


	&lt;p&gt;Here’s what we came up with.&lt;/p&gt;


	&lt;p&gt;First, we focused on who to include. Instead of everyone who’s talking about cycling, this contains only pro cyclists (and a few others associated with the sport, like managers or team mechanics).&lt;/p&gt;


	&lt;p&gt;Second, we extended the data that is given to us by Twitter. We can enter every cyclist’s real name, nationality, and team, as well as expanded biographical data (here’s &lt;a href="http://www.velotweets.com/profiles/10"&gt;Lance Armstrong’s profile&lt;/a&gt; for instance).&lt;/p&gt;


	&lt;p&gt;Third, we collected cycling events in a &lt;a href="http://www.velotweets.com/events"&gt;calendar&lt;/a&gt; that’s displayed on the site, and added a Message of the Day that’s tuned to what’s happening in the racing world each day.&lt;/p&gt;


	&lt;p&gt;Forth, we brought in photos from the tweets (only &lt;a href="http://twitpic.com"&gt;TwitPic&lt;/a&gt; is supported right now). We store references to the photos in our DB so we can show the latest photos, along with photos that individuals have posted, and &lt;a href="http://velotweets.com/photos"&gt;all of them&lt;/a&gt;. This turns out to be really cool because where else are you going to see &lt;a href="http://twitpic.com/4rut7"&gt;photos like this one&lt;/a&gt; as they happen?&lt;/p&gt;


	&lt;p&gt;After all this we still weren’t totally satisfied with what we’d come up with, because it still looked too much like Twitter (long list of messages in reverse chronological order). Then Jamie came up with the idea of only displaying each cyclist’s most recent tweet in a grid. We really like how this works because people who tweet a lot (like Lance) don’t dominate the page. It gives you an overview of what the whole peloton is talking about without letting a few people dominate it.&lt;/p&gt;


	&lt;h2&gt;Behind the scenes&lt;/h2&gt;


	&lt;p&gt;This application uses Rails 2.3, the &lt;a href="http://github.com/thoughtbot/suspenders/tree/master"&gt;Suspenders base app&lt;/a&gt;, &lt;a href="http://github.com/hcatlin/make_resourceful/tree/master"&gt;make_resourceful&lt;/a&gt;, &lt;a href="http://github.com/rubypond/semantic_form_builder/tree/master"&gt;semantic_form_builder&lt;/a&gt; and the excellent &lt;a href="http://dev.ctor.org/http-access2"&gt;HTTPClient&lt;/a&gt; library for interacting with Twitter (give up on net/http – &lt;a href="http://olabini.com/blog/tag/httpclient/"&gt;it is full of fail&lt;/a&gt;).&lt;/p&gt;


	&lt;p&gt;Twitter &lt;span class="caps"&gt;API&lt;/span&gt; access is done directly with &lt;span class="caps"&gt;JSON&lt;/span&gt;. We pull the &lt;code&gt;friends_timeline&lt;/code&gt; and insert those tweets into the database.&lt;/p&gt;


	&lt;h2&gt;Developing for Twitter&lt;/h2&gt;


	&lt;p&gt;I’ve been doing a number of Twitter-related projects lately. The first was &lt;a href="http://twistr.org"&gt;Twistr&lt;/a&gt;, which combines Twitter and Flickr LOLcat style for occasionally amusing results. Then &lt;a href="http://bjhess.com"&gt;Barry Hess&lt;/a&gt; and I built &lt;a href="http://followcost.com"&gt;Follow Cost&lt;/a&gt;, which tells you how much someone tweets &lt;em&gt;before&lt;/em&gt; you follow them. I created &lt;a href="http://fanchatter.com"&gt;a prototype for FanChatter’s next product&lt;/a&gt; based on Twitter conversation aggregation. Now comes VeloTweets and another project that’s not public yet.&lt;/p&gt;


	&lt;p&gt;I really enjoy working with the Twitter APIs. It’s fun to develop applications that utilize the platform that the Twitter folks have built.&lt;/p&gt;


	&lt;p&gt;On that front, I recently received a copy of &lt;a href="http://www.amazon.com/gp/product/0596154615?ie=UTF8&amp;amp;#38;tag=justlook-20&amp;amp;#38;linkCode=as2&amp;amp;#38;camp=1789&amp;amp;#38;creative=390957&amp;amp;#38;creativeASIN=0596154615"&gt;Twitter &lt;span class="caps"&gt;API&lt;/span&gt;: Up and Running&lt;/a&gt; (Follow Cost is mentioned on page 70!) which I will give a full review to soon. You don’t &lt;em&gt;need&lt;/em&gt; a book on the Twitter &lt;span class="caps"&gt;API&lt;/span&gt; to develop applications for it, but it does provide some ideas and a useful reference, as well as details on some interesting aspects of Twitter (for example, I did not know that direct messages disappear if they are deleted by either party.).&lt;/p&gt;
          &lt;img src="http://feeds.feedburner.com/~r/RailSpikes/~4/M7sssUH-BB8" height="1" width="1"/&gt;</content>  <feedburner:origLink>http://railspikes.com/2009/5/10/announcing-velotweets</feedburner:origLink></entry>
  <entry xml:base="http://railspikes.com/">
    <author>
      <name>Jon</name>
    </author>
    <id>tag:railspikes.com,2009-04-30:1966</id>
    <published>2009-04-30T18:49:00Z</published>
    <updated>2009-04-30T18:50:06Z</updated>
    <category term="music" />
    <category term="railsconf" />
    <link href="http://feedproxy.google.com/~r/RailSpikes/~3/8HX2zDXhDGk/music-and-programming-interviews-with-chad-fowler-and-dave-thomas" rel="alternate" type="text/html" />
    <title>Music and programming: interviews with Chad Fowler and Dave Thomas</title>
<content type="html">
            &lt;p&gt;I’ll be speaking at &lt;a href="http://en.oreilly.com/rails2009/"&gt;RailsConf 2009&lt;/a&gt; this year on music and software development (&lt;a href="http://en.oreilly.com/rails2009/public/schedule/detail/7494"&gt;Five musical patterns for programmers&lt;/a&gt;). The basic premise is that software development and music actually have quite a bit in common. This may be surprising to some people, who see programming as a cold, rational left-brain sort of thing, like science. But we programmers know that this is not really the case at all.&lt;/p&gt;


	&lt;p&gt;So as a prelude to my talk, I decided to interview two programmer-musicians on the subject: Chad Fowler and Dave Thomas. Both compose and perform music, and both are noted programmers. Here is the interview.&lt;/p&gt;


	&lt;p&gt;&lt;em&gt;&lt;strong&gt;Rail Spikes:&lt;/strong&gt; Tell us a little about your background with both programming and music.&lt;/em&gt;&lt;/p&gt;


	&lt;p&gt;&lt;strong&gt;Chad Fowler:&lt;/strong&gt; I started my professional life as a saxophonist in Memphis. I played the Beale street clubs and all the typical Memphis professional musician stuff.  Among others, I played for a while with &lt;a href="http://en.wikipedia.org/wiki/Ann_Peebles"&gt;Ann Peebles&lt;/a&gt; and her husband &lt;a href="http://project.ioni.st/2007/11"&gt;Don Bryant&lt;/a&gt; with the rhythm section from all the old &lt;a href="http://www.hirecords.com/"&gt;Hi Records&lt;/a&gt; recordings. I did mostly R&amp;B and jazz professionally but I was probably most well known in the Memphis community for making “strange” music. Before playing music professionally, I played guitar in punk bands in high school.  I was a fan of punk, heavy metal, hip hop, pop, (new) classical and pretty much everything else.  As I immersed myself in the world of jazz, it became quickly clear that the jazz community doesn’t like punk and other less “serious” types of  music and has an almost religious negative reaction to jazz musicians who  do.&lt;/p&gt;


	&lt;p&gt;It was almost as if any deviation from the “normal” world of jazz made you a traitor. So I did the natural thing: started a group called The Jazz Traitors, which played music that 1) we loved and 2) offended the jazz community (not necessarily in that order).&lt;/p&gt;


	&lt;p&gt;I was also very interested in composing “classical” music. I studied with a composer named &lt;a href="http://kamrancince.com"&gt;Kamran Ince&lt;/a&gt;, who is still my favorite such composer.&lt;/p&gt;


	&lt;p&gt;As for programming, I’ve been interested in programming since I was a young child using my commodore 64. I wasn’t really that good at it as a kid but I played around a lot. I didn’t get serious until I picked up programming again as a hobby while I was a professional musician. After a late night gig at a bar, it was relaxing to go home and unwind to some C programming tutorials. I didn’t have a &lt;em&gt;need&lt;/em&gt; to program, nor did I have a project in mind (except that I have always loved video games and wanted to learn how they worked). But I got so into it, that I ended up getting a job in computer support because a friend filled out an application for me.&lt;/p&gt;


	&lt;p&gt;Being the gamer I am, as soon as I started in computer support, I naturally wanted to “level up”. That meant becoming a network administrator. Then a system administrator. Then a programmer, then a designer, then an architect, then a &lt;span class="caps"&gt;CTO&lt;/span&gt;, etc.  Now here I am. It’s been fun.&lt;/p&gt;


	&lt;p&gt;&lt;strong&gt;Dave Thomas:&lt;/strong&gt; There was always a lot of music in our house. My father liked to play the piano and the organ (I learned to solder as he built a Heathkit organ from a kit in the late 60s). My mother liked Broadway musicals. So we’d often experience alternating hours of Chopin and South Pacific. My brother was also musical. I wasn’t particularly, but I enjoyed noodling on the piano, and spent hours just playing with chords and progressions.&lt;/p&gt;


	&lt;p&gt;I’ve been programming since I was 15 or so.&lt;/p&gt;


	&lt;p&gt;&lt;em&gt;&lt;strong&gt;Rail Spikes:&lt;/strong&gt; Some developers – yourself included – have suggested a similarity between programming and music composition or performance. How exactly are music and programming similar?&lt;/em&gt;&lt;/p&gt;


	&lt;p&gt;&lt;strong&gt;Dave Thomas:&lt;/strong&gt; I’m not sure, but I think it might be something to do with the discovery of patterns. Both music and code consist of nested sets of variations and repetitions. There’s a rythm to executing code, in the same way there’s a rythm to music. It is never exact, but it’s there. After a while, I found I could imagine the rythm and structure of my programs as they run, in the same way you can pick apart the structure of a piece of music as you listen to it. And, jsut as with music, it takes experience to be able to feel the deeper structures and notice the more extreme variations. But being able to spot them in programs makes coding simpler and more interesting. The basic coding structures—loops, method calls, and so on—provide the framework for composing in the same way that staff and bar lines do for music. Algorithms are like the progressions, and data becomes the notes. And in the same way that good music takes all these things and then surprises you, good code does the same thing. It isn’t mechanical and repetitive: instead it uses the constraints to build something bigger and more interesting.&lt;/p&gt;


	&lt;p&gt;&lt;strong&gt;Chad Fowler:&lt;/strong&gt; It’s hard for me to put my finger on. There’s something similar in the way I think when I do each.&lt;/p&gt;


	&lt;p&gt;I think it all boils down to language, though. In all of these cases (including learning actual language), you take a bunch of tokens (notes, sounds, grunts, functions, classes) and combine them into a grammar which you use to express ideas. The way you do that is totally up to you as long as the intended ideas are communicated. With computer programs, they have to do what they’re meant to do. With music, they express or evoke emotions, paint pictures, cause anxiety or whatever.&lt;/p&gt;


	&lt;p&gt;Some computer programs evoke emotions and cause anxiety as well.&lt;/p&gt;


	&lt;p&gt;&lt;em&gt;&lt;strong&gt;Rail Spikes:&lt;/strong&gt; Is Ruby development more like improvised jazz or composed classical music?&lt;/em&gt;&lt;/p&gt;


	&lt;p&gt;&lt;strong&gt;Chad Fowler:&lt;/strong&gt; I think it’s both. And I don’t think Ruby is any different in this than other languages. Much of the discussion about the relationship between programming and music focuses on the more obvious idea of programming as composition. It makes sense, since programmers tend to sit and type their ideas into an editor and then eventually execute it. The programs can be checked, tested, refactored, etc. before the actual performance. This is how classical composition works as well.&lt;/p&gt;


	&lt;p&gt;But the less obvious angle is that in many situations, programming is like performance. In fact, even in music, improvisation  is really just real time composition. You don’t get a chance to refactor because your “code” is executed as you write it.&lt;/p&gt;


	&lt;p&gt;I’ve had this same feeling while debugging production problems, hacking new features on a tight deadline, or sometimes during the initial creation of an application. The same synapses are firing as when I was trying to play Cherokee at 200 beats per minute. Mistakes can’t be erased, so they have to be nuanced into (worst case) insignificant events or (best case) important drivers behind the work.&lt;/p&gt;


	&lt;p&gt;From a purely development-oriented perspective, &lt;span class="caps"&gt;TDD&lt;/span&gt; is more like improvisation than composition. I think that’s what I like about it. It’s motivating and creative in an exciting, time-sensitive way. You take small steps and see where they lead you. Sure, you can always revert your changes if you paint yourself into a corner but part of the fun and challenge is to not paint yourself into a corner.&lt;/p&gt;


	&lt;p&gt;One thing jazz musicians like to say is that every wrong note is just a half step away from a right note. &lt;span class="caps"&gt;TDD&lt;/span&gt; is like that. You might take a slightly wrong turn. It’s fun to see if you can course-correct without starting over.&lt;/p&gt;


	&lt;p&gt;&lt;em&gt;&lt;strong&gt;Rail Spikes:&lt;/strong&gt; Do developers need to be musically inclined? Does it help?&lt;/em&gt;&lt;/p&gt;


	&lt;p&gt;&lt;strong&gt;Chad Fowler:&lt;/strong&gt; Obviously not. Some of the best programmers I know are not musicians. I can’t tell if it helps, but I would guess that developers who are also musicians are different than developers who aren’t. I don’t think that’s because being a musician changes people, though. I think it’s because the people who are both are the kind of people who &lt;em&gt;need&lt;/em&gt; to do both.&lt;/p&gt;


	&lt;p&gt;This usually means they’re “right brain” people. This leads to a way of thinking that changes how they approach programming problems.&lt;/p&gt;


	&lt;p&gt;I think learning music (or another right brain discipline) is a good way to exercise your mind. So I wouldn’t be surprised if leaning music helps people exercise their thought processes in ways that will benefit their work as programmers (or authors, or lawyers, or doctors or whatever).&lt;/p&gt;


	&lt;p&gt;I also think, though, that if we were all musicians at heart, we wouldn’t get much done. I rely heavily on my less artsy colleagues to ground me and be sometimes more pragmatic than I am. So I don’t think we all need to be a “right brain” programmer. It would be disasterous if we were.&lt;/p&gt;


	&lt;p&gt;&lt;strong&gt;Dave Thomas:&lt;/strong&gt; Do they need to be? No. But many of the good ones I know are. I’d guess that density of musicians in software development is many times the population norm. But that means you could also ask the question “Do musicians have to know software development?”&lt;/p&gt;


	&lt;p&gt;I think the more interesting question is to ask “how can people best express what they enjoy doing?” because both music and software development are outlets for this.&lt;/p&gt;


	&lt;p&gt;&lt;em&gt;&lt;strong&gt;Rail Spikes:&lt;/strong&gt; What sort of music do you listen to? Any recommendations for Ruby developers looking to expand their musical horizons?&lt;/em&gt;&lt;/p&gt;


	&lt;p&gt;&lt;strong&gt;Chad Fowler:&lt;/strong&gt; As I mentioned earlier, I like all kinds of music (with a few exceptions). Lately I’ve been listening to a lot of instrumental hip hop, such as DJ Qbert and Mixmaster Mike. I’ve also been getting into a genre of electronic music called “electro”, which sounds like the bleeps and bloops that are the soundtrack of my dreams (if a computer is going to generate music I always like it to sound like a computer generated it).&lt;/p&gt;


	&lt;p&gt;As for recommendations, here are a few ideas for things that most developers probably haven’t listened to:&lt;/p&gt;


	&lt;ul&gt;
	&lt;li&gt;&lt;a href="http://kamranince.com"&gt;Kamran Ince&lt;/a&gt; – He was my composition teacher and, I think, an accessible introduction to the world of “new music”, which is what we call new composed “classical” music. The term “classical” is a widely spread misnomer. It actually refers to music written in the late 18th and early 19th centuries, but most people use it to mean high brow music written for instruments like violins. So whatever you call it, Kamran Ince writes some beautiful instances of it. Specifically check out his chamber music, such as Domes and Arches.&lt;/li&gt;
	&lt;/ul&gt;


	&lt;ul&gt;
	&lt;li&gt;&lt;a href="http://charliewood.us"&gt;Charlie Wood&lt;/a&gt; – I have had the pleasure of playing with Charlie on a few occasions. He is a R&amp;B singer/organist/composer from Memphis and writes some of the most intelligent songs you’ll hear. My favorite album of his is “Who I Am”.&lt;/li&gt;
	&lt;/ul&gt;


	&lt;ul&gt;
	&lt;li&gt;&lt;a href="http://www.tzadik.com/"&gt;John Zorn&lt;/a&gt; – Zorn has been around for a long time and is a leader in the world of Avant Garde music. He’s also one of the most amazing saxophonists ever. If you’re new to this kind of thing, his Masada quartet (“radical Jewish music”) produces some great stuff that’s accessible to first time listeners. If you’re looking for something to shock your aural taste buds, try Painkiller (metal-tinged noise) or Naked City.&lt;/li&gt;
	&lt;/ul&gt;


	&lt;p&gt;&lt;strong&gt;Dave Thomas:&lt;/strong&gt; I listen to just about anything that’s interesting. My playlist here is very varied, and I try to add new stuff to it farily regularly. I know people who are trained as musicians, and I tend to ask them what they’re listening to. Sometimes that leads to challenges: my ear isn’t as developed as their ears. But often it leads to whole new areas of cool stuff. So I’d recommend everyone should find a friend who knows more than you do about music and ask them to surprise and challenge you. (That advice probably applies to just about everything, thinking about it.) It’s easy to find music that stimulates your lizard brain. Get into the habit of looking for the stuff that engages at a higher level too. And, like everything, have fun with it.&lt;/p&gt;
          &lt;img src="http://feeds.feedburner.com/~r/RailSpikes/~4/8HX2zDXhDGk" height="1" width="1"/&gt;</content>  <feedburner:origLink>http://railspikes.com/2009/4/30/music-and-programming-interviews-with-chad-fowler-and-dave-thomas</feedburner:origLink></entry>
</feed>
