<?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"
	>

<channel>
	<title>Pathfinder Development &#187; Josh Symonds</title>
	<atom:link href="http://www.pathf.com/blogs/author/josh-symonds/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.pathf.com/blogs</link>
	<description>Running commentary about agile development, user experience design and Ajax.</description>
	<pubDate>Wed, 19 Nov 2008 15:24:09 +0000</pubDate>
	<generator>http://wordpress.org/?v=2.5.1</generator>
	<language>en</language>
			<item>
		<title>8 Tips &#038; Tricks When Starting Objective-C iPhone Apps: [self.paradigm shiftFrom:@"ruby" to:@"objective-c"];</title>
		<link>http://www.pathf.com/blogs/2008/10/8-tips/</link>
		<comments>http://www.pathf.com/blogs/2008/10/8-tips/#comments</comments>
		<pubDate>Wed, 22 Oct 2008 21:14:56 +0000</pubDate>
		<dc:creator>Josh Symonds</dc:creator>
		
		<category><![CDATA[Agile Ajax]]></category>

		<guid isPermaLink="false">http://www.pathf.com/blogs/?p=1213</guid>
		<description><![CDATA[All languages have something interesting to teach us about the art of programming -- and as a Ruby developer almost exclusively, I've always been afraid of strongly typed languages like Java and C++, or the great-grand-daddy of them all, C. So when I decided to tackle Cocoa to work on iPhone apps I went in [...]]]></description>
			<content:encoded><![CDATA[<p>All languages have something interesting to teach us about the art of programming -- and as a Ruby developer almost exclusively, I've always been afraid of strongly typed languages like Java and C++, or the great-grand-daddy of them all, C. So when I decided to tackle Cocoa to work on iPhone apps I went in somewhat leery of how I'd have to change, but hopeful that I'd become a better, more versatile programmer. After a few weeks I would say I've achieved my goal, but it's certainly taken a lot of blood, sweat, and tears to get here.</p>
<p>I think a lot of people are in a similar position to me: trying to pick up Objective-C to do iPhone programming, and coming in with only a book or two as their guide. Most of the books out there for learning Cocoa and the iPhone SDK are very good but there are a lot of gotchas and stylistic tricks that really mean the difference between comprehending a statement and staring at it in horror and confusion until Google comes to your rescue. The aim of this blog post is to come to your rescue instead of Google. These are the 8 biggest foul-ups that I wish I had known before I started learning Objective-C. Hopefully you'll learn something here that will prevent you from making an idiotic mistake I already made.</p>
<p><span id="more-1213"></span></p>
<ol>
<li>
<h4>TURN ON NSZOMBIEENABLED</h4>
<p>Seriously, I'm not even kidding. This is THE way to debug hard to find errors in your apps.</p>
<p>As you may or may not know, iPhone apps do not have an automated garbage collector, so you have to release and retain objects manually. Sometimes you accidentally release an object that you intended to hold on to. Your code will not fail until a message is sent to the deallocated instance, at which point your application will crash and you'll have no idea why. Oh, sure, you'll have the general EXC_BAD_ACCESS error that tells you you tried to access memory that was deallocated... but that isn't really helpful.</p>
<p>If you turn on NSZombieEnabled, then deallocated instances are retained in memory but their class is changed to Zombie, so that when they receive a message they raise an error. Now you can actually debug those memory problems.</p>
<p>To turn this on:</p>
<ol>
<li>Open your project in Xcode</li>
<li>Expand the Executables section</li>
<li>Right-click on the name of your executable and select 'Get Info'</li>
<li>Click on 'Arguments' at the top</li>
<li>Click the plus underneath 'Variables to be set in the environment</li>
<li>For the variable name, type in NSZombieEnabled, and for its value, enter YES</li>
</ol>
<p>Do this right now. You'll thank me later. Just remember to redact it before you bundle your app to production, because in production, you want instances to be deallocated, not turned into zombies.</p>
</li>
<li>
<h4>Nil is your friend, not your enemy</h4>
<p>This one was difficult for me to wrap my head around.</p>
<p>In most object oriented languages, like Ruby, if you send a method to an object but that object is nil, your program dies messily. This is what amazing gems like <a href="http://andand.rubyforge.org/">Andand</a> are supposed to protect against: nil inadvertently receiving a message and raising an error.</p>
<p>In Objective-C, if nil is sent a message, that's just fine. In fact I would go so far as to say this is an amazing and distinguishing feature of Objective-C: it is used extensively in the iPhone classes and you should use it too. This allows you to make code sort of like this:</p>
<pre>
if ([anObjectThatMayBeNil startProcessing]) {
  // ...code...
}
</pre>
<p>You don't have to test whether or not the object is nil. If this statement isn't true then either startProcessing failed, or the object wasn't there: either way, you don't want to execute the code block. Whether or not this is just madness is certainly open for personal interpretation. Coming from Ruby I sort of like it, but I can see how it can make code very very difficult to debug.</p>
<p>My advice is to embrace the insanity. Objective-C provides a lot of power by allowing you to use objects' methods even when they may not exist: be careful in how you use this power and your programs will flourish.</p>
</li>
<li>
<h4>Remember the damn @'s and ;'s</h4>
<p>This is a really simple and dumb one.</p>
<p>NSString is what most Objective-C classes that want string-like objects expect; they are NOT formed with quotes, but with an at-sign then quotes.</p>
<p>@"This is a valid NSString."</p>
<p>"This is not, and will raise annoying and mysterious compiler errors if you try to use it."</p>
<p>Similarly, don't forget your semi-colons. I know I sound like a noob, but coming from Ruby it's easy to trip up and just hit enter and then be confused when the compiler dies. Happily in this case at least you get a sensible message so you can find the problem and put in a semi-colon.</p>
</li>
<li>
<h4>Use delegates in your code</h4>
<p>Native Objective-C classes (particularly iPhone classes) make extensive use of delegates. They rely on the fact that you can send messages to nil objects without a problem that I discussed earlier: even if you don't assign a delegate the messages are sent anyway, there's just no one there to listen to them. It's like 'if a function falls in a forest...' or something like that.</p>
<p>Anyway, delegates are extremely powerful and are one of the cooler elements of style in Objective-C. They allow you to send long-running or complicated tasks off to another object and be certain that you'll hear back from them eventually, while simultaneously affording you the power of polymorphism in that you can call that task from any object and respond to the task situationally.</p>
<p>An excellent example of this is CoreLocation, the framework the iPhone uses to do location updating. In my iPhone app I have a singleton class Locator that controls access to the CoreLocation framework. It is the delegate of the CLLocationManager like this:</p>
<pre>
self.locationManager = [[CLLocationManager alloc] init];
self.locationManager.delegate = self;
[self.locationManager startUpdatingLocation];
</pre>
<p>When the CLLocationManager receives a location update, it calls a method on the delegate called locationManager:didUpdateToLocation:fromLocation:. All I have to do in my code is implement that method: I know that it will be called if and only if the location was correctly received. There's another method for locationManager errors.</p>
<p>The power of this, of course, is that one object can have its delegate changed; thus, the delegators can respond to the same call in different ways. Perhaps in one controller in my app I pop up a window after the location has been updated. In another, I animate something. The method is the same for both controllers (locationManager:didUpdateToLocation:fromLocation:): all I'm doing is changing which one is the delegate of CLLocationManager.</p>
<p>Once you get used to this programming style, you'll really like it.</p>
</li>
<li>
<h4>NSLog EVERYTHING</h4>
<pre>NSLog(@"Hi there, the object you want is: %@", anObject);</pre>
<p>Ruby gives an excellent backtrace when it crashes. Objective-C (even with gdb) leaves a lot to be desired, in my opinion. Log frequently, everywhere, everything, so that when your application mysteriously crashes (and it will) you know around where so hopefully you can find the foul-up.</p>
<p>By the way, the %@ inside the NSString up there? That's the syntax for object substitution. This ONLY works for NSObjects, and it calls their description method. If you try to do it on a regular C type it'll crash, so this is totally wrong:</p>
<pre>
int i = 1;
NSLog(@"The number is: %@", i); // BOOM CRASH!
</pre>
<p>Instead, you should use the correct string substitution:</p>
<pre>
int i = 1;
NSLog(@"The number is: %i", i); // sweet, sweet success
</pre>
<p>An easy gotcha to miss. Check out <a href="http://developer.apple.com/documentation/Cocoa/Conceptual/Strings/Articles/formatSpecifiers.html#//apple_ref/doc/uid/TP40004265">the Cocoa string substitution documentation</a> for all the other types out there.</p>
</li>
<li>
<h4>Define description for your custom classes</h4>
<p>A closely-related corollary to the NSLog advice: give all your custom object classes a description method.</p>
<pre>
- (NSString *)description {
	return self.name;
}
</pre>
<p>Now when you log them with NSLog they'll return a sensible string, instead of nil.</p>
</li>
<li>
<h4>Objective-C doesn't really use strong typing, and neither should you</h4>
<p>Use strong typing when it seems sensible, but you don't have to be married to it because Objective-C certainly isn't. Any Objective-C object can be declared with the type 'id' rather than its particular class. This allows you to use some potentially dangerous instances of polymorphism:</p>
<pre>
Duck *aDuck = [[Duck alloc] init];
Goose *aGoose = [[Goose alloc] init];
Pond *bigLake = [[Pond alloc] init];

bigLake.inhabitant = aDuck;
[bigLake.inhabitant quack]; // The duck says: "quack!"

bigLake.inhabitant = aGoose;
[bigLake.inhabitant quack]; // The goose says: "do I look like a duck to you?"
</pre>
<p>This is made possible by a simple declaration in the Pond class:</p>
<pre>
@interface Pond : NSObject {
	id *inhabitant;
}

@property (nonatomic, retain) id *inhabitant;
</pre>
<p>Now Objective-C doesn't care what the inhabitant is, only that it descends from NSObject (that defines id). This will sensibly warn you at compile-time that the inhabitant might not respond to quack, though, so be careful with this power. If you send a bad method to an object it isn't the same as if you sent a message to nil: your program will crash if the object has no such method defined on it.</p>
<p>But still, you can pass all kinds of different objects around now however you like. Just remember to make sure they respond to the method you pass to them before you use them.</p>
</li>
<li>
<h4>Read the API reference, then double-check it on Google</h4>
<p>I was trying to do something clever with the UIWebView object but it didn't seem like it was possible with the documentation given to me by the default API viewer. Then Google came to the rescue and showed me the light (or rather, the method webView:shouldStartLoadWithRequest:navigationType:). Even though the documentation is ostensibly complete (and even that won't be true unless you subscribe to it and download the complete docs), a lot of people have experimented with Cocoa and the iPhone SDK for a lot longer than we have. A quick Google search can sometimes yield surprising results, and you can bet any problem you've run into, someone else has already had trouble with.</p>
</li>
</ol>
<h3>That's a wrap</h3>
<p>I'm sure there's a bunch I missed. My C was very rusty; after using Ruby almost exclusively for a few years, it was difficult to pick up Objective-C. But ultimately I think it was very rewarding. Objective-C is elegant and simple, giving you more than enough rope to hang yourself, or create something really amazing (out of rope, to maintain the metaphor). Just make sure to keep in mind this hit-list of 8 items and your Objective-C programs will flourish. And if you've got something to share, post it as a comment, and let the world read your helpful advice!</p>
]]></content:encoded>
			<wfw:commentRss>http://www.pathf.com/blogs/2008/10/8-tips/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Rails Performance, Code Metrics, and Locking Down your Application: Tips &#038; Tricks from Windy City Rails 2008</title>
		<link>http://www.pathf.com/blogs/2008/09/tips-tricks-from-windy-city-rails/</link>
		<comments>http://www.pathf.com/blogs/2008/09/tips-tricks-from-windy-city-rails/#comments</comments>
		<pubDate>Wed, 24 Sep 2008 20:27:25 +0000</pubDate>
		<dc:creator>Josh Symonds</dc:creator>
		
		<category><![CDATA[Agile Ajax]]></category>

		<guid isPermaLink="false">http://www.pathf.com/blogs/?p=1161</guid>
		<description><![CDATA[Windy City Rails was the best Rails conference I've ever been to, which is easy for me to say since it was my first actual Rails conference. But even speaking from a fairly uninformed point of view I found it very full of quality. In case you didn't know, it was created by ChicagoRuby, sponsored [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://www.pathf.com/blogs/wp-content/uploads/2008/08/rails.png"><img class="alignright size-medium wp-image-1100" title="Ruby on Rails" src="http://www.pathf.com/blogs/wp-content/uploads/2008/08/rails.png" alt="" width="50" height="64" /></a>Windy City Rails was the best Rails conference I've ever been to, which is easy for me to say since it was my first actual Rails conference. But even speaking from a fairly uninformed point of view I found it very full of quality. In case you didn't know, it was created by ChicagoRuby, sponsored by Pathfinder (us) among others, and you can find tons more details if you're interested at <a href="http://windycityrails.org/">http://windycityrails.org/</a>. Anyway, it was this last Saturday the 20th, and after four days of digestion I am prepared to deliver some of the highlights:</p>
<p><span id="more-1161"></span></p>
<h3>DHH on Rails Performance and Winning in the Website Business</h3>
<p>DHH did a pretty neat 30 minute Q&amp;A session towards the beginning of the day. I'd never actually met (or seen) the guy who initially spawned the framework from which I make my day-to-day livelihood. He's very personable, awfully loud, thoroughly opinionated, and quite brilliant, just like Rails. It is my career goal to be cool enough that I can show up at a conference dedicated to software I created, with no speech in hand and no real plan, but still wing a Q&amp;A session that ends up being one of the conference highlights, because DHH did just that.</p>
<p>One of the questions he answered was about the speed of the Rails framework, which got him off on a really interesting diatribe on how Rails is A) fairly speedy at doing its thing and B) not usually the problem when there are throughput difficulties on a server. Rails only takes up about 10-20% of the time a request is being processed by the server. Seriously, the biggest improvement DHH said 37signals implemented in BaseCamp was telling the server to check the browser's etags. Very handy headers that have been part of the HTTP spec for generations (like HTTP_IF_MODIFIED_SINCE) can provide huge speed improvements if implemented correctly, and that's something usually done by Apache and not Rails at all. But that said in Edge Rails we now have a request.fresh? method that lets us quickly return head :not_modified. We don't even have to hit the database. How cool!</p>
<p>Remember to gzip files you're sending around, and minify JS, and all that other good stuff. Seriously. The tool <a href="http://developer.yahoo.com/yslow/">yslow</a> (which I knew about before the talk because I'm a great web developer) is completely invaluable for boosting the performance of your apps. Use it. Love it.</p>
<p>After DHH finished his talk, there was a small collection of people out in the hallway sponging around him, and being a mindless sheep I stuck around too and learned that DHH has a secret hatred of migrations. They're really great to build iteratively and allow seamless database support, but he was definitely of the opinion that they should be thrown away with great regularity and replaced with the overall schema. Certainly they were never intended for use in production environments (which should be obvious from the existence of the rake db:schema:load task).</p>
<p>And finally, I spoke with him myself, which was kind of awkward since I had absolutely nothing to say. I mean, after you thank him for creating the thing that makes you money, what conversational gambits are left? Discussions of the weather? I ended kind of lamely and ended up kicking myself through the rest of the conference for it. Next time, I'm going to have some emergency questions prepared in case I get a one-on-one with him or another luminary of he Rails world.</p>
<p>What I took away most from his talk was something just of general inspiration and not Rails-related at all, though. In answering someone's question about how to succeed in creating web applications, he stated two things: A) be marginally better than your competition, and B) have greater longevity. Seriously, if you're only 2% better, you'll win in the long run because most companies die and your competitor's will before yours, if you play your cards right. Ultimately, he stated that having a market of millions is nearly impossible; be satisfied with thousands, or even a few dozen thousands.</p>
<p>Think about this: a mere 2,000 customers paying $40 a month leaves your company with a revenue stream approaching a million dollars. That is certainly nothing to sneeze at, and only goes to show that web business models do not require 100,000 users before they become profitable. A lot of people fall into the trap of believing that they'll be the next Google or YouTube and their company will have a market capitalization of a billion dollars overnight. It won't happen. It's more likely you'll win the lottery. Aim modestly, and your chances of success increase exponentially.</p>
<h3>Jake Scruggs and Code Metrics that Matter</h3>
<p>Of course, our own John McCaffery delivered an immensely popular talk about JavaScript testing, highlighting JavaScript-unfriendly browsers like everyone's favorite Internet Explorer. But since I had heard it already, I went to Jake Scruggs' presentation, 'Using Metrics to Take a Hard Look at Your Code.'</p>
<p>Everyone knows the big code metric: code coverage. It's kind of the old standby of the code numbers world. But Jake Scruggs was pretty dismissive towards it, which is perfectly correct of him. Rcov in particular is not a complicated tool; it checks code coverage only by seeing that particular lines are called. It does not check complicated conditional logic, nor does it check for weird failing cases, and it doesn't tell you when your methods are crazy and overwrought. It is a good metric because you want tests, but it is not a good metric because it doesn't really tell you how good your code actually is.</p>
<p>For that, he recommended a tool I had never heard of: <a href="http://ruby.sadi.st/Flog.html">flog</a>. Flog determines the complexity of your methods and lets you know when your code should be refactored into more sensible, bite-sized chunks. This isn't to say that you can't have a hundred-line-long method; but testing is easier and more sensible when code is atomic, and flog really encourages refactoring with an eyes towards atomization.</p>
<p>Also he talked about <a href="http://saikuro.rubyforge.org/">Saikuro</a>, which is a cyclomatic complexity analyzer. In human speak that means it counts the number of branches in your code for you, which is probably as many tests as that method should have. If you have 5 paths through a method, you want to test them all, am I right? Even if Rcov, the lying but wonderful tool it is, says you have 100% coverage, you almost certainly don't unless you have those 5 paths as 5 different tests.</p>
<p>Anyway I'm totally giving his talk short shrift. It was really fascinating and you can read more about the individual bits of it on <a href="http://jakescruggs.blogspot.com/">his blog</a>.</p>
<h3>Locking Down Rails with Aaron Bedra</h3>
<p>Aaron Bedra gave a really cool talk on Rails security. Really I don't think developers pay enough attention to this (and I am just as guilty as the rest of us). We take for granted the amazing tools Rails provides to protect against malicious users. SQL injection is rendered useless by sensible finders, cross-site request forgery is foiled by authenticity tokens, and the small little h tag nullifies most cross-site scripting attacks. These are so easy to use and require so little thought on our part that we don't test them, which is clearly the wrong thing to do.</p>
<p>So Aaron suggested a cool new tool that I intend to use from now on called <a href="http://github.com/relevance/tarantula/tree/master">tarantula</a>. Tarantula by default crawls your app and puts bad form data into it to see if your application bombs out. That's fun but kind of yawn-inducing (you're testing your model validations already, right?). Where it gets really cool is that you can set it to perform XSS, CSRF, and SQL injection attacks on your site.</p>
<p>You might get lots and lots of failures.</p>
<p>In that case, it's best to install a plugin that helps audit your code. I recommend <a href="http://xss.rubyforge.org/">xss_sniper</a>, which wraps all of your strings and texts in little h tags so you don't need to remember to whitelist them yourself. But Aaron also suggested <a href="http://agilewebdevelopment.com/plugins/safe_erb">SafeERB</a> and <a href="http://github.com/artmotion/xss_shield/tree/master">xss_shield</a>. Check 'em out and install one! It can't hurt to secure your app even more.</p>
<h3>Noel Rappin's Test Last Development</h3>
<p>Our very own Noel Rappin also gave a really cool talk on some common pitfalls in test driven development. I'll be brutally honest here. For all my strengths, I am not the best test driven developer in existence. It is hard work to remember to be test driven, especially when you tell yourself, "Oh, I'll just whip this up really quickly and get to the tests later." Good self-auditing techniques are completely required to keep on the testing straight and narrow... and it's very, very easy to stumble.</p>
<p>Noel talked a lot about those stumbles and what they show us about test driven development. I'll leave it for him to discuss the details since I hate stealing others' thunder, and anyway if I tried I certainly wouldn't cover the topic nearly as well as him. Suffice it to say that all of us have been guilty of stumbling into potholes on the road to completely test driven development, and that actually analyzing those roadbumps helps us figure out when some can actually be useful, and how to avoid them in the future.</p>
<p>So, all in all, Windy City Rails rocked! The energy level was high, the food was completely bearable, there were lots of people there, a fair amount of swag was given away (but in a grotesque oversight I did not win any), and here's my strange anecdote from the conference: I was standing in line for lunch and the guy behind me struck up a conversation with me. He said that he's a .Net developer and doesn't know the first thing about Rails. He just wants to learn more about our development processes and what we're doing.</p>
<p>How cool is that?</p>
]]></content:encoded>
			<wfw:commentRss>http://www.pathf.com/blogs/2008/09/tips-tricks-from-windy-city-rails/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Selling Git on the Business End</title>
		<link>http://www.pathf.com/blogs/2008/08/selling-git-on-the-business-end/</link>
		<comments>http://www.pathf.com/blogs/2008/08/selling-git-on-the-business-end/#comments</comments>
		<pubDate>Thu, 28 Aug 2008 05:55:26 +0000</pubDate>
		<dc:creator>Josh Symonds</dc:creator>
		
		<category><![CDATA[Agile Ajax]]></category>

		<category><![CDATA[Git]]></category>

		<guid isPermaLink="false">http://www.pathf.com/blogs/?p=1122</guid>
		<description><![CDATA[
Today I gave a presentation on why Git makes sense for an agile consultancy like ours. It was more challenging than I initially imagined; there are many, many blog posts out there discussing why Git is technically superior to Subversion. But when I searched for posts discussing the business merits of Git I came up [...]]]></description>
			<content:encoded><![CDATA[<p><img src="http://www.pathf.com/blogs/wp-content/uploads/2008/08/git-logo1.png" alt="Git Logo" title="git-logo" width="73" height="28" class="right" /></p>
<p>Today I gave a presentation on why Git makes sense for an agile consultancy like ours. It was more challenging than I initially imagined; there are many, many blog posts out there discussing why Git is technically superior to Subversion. But when I searched for posts discussing the business merits of Git I came up short. Git is faster, branches better, it has a local copy of the repository, it's small and cheap, but these are points that sell an engineer. What sells the administrators, the business analysts, the project managers?</p>
<p>I came up with a few cool scenarios to illustrate why we, as a business, should adopt Git -- essentially, why it makes not only my life easier, but why it will make the decision makers incredibly happy too. Then my colleague Jason Sendelbach and I gave a short talk on not only the why of the Git, but how we can start using it. Here I'll summarize our presentation. If you want to use Git in your company, but you have problems selling it to the administration, feel free to crib liberally. These points worked great for me.</p>
<p><span id="more-1122"></span></p>
<p>Essentially, Git is excellent for agile development houses because it allows them to be more responsive. Agile is all about short sprints and quick response times; Git facilitates an agile methodology and supports engineers using less time, making better code, and working more closely together. That means less time spent on each individual project, and that means more time to spend on new projects. Using Git, development houses can support clients more easily, collaborate more effectively, and control the quality of their code simply and easily -- and that means money to them, and satisfaction to their clients.</p>
<h3>Easy Client Support</h3>
<p>When I discussed why Git helps us support clients, I actually directly referenced a call I got last week from a client. I think every developer has been in a situation like this. I'm busy programming in the trunk, making new features, when the client phones us and says, "Uhh... you know, we need a change made, and we need it right away." But I'm in the middle of working on stuff! What am I supposed to do? Either I make a new branch, or I roll back the changes I've made in the trunk, or I keep track of which files I made the changes in and make sure I don't commit them. Or I try to finish up my new features in the trunk quickly and head over to the change request. Headaches!</p>
<p>In this scenario, Git works with me, where Subversion presents a stumbling block. The easiest thing to do in Git is use Git stash. In the command line, I just type:</p>
<pre>git stash</pre>
<p>And suddenly all my changes are saved and my master branch is clean again. I make the changes, commit them, push them to the server, and then:</p>
<pre>git stash apply</pre>
<p>The new features are rolled back into the master branch and you can continue developing as if you hadn't just gotten a client call. How cool is that? Your project manager immediately sees that this saves time in every step of the process -- you develop not only new features better and more quickly, but you support the client immediately and responsively.</p>
<p>Of course, you can do this just as well with branching. But seeing this happen in the stash is much more visceral and in my small test runs got a lot more punch than creating a new branch, committing to that, and then working back in the master again.</p>
<h3>Faster Development Through Collaboration</h3>
<p>Apportioning development work in a project is an unenviable task. A project manager has only a certain amount of resources to allocate in order to achieve an amazing web application; ensuring that designers work together effectively is incredibly important in creating a cohesive, and whole, final product. Git helps developers work together on disparate parts of a project quickly and more easily than they can with Subversion.</p>
<p>For example, only a few days ago I was tasked with integrating a merchant account into a project. (I used ActiveMerchant.) I had all the necessary details for my part of the project except for one: the shopping cart was someone else's task. I knew exactly what model objects I would use and how to calculate the amount that would be charged to the credit card, but without the shopping cart my work on the merchant account shouldn't be committed into the main repository. It's sort of a disassociated, floating piece until the shopping cart itself is created.</p>
<p>This was an example that allows us to really talk about how Git's branching is functionally superior to Subversion's, because the solution is the same in both version control systems: make a new branch and work with the developer in that branch. But Git allows us to do this quickly and easily, whereas Subversion is slow and clunky. Git is merely:</p>
<pre>git checkout -b cc_processing
git commit -am "Credit card processing integration"
git push origin cc_processing:refs/head/cc_processing</pre>
<p>When the shopping cart developer next pulls from the origin, they get a new remote branch called cc_processing. They change into it with:</p>
<pre>git checkout -b origin/cc_processing</pre>
<p>And they can merge the changes I've made into their shopping cart. Once the two pieces function as a cohesive whole they are integrated into the trunk of the project. Collaboration is as easy as sharing a quickly created branch; changes are pulled in faster and easier. In short, developers work better as a team with Git.</p>
<h3>Code Quality and Requirements Management</h3>
<p>Git's main selling point to the higher-ups, though, is that it can allow them more direct control in the development process. Because no repository is a special, central repository, we can easily and quickly set up multiple repositories with different purposes, that give the project managers more immediate control over the quality of the project.</p>
<p>Let's say that we have a project with a bunch of developers and one project manager. There are two repositories in the project. The first is the blessed repository; all the developers have read access to it, and they constantly rebase their local repositories from it. They make their changes locally and then commit to a second, different repository -- the unclean repository.</p>
<p>The project manager checks out the unclean repository and looks at all the changes that have been made in the developer's branches there. They can go over them with a fine toothed comb, compare them to requirements, ensure test coverage, and when they are satisfied, the changes are merged into the master and pushed to the blessed repository.</p>
<p>You should have seen the project managers' eyes light up when I hit this point. It was like I could hear them thinking: "We can vet the code against the requirements before it's pushed? We can do sensible, easy quality control? And it doesn't even mean a lot of work for us?" I have to say it was a pretty neat moment.</p>
<h3>How Do We Integrate It?</h3>
<p>So now those bigwigs are sold. The project managers want to sign on to the big Git train, and soon the business analysts will be branching and rebasing as if they'd never used Subversion. But you can't just start using Git. In most businesses, no matter how agile they are, there are processes already in place, and in our business at least that process is heavily based around Subversion.</p>
<p>How do we start changing that process to use Git?</p>
<p>This is where Jason Sendelbach came to the rescue and talked about git svn. Since I use Git primarily by itself I had very little experience with git svn, but actually it really gelled into our existing infrastructure: we keep our existing Subversion server and even CruiseControl setup and git svn just builds on top of that, giving us the local power of git but without changing our existing Subversion setups.</p>
<p>Over time, new projects will be set up using only Git: but for now, to get developers using Git locally without committing ourselves to a new process, we're going to be using git svn and sending our developers to the excellent <a href="http://git.or.cz/course/svn.html">Git - SVN crash course</a>. We'll get the benefits of an agile Git repository and over time we'll migrate to actually use one.</p>
<p>I hope you find these tips as useful as they were for me. And hey, there might still be holdouts among the higher-ups: if you have any additional tips for ways to sell the business end on Git, why not share them with all of us?</p>
]]></content:encoded>
			<wfw:commentRss>http://www.pathf.com/blogs/2008/08/selling-git-on-the-business-end/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Getting Started with Facebooker</title>
		<link>http://www.pathf.com/blogs/2008/07/getting-started-with-facebooker/</link>
		<comments>http://www.pathf.com/blogs/2008/07/getting-started-with-facebooker/#comments</comments>
		<pubDate>Wed, 30 Jul 2008 20:53:37 +0000</pubDate>
		<dc:creator>Josh Symonds</dc:creator>
		
		<category><![CDATA[Agile Ajax]]></category>

		<category><![CDATA[Facebook]]></category>

		<category><![CDATA[Ruby on Rails]]></category>

		<guid isPermaLink="false">http://www.pathf.com/blogs/?p=1065</guid>
		<description><![CDATA[Developing for the Facebook platform can be a big headache, and on Rails your headaches are unfortunately compounded from the get-go. While the otherwise-inferior PHP users get an API library from the Facebook development team (I'm kidding, I love you PHP guys), on Rails we have to deal with gems that aren't even at version [...]]]></description>
			<content:encoded><![CDATA[<p>Developing for the Facebook platform can be a big headache, and on Rails your headaches are unfortunately compounded from the get-go. While the otherwise-inferior PHP users get an API library from the Facebook development team (I'm kidding, I love you PHP guys), on Rails we have to deal with gems that aren't even at version 1.0 yet. While Facebooker is quite good at this point, its <a href="http://facebooker.rubyforge.org/">documentation</a> covers a rather sparse selection of its impressive feature set, and RFacebook, which is better documented, hasn't been updated in aeons and is way more difficult to use besides. And unfortunately the standard <a href="http://apps.new.facebook.com/facebooker_tutorial/">Facebooker tutorial</a> doesn't include the newest features from the recent Facebook profile overhaul or even all the necessary steps to get a new Rails application running on Facebook. So, enter Josh.</p>
<p>In this blog post I'll tell you the best way to integrate Facebooker into a new Rails project so you can start developing social networking applications quickly and easily, and how to hook them in to Facebook's new profile plan. The goal is that by the end of this post you'll have a totally working Facebooker Rails application and you'll understand how to develop in it at least a little bit.</p>
<p><span id="more-1065"></span></p>
<h3>Getting Started</h3>
<pre class="bash">&nbsp;
rails <span style="color: #7a0874; font-weight: bold;">test</span>
<span style="color: #7a0874; font-weight: bold;">cd</span> <span style="color: #7a0874; font-weight: bold;">test</span>
<span style="color: #c20cb9; font-weight: bold;">rm</span> public/index.html
script/plugin <span style="color: #c20cb9; font-weight: bold;">install</span> git://github.com/mmangino/facebooker.git
&nbsp;</pre>
<p>Now go to <a href="http://www.facebook.com/developers/">the Facebook developer application</a> and add it in.</p>
<p style="margin: 5px 0px 10px 35px;">
	<a href="http://www.pathf.com/blogs/wp-content/uploads/2008/07/blog1.png"><br />
		<img src="http://www.pathf.com/blogs/wp-content/uploads/2008/07/blog1.png" alt="Allow Access to the Developer Application" title="Allow Access to the Developer Application"/><br />
	</a>
</p>
<p>Click on Allow, then on Create a New Application to get the ball rolling. Come up with a good name for your future masterpiece, read and agree to the Facebook TOS, and create your application.</p>
<p>You'll be dropped to your application page which lists your API key and your secret. Let's get those into our application. After you installed the Facebooker plugin, you'll find a new yml file in config called facebooker.yml. Copy and paste the API key and secret into facebooker.yml under the correct fields in the development environment (and also the production environment if this copy of the application will eventually be going live).</p>
<p>Now there are some settings we have to monkey with. Click on Edit Settings and you'll be taken to your application settings page. There are a couple hyper important things to do here.</p>
<p>The first is to fill in the callback URL. This is the real URL of the server that will be hosting your application. For development purposes, this should be a non-standard port on a server that you can open non-standard ports on. We'll change this to a more accessible port once we've finished development.</p>
<p>Secondly, the canvas URL specifies the location people will see in their address bar when they actually access your app. This is the point of access to your application for users -- if they go to the actual URL of your server (like www.test.com), they'll be redirected to this canvas page by Facebooker. So make it something memorable and sensible.</p>
<p style="margin: 5px 0px 10px 40px;">
<a href='http://www.pathf.com/blogs/wp-content/uploads/2008/07/blog10.png'><img src="http://www.pathf.com/blogs/wp-content/uploads/2008/07/blog10.png" alt="Callback URL and Canvas Path" title="Callback URL and Canvas Path" /></a>
</p>
<p>Third, ensure you've selected "yes" for "Can your application be added to Facebook?" Otherwise you're not going to be seeing your application in its full FBML glory anytime soon. When you click "yes" the "Installation Options" area appears. Check "Users" for who can add your Facebook application to your account, and also check the "Development Mode" box so only you can your team can install the app. </p>
<p>Once you've made those changes, save your application, and add in the canvas URL and canvas_page_name to facebooker.yml (in my example, http://www.test.com:8000 and pathfinder_test, respectively). Once you click save you'll be returned to your application settings page.</p>
<p style="margin: 5px 0px 10px 30px;">
<a href='http://www.pathf.com/blogs/wp-content/uploads/2008/07/blog4.png'><img src="http://www.pathf.com/blogs/wp-content/uploads/2008/07/blog4.png" alt="Application Info" title="Application Info" /></a>
</p>
<p>When you're returned to the application's setting page, click on the "View About Page" link. (It's in the lower right of the screen shot right above this). You'll then be looking at the application's about page, which should look a lot like this:</p>
<p style="margin: 5px 0px 10px 30px;">
<a href='http://www.pathf.com/blogs/wp-content/uploads/2008/07/blog6.png'><img src="http://www.pathf.com/blogs/wp-content/uploads/2008/07/blog6.png" alt="Application Homepage" title="Application Homepage" /></a>
</p>
<p>If it does, we're on the right track.</p>
<h3>Digging a Tunnel</h3>
<p>When you're developing Facebook apps, having a remote server to develop on is completely integral. If you're developing in FBML (and in the new version of the Facebook profile system, FBML is practically required), to see the results of your hard work you'll have to actually allow the Facebook servers to interpret your markup. That means they need access to your development machine, or you need a tunnel from your development machine to a remote server that's already accessible from the Internet, or you set up a staging server by following the advice of Noel Rappin's excellent blog post, <a href="http://www.pathf.com/blogs/2008/04/facebook-applic/">Facebook Application Logistics for Team Development</a>.</p>
<p>I recommend the latter route.</p>
<p>But if you don't have the resources to come up with your own staging server, we have to choose either your own computer or a tunnel. Opening up your computer to the Internet is a bad thing; development machines and networks have firewalls for a reason. So select a remote server that you have sudo rights to and let's get started building a tunnel.</p>
<p>Sudo rights are necessary because you'll likely have to edit your remote host's sshd config. (At least, I did.) Append this to the end of sshd_config:</p>
<pre>
GatewayPorts clientspecified
</pre>
<p>Now return to your handy-dandy facebooker.yml. Under the tunnel section for development, put in the username you have on the remote machine, the machine's URL, the port you can open on the remote machine (under public port), and the server you'll be running on your local machine (3000 is the Rails default).</p>
<p>Starting the tunnel is simple. From the root of your app:</p>
<pre>
rake facebooker:tunnel:start
</pre>
<p>You'll be asked for your SSH password to the remote server. If the connection is successful you will see nothing on this terminal session. Open up a new terminal and start your local server on your local port.</p>
<p>Navigate to http://apps.new.facebook.com/canvas_path and your server will report this routing error:</p>
<p style="margin: 5px 0px 10px 30px;">
<a href='http://www.pathf.com/blogs/wp-content/uploads/2008/07/blog7.png'><img src="http://www.pathf.com/blogs/wp-content/uploads/2008/07/blog7.png" alt="It Works! Kind of!" title="It Works! Kind of!" /></a>
</p>
<p>Congrats, we're up and running... sort of.</p>
<h3>Getting on the Rails</h3>
<p>We're seeing this error because Facebooker expects a route to be generated with :conditions => {:canvas => true} if it's intended for consumption by Facebook. We have no such route and there's nothing in our app at this point anyway. But now that we've finished with the Facebook side of this application, let's work on getting something in Rails that Facebook can understand.</p>
<p>A good place to start is our first scaffold.</p>
<pre>
script/generate scaffold airplane model:string pilot:string destination:string arrival:datetime
rake db:migrate
</pre>
<p>Unfortunately scaffolding won't do a whole lot to help us right away. We have to modify the Rails-generated files fairly significantly before our Facebook page will work. To start with, open up config/routes.rb. At the top you'll see map.resources :airplanes. Change that to:</p>
<pre class="ruby">&nbsp;
map.<span style="color:#9900CC;">resources</span> <span style="color:#ff3333; font-weight:bold;">:airplanes</span>, <span style="color:#ff3333; font-weight:bold;">:conditions</span> =&gt; <span style="color:#006600; font-weight:bold;">&#123;</span>:canvas =&gt; <span style="color:#0000FF; font-weight:bold;">true</span><span style="color:#006600; font-weight:bold;">&#125;</span>
&nbsp;</pre>
<p>And while we're here go ahead and uncomment map.root and change it to:</p>
<pre class="ruby">&nbsp;
map.<span style="color:#9900CC;">root</span> <span style="color:#ff3333; font-weight:bold;">:controller</span> =&gt; <span style="color:#996600;">&quot;airplanes&quot;</span>
&nbsp;</pre>
<p>Now our controller is connected correctly, but if you try to refresh you'll see we're getting 406 errors: the format that the request is coming in is unacceptable to the webserver. Fixing that is as easy as opening up config/initializers/mime_types.rb. Append this line to it:</p>
<pre class="ruby">&nbsp;
<span style="color:#6666ff; font-weight:bold;">Mime::Type</span>.<span style="color:#9900CC;">register_alias</span> <span style="color:#996600;">&quot;text/html&quot;</span>, <span style="color:#ff3333; font-weight:bold;">:fbml</span>
&nbsp;</pre>
<p>Restart your server after you save.</p>
<p>FBML will now be correctly processed by Rails, but your application still doesn't understand when to call FBML pages. You'll need to go into the airplanes_controller and change every format.html in a respond_to block to format.fbml. For example, after I altered the index action, it looked like this:</p>
<pre class="ruby">&nbsp;
app/controllers/airplanes_controller.<span style="color:#9900CC;">rb</span>
&nbsp;
<span style="color:#008000; font-style:italic;"># GET /airplanes</span>
<span style="color:#008000; font-style:italic;"># GET /airplanes.xml</span>
<span style="color:#9966CC; font-weight:bold;">def</span> index
  <span style="color:#0066ff; font-weight:bold;">@airplanes</span> = Airplanes.<span style="color:#9900CC;">find</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#ff3333; font-weight:bold;">:all</span><span style="color:#006600; font-weight:bold;">&#41;</span>
&nbsp;
  respond_to <span style="color:#9966CC; font-weight:bold;">do</span> |format|
    <span style="color:#CC0066; font-weight:bold;">format</span>.<span style="color:#9900CC;">fbml</span> <span style="color:#008000; font-style:italic;"># index.fbml.erb</span>
    <span style="color:#CC0066; font-weight:bold;">format</span>.<span style="color:#9900CC;">xml</span>  <span style="color:#006600; font-weight:bold;">&#123;</span> render <span style="color:#ff3333; font-weight:bold;">:xml</span> =&gt; <span style="color:#0066ff; font-weight:bold;">@airplanes</span> <span style="color:#006600; font-weight:bold;">&#125;</span>
  <span style="color:#9966CC; font-weight:bold;">end</span>
<span style="color:#9966CC; font-weight:bold;">end</span>
&nbsp;</pre>
<p>After you've finished that, there's another fun task awaiting you. Now our application knows that it's receiving FBML and that it has to call FBML pages when it gets a request formatted in FBML. Unfortunately we have no files that are formatted with FBML: they're all HTML right now. So, open up app/views and change every file there from *.html.erb to *.fbml.erb. Yes, this is kind of painful, but it's over quickly.</p>
<p>When you're done, your views should look like this.</p>
<p style="margin: 5px 0px 10px 120px;">
<a href='http://www.pathf.com/blogs/wp-content/uploads/2008/07/blog8.png'><img src="http://www.pathf.com/blogs/wp-content/uploads/2008/07/blog8.png" alt="What your airplane views should look like" title="What your airplane views should look like"/></a>
</p>
<p>Finally, you need to edit layouts/airplanes.fbml.erb. &lt;body&gt; tags are illegal in FBML and must be removed before Facebook will process our page. For simplicity's sake, I usually remove &lt;html&gt; and &lt;head&gt; as well, since you can't change the head of the page anyway. My layouts/airplanes.fbml.erb ended up looking this simple:</p>
<pre>
app/views/layouts/airplanes.fbml.erb

&lt;p style="color: green"><%= flash[:notice] %>&lt;/p>

<%= yield  %>
</pre>
<h3>The Fun Stuff: Getting Information</h3>
<p>Finally! Now that this is all accomplished, if you go to your canvas page in your browser, you should see your local server receive the request and render the airplanes index. You can go through the regular scaffold actions here but it's honestly not very exciting. Didn't I promise some FBML at the beginning? All we've really got here is HTML. Sure, it's cool and all, but can't we do something more with it?</p>
<p>The key to that 'something more' is inserting the following line at the top of airplanes_controller:</p>
<pre>
ensure_application_is_installed_by_facebook_user
</pre>
<p>This is a standard before filter and it accepts :except and :only just like a regular one might. If a user encounters this filter they'll be forced to install your application. Installation empowers an already-existing controller method that I haven't referenced before: facebook_session. facebook_session is the Facebooker object that allows you to make calls to the Facebook API server but it wasn't doing us a whole lot of good before now, since almost no API calls can be made before a user installs an application.</p>
<p>After a user installs your application, this changes dramatically. We can now leverage the power of the Facebook API to pull from and push to the user profile.</p>
<p>A good, straightforward idea at this point is to automatically identify the Facebook user when they visit to your application. Create a user model and make sure it has a uid string field in the migration. Once that's done, let's put in a quick before filter in our airplanes_controller:</p>
<pre class="ruby">&nbsp;
app/controllers/airplanes_controller.<span style="color:#9900CC;">rb</span>
&nbsp;
  before_filter <span style="color:#ff3333; font-weight:bold;">:get_user</span>
  ...
&nbsp;
  <span style="color:#9900CC;">private</span>
&nbsp;
  <span style="color:#9966CC; font-weight:bold;">def</span> get_user
    <span style="color:#0066ff; font-weight:bold;">@current_user</span> =
      User.<span style="color:#9900CC;">find_or_create_by_uid</span><span style="color:#006600; font-weight:bold;">&#40;</span>facebook_session.<span style="color:#9900CC;">user</span>.<span style="color:#9900CC;">id</span><span style="color:#006600; font-weight:bold;">&#41;</span>
  <span style="color:#9966CC; font-weight:bold;">end</span>
&nbsp;</pre>
<p>Now you'll automatically load the @current_user every time they return to your Facebook app. You'll probably want to tie most of your application data to this user: their posters, their songs, whatever your Facebook application does, this is the easy way to identify the incoming Facebook user and get their stuff accordingly.</p>
<p>You can call any of a user's profile information from the facebook_session.user object, like facebook_session.user.name, facebook_session.user.books, and so on and so forth. (id obviously returns the Facebook user id for our subject.)</p>
<h3>The Funner (More Fun) Stuff: Setting Information</h3>
<p>Of course, our application can't reasonably be considered cool unless it can put messages all over a user's profile. Facebooker provides an amazing utility to do this that is almost hilariously under-documented: it allows you to set up ActionMailer-style models to deliver information straight to a user's profile!</p>
<p>Before we actually update the user's profile, though, we must have permission to do it. The new Facebook profile system requires you to specifically request permission to add your application to a user's profile; if you send information to their profile before you request information, you'll get a success message but nothing will appear on the user profile. Let's put in a cute little block in the airplane layout to bug a user to add our app to their profile:</p>
<pre>
app/views/layouts/airplanes.fbml.erb

&lt;fb:if-section-not-added section="profile">
  &lt;p>Add Airplanes to your profile to see it listed there.&lt;/p>
  &lt;fb:add-section-button section="profile" />
&lt;/fb:if-section-not-added>
</pre>
<p>Thanks to the magic of FBML the if-section-not-added tags appear only if the section isn't added for the users; the add-section-button presents them with a button to add your application to their profile. Once they've added your application this section will disappear and you'll be able to update their profile as per normal.</p>
<p>To add information to a user's profile, make a new file in the models directory, and name it as if it were an ActionMailer.</p>
<pre class="ruby">&nbsp;
app/models/user_mailer.<span style="color:#9900CC;">rb</span>
&nbsp;
<span style="color:#9966CC; font-weight:bold;">class</span> UserMailer &lt; <span style="color:#6666ff; font-weight:bold;">Facebooker::Rails::Publisher</span>
&nbsp;
  <span style="color:#9966CC; font-weight:bold;">def</span> profile<span style="color:#006600; font-weight:bold;">&#40;</span>user<span style="color:#006600; font-weight:bold;">&#41;</span>
    send_as <span style="color:#ff3333; font-weight:bold;">:profile</span>
    from user
    recipients user
    fbml = <span style="color:#996600;">&quot;This is some test FBML that will be inserted into a user's profile.&quot;</span>
    profile<span style="color:#006600; font-weight:bold;">&#40;</span>fbml<span style="color:#006600; font-weight:bold;">&#41;</span>
    profile_main<span style="color:#006600; font-weight:bold;">&#40;</span>fbml<span style="color:#006600; font-weight:bold;">&#41;</span>
  <span style="color:#9966CC; font-weight:bold;">end</span>
&nbsp;
<span style="color:#9966CC; font-weight:bold;">end</span>
&nbsp;</pre>
<p>Obviously, the mailer is descending from Facebooker::Rails::Publisher instead of the regular ActionMailer. send_as :profile instructs the Publisher to send this as a profile update, rather than a mini-feed update or other Facebook content type. You can designate the user the profile update is from and the one that it's to: in my application they're both the same, but they might differ for yours. You can render the FBML from a file here too if you want.</p>
<p>Setting profile is the deprecated way of updating a user's profile: profile_main is the way used in the new Facebook styles, but for backwards compatibility include both here.</p>
<p>Now, from your controller, simply include this line in an action to update their profile:</p>
<pre class="ruby">&nbsp;
UserMailer.<span style="color:#9900CC;">deliver_profile</span><span style="color:#006600; font-weight:bold;">&#40;</span>facebook_session.<span style="color:#9900CC;">user</span><span style="color:#006600; font-weight:bold;">&#41;</span>
&nbsp;</pre>
<p>The profile information will be packaged and sent off to the target user and will appear immediately in their profile (provided they've added your app).</p>
<h3>Going Further</h3>
<p>Obviously this is a very broad overview of the power of Facebooker, concentrating more on its installation and setup then how to really leverage its power. If you want to figure out everything it can do, the <a href="http://apps.new.facebook.com/facebooker_tutorial/">Facebooker tutorial on the Facebook</a> is sure to be a great help to you. Otherwise my suggestion to you is to inspect the source of Facebooker to really understand its functionality. As I said at the beginning of the document, it is unfortunately not very well documented at all, but at least if you follow the advice I've posted here you'll have an excellent start for developing your Facebook applications.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.pathf.com/blogs/2008/07/getting-started-with-facebooker/feed/</wfw:commentRss>
		</item>
		<item>
		<title>DRYing up Rails Controllers: Polymorphic and Super Controllers</title>
		<link>http://www.pathf.com/blogs/2008/07/drying-up-rails-controllers-polymorphic-and-super-controllers/</link>
		<comments>http://www.pathf.com/blogs/2008/07/drying-up-rails-controllers-polymorphic-and-super-controllers/#comments</comments>
		<pubDate>Wed, 09 Jul 2008 04:48:13 +0000</pubDate>
		<dc:creator>Josh Symonds</dc:creator>
		
		<category><![CDATA[Agile Ajax]]></category>

		<category><![CDATA[Ruby on Rails]]></category>

		<guid isPermaLink="false">http://www.pathf.com/blogs/?p=1012</guid>
		<description><![CDATA[Controllers are an obvious point to find repeated behavior in an application. Identical methods across many controllers are a very common problem: consider comments, for example, where you might encounter an add_comment and remove_comment in every controller. Or think of all the controllers that render the same actions in the same way. Maybe they implement [...]]]></description>
			<content:encoded><![CDATA[<p>Controllers are an obvious point to find repeated behavior in an application. Identical methods across many controllers are a very common problem: consider comments, for example, where you might encounter an add_comment and remove_comment in every controller. Or think of all the controllers that render the same actions in the same way. Maybe they implement very basic CRUD functionality but have very complicated AJAXy tricks. You find yourself typing in those tricks over and over again on every controller. Let's fix that! By using a few neat techniques, we can significantly DRY up our controllers and end up with code that's not only very reusable, but very easily changeable to effect significant alterations in our application.<br />
<span id="more-1012"></span><br />
Let's start with the first problem: identical actions across many controllers. What we really want is a controller that responds to many different requests the same way, without caring what those requests are as long as they fit our rather generalized expectations. This is an instance of polymorphism. But is there a good way to implement it in controllers? While there is, before we start, let's take a quick look at how Rails implements polymorphism in models to get an idea for how we can implement it ourselves.</p>
<h3>Polymorphic Models</h3>
<p>Many Rails models have a polymorphic relationship with other models. Think of comments, for example. If you wanted to implement comments on your website, then you'd want to apply them everywhere; for example, it would be nice if you could add comments to users, and projects, and events, and meetings... well, to more or less everything. In this use case, we call comments polymorphic: they can belong to many different models. This is an easy relationship to establish in Rails:</p>
<pre>
app/models/comment.rb
class Model < ActiveRecord::Base
  belongs_to :commenter, :polymorphic => true
end

app/models/user.rb
class User < ActiveRecord::Base
  has_many :comments, :as => :commenter
end

app/models/project.rb
class Project < ActiveRecord::Base
  has_many :comments, :as => :commenter
end
</pre>
<p>Each model has_many :comments as :commenter. Comment.rb in turn says it belongs to a :commenter with a polymorphic relationship. As long as the comments table has a commenter_type string field and commenter_id integer field, Rails fills in all the details, and you can code:</p>
<pre>
user.comments.create(:body => "This is a user comment.")
post.comments.create(:body => "But this is a post comment.")
</pre>
<p>With equal ease. While this solution is extremely elegant it starts to fall apart in the controllers (which is why this post is about controllers, not about models). There's no natural polymorphic solution for controllers, so I frequently see repeated code across controllers with methods like add_comment, edit_comment, and remove_comment on the users controller, the posts controller, and all other controllers where comments may be added to their model.</p>
<p>While it may seem like the obvious solution is to create a module and mix it in to the controllers with the comment code, there's an even easier way to DRY this up: make your controller as polymorphic as the model.</p>
<h3>Polymorphic Controllers</h3>
<p>A polymorphic controller works exactly like a polymorphic model. It receives a type and an ID just like the model does: using the type it establishes the model class, and using the ID it finds a member of that class (specifically, the one which we are adding the comment to). Let's continue with our previous example and implement a fully-functioning comments controller for a polymorphic model called Comment.</p>
<p>We know that this controller will be receiving two params all the time: commenter_type and commenter_id. We can use these to find the model object that we want to add comments to before we do anything else.</p>
<pre>
app/controllers/comments_controller.rb
class CommentsController < ApplicationController
  before_filter :find_commenter

  private

  def find_commenter
    @klass = params[:commenter_type].capitalize.constantize
    @commenter = klass.find(params[:commenter_id])
  end
end
</pre>
<p>Using the handy-dandy Rails helper <code>constantize</code>, we convert the string representation of the class (once it is correctly capitalized) into the constant referring to the class itself. Afterwards it is simplicity itself to find the actual commenter by finding on its class. Let's capitalize on our success and add in a create action.</p>
<pre>
app/controllers/comments_controller.rb
class CommentsController < ApplicationController
...
  def create
    @comment = @commenter.comments.create(params[:comments])
    respond_to do |format|
      format.html {redirect_to :controller => @commenter.class.to_s.pluralize.downcase, :action => :show, :id => @commenter.id}
    end
  end
...
end
</pre>
<p>This example assumes that the other controller classes are named for their pluralized models (which is also Rails' assumption). Now it is easy for us to add in code to every view that we want to create a comment in:</p>
<pre>
app/views/users/show.html.erb
<-- User show code here -->
<% form_for @comment, :url => comments_path(:commenter_type => "user", :commenter_id => @user.id) do |f| %>
  <%= f.text_field :body %>
<% end %>

app/controllers/users_controller.rb
def show
  @user = User.find(params[:id])
  @comment = Comment.new
end
</pre>
<p>That comments_path is rather ugly, though. Allow me to suggest a small helper to improve the readability of your code at the cost of some convention expectations on your part:</p>
<pre>
app/helpers/application_helper.rb
def commenter_url
  commenter = controller.controller_name.singularize
  comments_path(:commenter_type => commenter, :commenter_id => controller.instance_variable_get("@#{commenter}").id)
end
</pre>
<p>The convention expectation here is that you will name an instance variable in your controller after that controller. For example, in the users_controller.rb I showed earlier, @user fulfills that requirement: it is an instance variable named after its own controller. Now the show view would look like this:</p>
<pre>
app/views/users/show.html.erb
<% form_for @comment, :url => commenter_url do |f| %>
  <%= f.text_field :body %>
<% end %>
</pre>
<p>Commenter_url automatically fills in the commenter_type as "user" (the singularized name of itself) and the commenter_id as @user.id (by getting the instance variable @user set on the controller and referencing its ID) and creates a link to a new comment. This helper is easily reusable across all of your controllers and saves you the trouble of retyping the same comments_path every time you want to make a form for a new comment.</p>
<h3>Super Controllers</h3>
<p>Sometimes you have rather basic CRUD-like functionality in many controllers. All of that functionality is supposed to render the same, regardless of the controller. For example, let's say we have a meeting model and a user model. Meetings and users are different, but in our system they're going to end up being shown in exactly the same way: we render the action that they respond to, or if we received an xhr request we update a specific dom element on the page.</p>
<p>This is a perfect use case for super controllers. All Rails controllers already descend from a super controller: the application controller, held in app/controllers/application.rb. It is trivial for us to extend this descent hierarchy another step, and by doing so we can sometimes save ourselves a significant amount of time. Consider these two controllers:</p>
<pre>
app/controllers/users_controller.rb
class UsersController < ApplicationController
def update
  @user = User.find(params[:id])
  @user.update_attributes(params[:user])
  respond_to do |format|
    format.html {redirect_to :action => :show, :id => @user.id}
    format.js {render :update do |page|
      page.replace_html dom_id(@user), :partial => "user"
    end}
  end
end

app/controllers/meetings_controller.rb
class MeetingsController < ApplicationController
def update
  @meeting = Meeting.find(params[:id])
  @meeting.update_attributes(params[:meeting])
  @meeting.send_edit_notification # Inform the meetings' participants that it has been editted
  respond_to do |format|
    format.html {redirect_to :action => :show, :id => @user.id}
    format.js {render :update do |page|
      page.replace_html dom_id(@user), :partial => "user"
    end}
  end
end
</pre>
<p>It should be fairly obvious exactly where these methods are the same. But we can't use the same controller for both of them: if we did then the @meeting.send_edit_notification wouldn't be called correctly. The solution is a super-controller that encompasses both of them:</p>
<pre>
app/controllers/users_controller.rb
class UsersController < GenericController
def update
  @user = User.find(params[:id])
  @user.update_attributes(params[:user])
  super
end

app/controllers/meetings_controller.rb
class MeetingsController < GenericController
def update
  @meeting = Meeting.find(params[:id])
  @meeting.update_attributes(params[:meeting])
  @meeting.send_edit_notification # Inform the meetings' participants that it has been editted
  super
end

app/controllers/generic_controller.rb
class GenericController < ApplicationController

protected

def update
  instance_variable = instance_variable_get("@#{controller_name.singularize}"
  respond_to do |format|
    format.html {redirect_to :action => :show, :id => instance_variable.id}
    format.js {render :update do |page|
      page.replace_html dom_id(instance_variable), :partial => controller_name.singularize
    end}
  end
end
</pre>
<p>Both UsersController and MeetingsController now descend from the Generic Controller, whose methods are protected (so that only children or itself may access them). Both of the children controllers call super at the end of their method, which evaluates the method of their parent in their context. The parent finds the instance variable we set earlier and then responds correctly based on it. (Interestingly we could even have moved the update_attributes into the parent update method with only a bit of finagling, but I think my point has come across).</p>
<p>Note that the amount of work we've done to extract update to a parent class is minimal, while the take away is huge. If the respond_to block was very large or complicated, as it may sometimes be, being able to have it all in one place to edit for both controllers at once is a huge boon and a great time-saver.</p>
<p>While I've made great use of polymorphic controllers in the past, I've only just started exploring the possibilities that super controllers present in a recent project. They saved me a great deal of time and have allowed me to considerably extract some code that otherwise would have been repeated across three different controllers -- and that's only a start. By employing polymorphic controllers and super controllers, your Rails code will improve immeasurably, in both readability and maintainability. I hope you find these techniques as useful and elegant as I have.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.pathf.com/blogs/2008/07/drying-up-rails-controllers-polymorphic-and-super-controllers/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Pretty blocks in Rails views</title>
		<link>http://www.pathf.com/blogs/2008/07/pretty-blocks-in-rails-views/</link>
		<comments>http://www.pathf.com/blogs/2008/07/pretty-blocks-in-rails-views/#comments</comments>
		<pubDate>Tue, 01 Jul 2008 19:27:00 +0000</pubDate>
		<dc:creator>Josh Symonds</dc:creator>
		
		<category><![CDATA[Agile Ajax]]></category>

		<category><![CDATA[Ruby on Rails]]></category>

		<guid isPermaLink="false">http://www.pathf.com/blogs/?p=998</guid>
		<description><![CDATA[One of the easiest ways to improve the readability and reusability of a Rails application is to refactor the view layer. I find that most Rails code I look at in models and controllers tends to be very good, but views are a huge mess of single-use partials, repeated behavior, and lots and lots of [...]]]></description>
			<content:encoded><![CDATA[<p>One of the easiest ways to improve the readability and reusability of a Rails application is to refactor the view layer. I find that most Rails code I look at in models and controllers tends to be very good, but views are a huge mess of single-use partials, repeated behavior, and lots and lots of missed opportunities to implement some really graceful and reusable helpers. I wanted to whomp up a quick blog post discussing some of my favorite techniques for making views prettier.</p>
<p><span id="more-998"></span></p>
<h3>Use Blocks in Helpers</h3>
<p>Ruby makes extensive use of blocks. So as good Rails programmers we want to follow in that grand tradition and make everything that can be blocky blocked. One of the first pieces of code I add to the application helper for a project is an override to <code>link_to</code> to accept a block:</p>
<pre>def link_to(*args,&amp;block)
  if block_given?
    concat(super(capture(&amp;block), *args), block.binding)
  else
    super(*args)
  end
end
</pre>
<p>This functionality is already in Edge Rails, and if you actually use this helper there it will fail because of it. This makes it extremely easy to make links of all kinds in your application:</p>
<pre>&lt;% link_to(users_path) do %&gt;
  &lt;%= image_tag "user_button.png" %&gt;
  <span class="user_add">Click here to add a user</span>
&lt;% end %&gt;
</pre>
<p>Imagine how ugly that would be without the use of a block! It would be one big multi-line mess. Here, we have clarity and ease of use, and we don't sacrifice anything. In this example I use the two most important methods for making views accept blocks: <code>concat</code> and <code>capture</code>. Through a more common use case, let's take a closer look at these methods, and why block helpers can make your life a whole lot easier.</p>
<h3>Rounded Corners</h3>
<p>We want to add some rounded corners to our application. Without any code, this is how we make them:</p>
<pre>&nbsp;
&lt;div class=&quot;rounded_box&quot;&gt;
&lt;div class=&quot;rounded_corner_top&quot;&gt;&lt;/div&gt;
&lt;div class=&quot;rounded_corner_content&quot;&gt;Rounded corners are so Web 2.0.&lt;/div&gt;
&lt;div class=&quot;rounded_corner_bottom&quot;&gt;&lt;/div&gt;
&lt;/div&gt;
&nbsp;</pre>
<p>Initially it might be tempting to make two methods to output the start and end of the helper:</p>
<pre>&lt;%= rounded_top %&gt;
Rounded corners are so Web 2.0.
&lt;%= rounded_bottom %&gt;
</pre>
<p>These are easy helper methods that we can clearly understand. Here's what the first looks like.</p>
<pre>def rounded_top
  return '&lt;div class="rounded_box"&gt;\n' +
    '&lt;div class="rounded_corner_top"&gt;&lt;/div&gt;\n' +
    '&lt;div class="rounded_corner_content"&gt;'
end</pre>
<p>But now we have a fair amount of ugly HTML in our helper. And will there ever be a case that we call <code>rounded_top</code> without wanting <code>rounded_bottom</code> an arbitrary amount of time afterwards? The answer would be no, so let's link the two together in a much more clever manner.</p>
<pre>&lt;% rounded_block do %&gt;
Rounded corners are so Web 2.0.
&lt;% end %&gt;
</pre>
<p>This is an ERb evaluation block, not an output block: this is because we are going to replace the content directly on the page rather than output anything at all. (Thus our helper method will function similarly to other Rails evaluation blocks like <code>form_for</code>.) So let's make it happen.</p>
<pre class="ruby"><span style="color:#9966CC; font-weight:bold;">def</span> rounded_block<span style="color:#006600; font-weight:bold;">&#40;</span>&amp;block<span style="color:#006600; font-weight:bold;">&#41;</span>
  concat<span style="color:#006600; font-weight:bold;">&#40;</span>content_tag<span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#ff3333; font-weight:bold;">:div</span>, <span style="color:#ff3333; font-weight:bold;">:class</span> =&gt; <span style="color:#996600;">&quot;rounded_box&quot;</span><span style="color:#006600; font-weight:bold;">&#41;</span> <span style="color:#9966CC; font-weight:bold;">do</span>
    content_tag<span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#ff3333; font-weight:bold;">:div</span>, <span style="color:#996600;">&quot; &quot;</span>, <span style="color:#ff3333; font-weight:bold;">:class</span> =&gt; <span style="color:#996600;">&quot;rounded_corner_top&quot;</span><span style="color:#006600; font-weight:bold;">&#41;</span> +
    content_tag<span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#ff3333; font-weight:bold;">:div</span>, <span style="color:#ff3333; font-weight:bold;">:class</span> =&gt; <span style="color:#996600;">&quot;rounded_corner_content&quot;</span><span style="color:#006600; font-weight:bold;">&#41;</span> <span style="color:#9966CC; font-weight:bold;">do</span>
      capture<span style="color:#006600; font-weight:bold;">&#40;</span>&amp;block<span style="color:#006600; font-weight:bold;">&#41;</span>
    <span style="color:#9966CC; font-weight:bold;">end</span> +
    content_tag<span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#ff3333; font-weight:bold;">:div</span>, <span style="color:#996600;">&quot; &quot;</span>, <span style="color:#ff3333; font-weight:bold;">:class</span> =&gt; <span style="color:#996600;">&quot;rounded_corner_bottom&quot;</span><span style="color:#006600; font-weight:bold;">&#41;</span>
  <span style="color:#9966CC; font-weight:bold;">end</span>, block.<span style="color:#CC0066; font-weight:bold;">binding</span><span style="color:#006600; font-weight:bold;">&#41;</span>
<span style="color:#9966CC; font-weight:bold;">end</span>
&nbsp;</pre>
<p>Let's dissect this helper quickly. <code>Rounded_block</code> accepts one argument, a block: in the middle, we capture that block, removing it from the page and returning it inside the helper. (We call this instead of yield, because if we yielded the block, it would appear twice on the page.) We add three content divs together and finally <code>concat</code> the whole shebang onto the block's binding which causes it to actually be displayed in the layout. <strong>Remember the plusses!</strong> Without them you'll only get the last content_tag, which is almost certainly not what you want.</p>
<p>This method is highly extensible and extremely flexible. Here's an example of the rounded_corner code I actually use in my applications:</p>
<pre>&lt;% rounded_yellow_box(:background =&gt; true, :title =&gt; "What I think about rounded corners", :id =&gt; "rounded_thoughts" ) %&gt;
  They're so Web 2.0-y.
&lt;% end %&gt;
</pre>
<p>And the code for it:</p>
<pre class="ruby"><span style="color:#9966CC; font-weight:bold;">def</span> rounded_box<span style="color:#006600; font-weight:bold;">&#40;</span>color, options = <span style="color:#006600; font-weight:bold;">&#123;</span><span style="color:#006600; font-weight:bold;">&#125;</span>, &amp;block<span style="color:#006600; font-weight:bold;">&#41;</span>
  <span style="color:#CC0066; font-weight:bold;">raise</span> <span style="color:#CC00FF; font-weight:bold;">ArgumentError</span>, <span style="color:#996600;">&quot;Missing block&quot;</span> <span style="color:#9966CC; font-weight:bold;">unless</span> block_given?
  options.<span style="color:#9900CC;">symbolize_keys</span>!
    concat<span style="color:#006600; font-weight:bold;">&#40;</span>content_tag<span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#ff3333; font-weight:bold;">:div</span>, <span style="color:#ff3333; font-weight:bold;">:id</span> =&gt; options<span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#ff3333; font-weight:bold;">:id</span><span style="color:#006600; font-weight:bold;">&#93;</span>, <span style="color:#ff3333; font-weight:bold;">:class</span> =&gt; <span style="color:#996600;">&quot;rounded_box&quot;</span><span style="color:#006600; font-weight:bold;">&#41;</span> <span style="color:#9966CC; font-weight:bold;">do</span>
      <span style="color:#9966CC; font-weight:bold;">if</span> options<span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#ff3333; font-weight:bold;">:title</span><span style="color:#006600; font-weight:bold;">&#93;</span> <span style="color:#9966CC; font-weight:bold;">then</span> content_tag<span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#ff3333; font-weight:bold;">:div</span>, options<span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#ff3333; font-weight:bold;">:title</span><span style="color:#006600; font-weight:bold;">&#93;</span>, <span style="color:#ff3333; font-weight:bold;">:class</span> =&gt; <span style="color:#996600;">&quot;rounded_title&quot;</span><span style="color:#006600; font-weight:bold;">&#41;</span> <span style="color:#9966CC; font-weight:bold;">else</span> <span style="color:#996600;">&quot;&quot;</span> <span style="color:#9966CC; font-weight:bold;">end</span> +
      content_tag<span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#ff3333; font-weight:bold;">:div</span>, <span style="color:#996600;">&quot; &quot;</span>, <span style="color:#ff3333; font-weight:bold;">:class</span> =&gt; <span style="color:#996600;">&quot;rounded_corner_top&quot;</span><span style="color:#006600; font-weight:bold;">&#41;</span> +
      content_tag<span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#ff3333; font-weight:bold;">:div</span>, <span style="color:#ff3333; font-weight:bold;">:class</span> =&gt; <span style="color:#9966CC; font-weight:bold;">if</span> options<span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#ff3333; font-weight:bold;">:background</span><span style="color:#006600; font-weight:bold;">&#93;</span> <span style="color:#996600;">&quot;rounded_corner_content&quot;</span> <span style="color:#9966CC; font-weight:bold;">else</span> <span style="color:#996600;">&quot;rounded_corner_no_bg&quot;</span> <span style="color:#9966CC; font-weight:bold;">end</span><span style="color:#006600; font-weight:bold;">&#41;</span> <span style="color:#9966CC; font-weight:bold;">do</span>
        capture<span style="color:#006600; font-weight:bold;">&#40;</span>&amp;block<span style="color:#006600; font-weight:bold;">&#41;</span>
      <span style="color:#9966CC; font-weight:bold;">end</span> +
      content_tag<span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#ff3333; font-weight:bold;">:div</span>, <span style="color:#996600;">&quot; &quot;</span>, <span style="color:#ff3333; font-weight:bold;">:class</span> =&gt; <span style="color:#996600;">&quot;rounded_corner_bottom&quot;</span><span style="color:#006600; font-weight:bold;">&#41;</span>
    <span style="color:#9966CC; font-weight:bold;">end</span>, block.<span style="color:#CC0066; font-weight:bold;">binding</span><span style="color:#006600; font-weight:bold;">&#41;</span>
<span style="color:#9966CC; font-weight:bold;">end</span>
&nbsp;
<span style="color:#9966CC; font-weight:bold;">def</span> method_missing<span style="color:#006600; font-weight:bold;">&#40;</span>method, *args, &amp;block<span style="color:#006600; font-weight:bold;">&#41;</span>
  <span style="color:#9966CC; font-weight:bold;">if</span> method.<span style="color:#9900CC;">to_s</span> =~ /^rounded_<span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#006600; font-weight:bold;">&#91;</span>a-z<span style="color:#006600; font-weight:bold;">&#93;</span>+<span style="color:#006600; font-weight:bold;">&#41;</span>_box$/
    rounded_box<span style="color:#006600; font-weight:bold;">&#40;</span>$<span style="color:#006666;">1</span>, *args, &amp;block<span style="color:#006600; font-weight:bold;">&#41;</span>
  <span style="color:#9966CC; font-weight:bold;">else</span>
    <span style="color:#9966CC; font-weight:bold;">super</span>
  <span style="color:#9966CC; font-weight:bold;">end</span>
<span style="color:#9966CC; font-weight:bold;">end</span>
&nbsp;</pre>
<p>A little dense, but extremely flexible: you can use helper methods like this to generate a lot of content situationally and change your block elements around quite a bit. Having this sort of agility can be invaluable in projects that demand many similar but different parts of the view layer.</p>
<h3>Extending Blocks to Partials</h3>
<p>Let's be honest: that <code>rounded_block</code> helper, though attractively simple, uses a fair amount of <code>content_tags</code>. Can we make this even simpler? Turns out we can by employing a little-used feature of partials: layout.</p>
<pre>show.html.erb
&lt;% render(:layout =&gt; 'rounded') do %&gt;
  Rounded corners are so Web 2.0.
&lt;% end %&gt;

_rounded.html.erb:
&lt;div class="rounded_box"&gt;
  &lt;div class="rounded_corner_top"&gt; &lt;/div&gt;
    &lt;div class="rounded_corner_content"&gt;&lt;%= yield %&gt;&lt;/div&gt;
  &lt;div class="rounded_corner_bottom"&gt; &lt;/div&gt;
&lt;/div&gt;
</pre>
<p>Or to really simplify your life, you can do the partial render on one line, if you're trying to put one partial into our rounded_corner layout:</p>
<pre>_content.html.erb
Rounded corners are so Web 2.0.

show.html.erb
&lt;%= render :partial =&gt; "content", :layout =&gt; "rounded" %&gt;
</pre>
<p>Couldn't be easier. You can even pass locals and collections to the partial call just as you might to a regular call to render partial:</p>
<pre>&lt;% render(:layout =&gt; 'rounded', :locals =&gt; {:title =&gt; "What I think about rounded corners", :id =&gt; "rounded_thoughts", :background =&gt; true}) do %&gt;
  Rounded corners are so Web 2.0.
&lt;% end %&gt;
</pre>
<p>And then in _rounded.html.erb:</p>
<pre>&lt;div class="rounded_box"&gt;
  &lt;div class="rounded_corner_top" id="&lt;%= id %&gt;"&gt; &lt;/div&gt;
    &lt;% if title %&gt;
      &lt;div class="rounded_title"&gt;&lt;%= title %&gt;&lt;/div&gt;
    &lt;% end %&gt;
    &lt;div class="&lt;%= background ? "rounded_corner_content" : "rounded_corner_no_bg" %&gt;"&gt;&lt;%= yield %&gt;&lt;/div&gt;
  &lt;div class="rounded_corner_bottom"&gt; &lt;/div&gt;
&lt;/div&gt;
</pre>
<h3>To Sum It All Up</h3>
<p>So which way is better? Both solutions offer a lot to DRY up your application with: they make your code extremely reusable and powerful. Theoretically speaking the <code>method_missing</code> happiness I inserted earlier is slow, but the pages will probably be cached at this point anyway so really it's just a matter of style. I tend to use helper methods when things seem extremely programmatic to me: passing an options hash is very Rails-y and sensible. Conversely, I use partials when the layout is almost entirely HTML that won't be changing very much. But really the two methods are very interchangeable: just make sure to use them when you've got a lot of repeating code!</p>
<p>And as a small end-note: Edge Rails is changing the way that <code>concat</code> and <code>capture</code> work. <code>concat</code> will no longer need a binding to be attached to the page. Now it binds directly to the new @erbout instance variable and is appended straight to the buffer, which not only improves performance, but increases the readability of the helpers I made above.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.pathf.com/blogs/2008/07/pretty-blocks-in-rails-views/feed/</wfw:commentRss>
		</item>
	</channel>
</rss>
