You know how you go to a conference and most of the smart, interesting folks are using Apple hardware? I’ve been noticing a trend among my colleagues at work and those whom I’ve met at user groups and conferences—the very same folks who are at the top of their game developing software also drive Acuras. Coincidence? Disclaimer: Yes, I drive a 2004 Acura TL and one reason (out of many) that I bought the car was for the technology (bluetooth hands-free-link, for example). Though I’m not conceited enough to consider myself a kick-ass software engineer.
February NoVA Ruby Users Group
This month we had Chad Fowler as a guest speaker at NoVA RUG. His talk was entitled “Quick and Clean Rails Development.” Here’s the abstract for his talk:
Rails is all about speed. It has been said that Rails programmers can develop software ten times faster than those programming in technologies such as .NET or J2EE. Rails itself is evolving at the speed of light. But, to paraphrase Martin Fowler’s RailsConf 2006 keynote, with Rails we don’t have to choose between Quick and Dirty and Slow and Clean. With Ruby, and therefore Rails, we can have both speed and maintainability. With Rails, the speed comes naturally. As it turns out, the cleanliness often doesn’t. This talk will focus on how to make your application development both quick _and_ clean.
Read on for a summary of Chad’s talk. Update: I found a video of this talk which Chad gave at Rails eXchange in London here. This presentation was a grab-bag of techniques to clean-up your Rails code, making it easier to maintain. Stick with CRUD. If you find yourself deviating from the create, show, update and destroy methods in your controller you need to rethink your design/schema so that you can map it to CRUD. Chad said that placing this constraint on his controller design led to much cleaner and easier to maintain code. Over Do MVC
- No SQL in your controllers (or views). Basically if you’re calling find with multiple arguments in your controller, you’re violating this principle. Here’s some before and after code:
{lang=“ruby”}
class PostsController < ApplicationController
def index
@recent_articles = Post.find(:all, : order => “created_at DESC”, :limit => 5)
@recent_visits = @user.visits.find(:all, : order => “created_at DESC”, :limit => 5)
end
end
and after:
{lang=“ruby”}
class Post < ActiveRecord::Base
def self.recent(limit = 5)
self.find(:all, : order => “created_at DESC”, :limit => limit)
end
end
class User < ActiveRecord::Base
has_many :visits do
def recent(limit = 5)
self.find(:all, : order => “created_at DESC”, :limit => 5)
end
end
end
class PostsController < ApplicationController
def index
@recent_articles = Post.recent
@recent_visits = @user.visits.recent
end
end
- No more than four lines per action in the controller
- No code in your view. This means putting your code in the helpers (or modules included by your helpers) to keep the view clean. Chad also recommended investigating other templating libraries like Amrita.
I really hope that Chad will make this presentation available online as there were some great examples in his slides. Next month I’ll be presenting at NoVA RUG on RESTful Rails (CRUD, REST and, if I can fit it in, ActiveResource).
The Rails Edge Day 3
By the final day of the conference my head was about to explode with the amount of new information crammed into it. There were some great tips and tricks on the final day, but overall, I think the conference peaked on day two. Here’s a run down of the sessions for day three:
- Buried Treasure: Hidden Rails Tips by Dave Thomas
- The Streamlined Framework by Justin Gehtland
- Rinda and DRb by Justin Gehtland
- Amazon’s S3 Web Services by Marcel Molina, Jr.
- Rake: Building Up Ruby by Jim Wierich
- Rails Production Tips and Tricks by James Duncan Davidson
Dave Thomas started out the day with a collection of Rails (and Ruby) tips and tricks that he’s acquired. He gave an overview of with_scope which sets default params for ActiveRecord methods. Next were named routes with_options and the fact that with_options works with any method that takes a hash (such as table creation in migrations). The returning … do … end block format which saves you from having to explicitly return your object after doing some other work first. The ampersand-colon trick which Dave calls the Blockinator:
{lang=“ruby”}
%w{ cat dog }.map(&:upcase)
The date and time goodies added by Rails were discussed next (such as the various to_s versions, like :db, :short, :long and ActiveSupport’s DATE_FORMATS hash which you can add your own formats to in environment.rb). Enumerable extensions such as group_by, index_by and sum. Array extensions like in_groups_of and to_sentence. String extensions like at, from, to, first, last and each_char. Subversion integration in the Rails scripts (—svn option to generate/destroy). Using your app via the console, reload! in the console, setting a default object in irb. And several useful TextMate tricks. Next up was Justin with his talk about Streamlined. Streamlined is a pretty nice framework for building the back-end of your Rails app (or for an enterprise web app, possibly the front-end as well). But, frankly, I’m sick and tired of hearing about it. I’ve attended at least four different events where either Stu or Justin presented Streamlined. After a short break, Justin came back and spoke about Rinda and DRb. Since I’d attended Brian Sletten’s NoVA RUG presentation this was all review for me. The ideas behind Rinda and DRb are very interesting and I would encourage you to read up on them. Next Marcel gave an overview of his AWS::S3 library which makes it very easy to use Amazon’s S3 service from your Ruby programs and it even comes with an interactive shell for working with S3. Following lunch Jim gave an excellent presentation on Rake and showed how to create a task for generating graphs in PNG format from digraph models. He started off with a very simple example and then refactored it to use the various features of Rake such as dependencies, file tasks, file lists, dynamic tasks, the CLEAN and CLOBBER lists, rules, pathmapping, library tasks, and finally, incorporating your own Rake tasks into your Rails projects. The final presentation of the conference discussed production tips and tricks by Duncan. He attempted to answer the most common questions regarding going into production such as:
- How much hardware do I really need? Two to four machines for redundancy: primary and backup web servers and primary and backup database servers.
- How many Mongrel instances should I fire up? Two to four instances on a dual core machine, the rule of thumb is # of CPU’s * 2.
- What should I do with my logfiles? Logfiles are gold for root cause analysis, you should aggregate logs onto a single machine, you may wish to use something like the FiveRuns solution or syslog over the network and ensure that you always filter out sensitive data.
- What kind of load balancer should I use? You could try round-robin DNS, but Pound/Pen software load balancers are quite good. A hardware load balancer is fine if you have the money but is overkill.
- Should I use Amazon’s EC2? Consider it, but keep an eye on it.
- How often should I deploy? Often.
- Should I deploy into production with edge Rails? You can, there are many others that do it, but be prepared for issues. Unless you’re really comfortable with it, just use Rails 1.2 for now.
- How do I test with real-world data? Get your production data back to the development team.
Overall, I thought this small regional conference was defintely worth it. Especially since I spent my own money to attend (unfortunely I don’t get to work on Rails at my day job). The single track was great for keeping everyone on the same page and fostering great inter-session discussion. If the Rails Edge is headed your way, I would definitely encourage you to attend.
The Rails Edge Day 2
The second day of the conference was even better than the first, in my opinion. There were several more talks which I was eager to hear. Here’s an overview of the second day’s presentations:
- Creating Rails Plugins by Chad Fowler and Bruce Williams
- The Presenter Pattern by Marcel Molina, Jr.
- The Deployment Golden Path by James Duncan Davidson
- Testing Rails Apps by Stu Halloway
- Red, Green, Refactor by Jim Weirich
- Building View Frameworks by Bruce Williams
- Lightning Talks
Read on for my notes. First up were Chad and Bruce who went through Creating Rails Plugins. Never having created a Rails plugin before, I was very interested in the process. They started by providing an overview of the plugin script and then the generate plugin script. Next they showed how you can provide your own controllers (in the lib subdir) and views (in the views/‘plugin name’ subdir), rake tasks (in the tasks subdir), models (right at the top-level of your plugin) and your own generators (in the generators/‘plugin name’ subdir). The remainder of the talk walked through the creation of their acts_as_ratable plugin. Marcel followed that with his talk on the Presenter Pattern. He was quick to point out that this is not a design pattern in the style of the Gang-of-Four book (especially since previous presenters had made derogatory comments about design patterns and their utility). The presenter pattern is basically a way to organize a chunk of view code. He started off with a discussion of the problems with helper modules, how they become a dumping ground for methods (one suggestion was to break-up your helpers into smaller modules organized around specific functionality and then include those in your helper). A comparison was made to the ‘method object’ in Kent Beck’s Smalltalk Best Practice Patterns (linked at bottom of this post). To finish, Marcel gave a brief demo of this but it’s basically vaporware at this point and didn’t have a date for when it would be released. JDD was up next with his talk on Deployment. He stressed that it was important to start deploying your app as soon as possible in the development cycle (he suggested that you do it at the same time you set up your Subversion repository). This is necessary to find all of the “interesting” deployment problems up front, so you can get into the deployment rhythm and so that you can show others what you’re working on for feedback. You just need a machine that works well enough, he suggested a Mac mini, but some folks in the audience suggested a virtual machine on the same box — Duncan said that while that might work he prefers having another machine to deploy to. The only deployment solution that he recommends right now is Mongrel fronted by Apache, Lighty, Pound, Pen or a hardware load balancer. Then he went on to describe what he calls ‘the golden path’ using Capistrano, Subversion and Unix machines. At the end he gave a live demo deploying his app to an Amazon EC2 machine. After lunch, Stu presented on Testing Rails Apps. Perhaps I’m insecure about my testing and test coverage (though Mike Clark’s rcov Rake task certainly provides peace-of-mind), but I always find myself very interested in the testing methodologies of others. Stu started off by discussion the reasons to write tests (tight feedback loop, easy refactoring, early warning, cheap measure of success and that it makes bad code painful). He went through testing models (ensure your tests are self-documenting, test everything in sight and then evolve your own style), fixtures (YAML, always use valid data, use ERB for dynamic data), controllers (check out the scaffold: it tests responses, redirects, model updates and uses restful verbs), managing your tests (group and run using rake, manage your fixtures with rake, put your common tasks in test_helper.rb). He then went through an example of testing a space station w/o having access to a rocket, so he used flexmock to mock one up, like this:
~~~~ {lang=“ruby”} def test_refuel_with_mock_recorder rocket = flexmock(“rocket”) rocket.should_expect do |rec|
rec.dock.ordered
rec.attach_fuel_hose.ordered
rec.add_fuel(Integer).returns(50).ordered
rec.detach_fuel_hose.ordered
rec.undock.ordered
end @station.refuel(rocket, 50) assert_equal 950, @station.fuel end ~~~~
He then went on to recommend rcov and said that you should have 100% of your code covered. He ran out of time before he could cover the Cerberus continuous integration tool. Jim Weirich sat down for a live coding presentation entitled, “Red, Green, Refactor” in which he demonstrated test/behavior driven development. The steps were:
- Write a new test and watch it fail
- Write just enough code for the test to pass
- remove duplication, clean up, etc. and repeat
He spoke in terms of dividing your perspective into two parts a Dr. Jekyll who writes a test that forces you to write the code you need and a Mr. Hyde who deliberately writes the minimal amount of code that passes the tests. His demo seemed pedantic at first, but because you have this extremely lazy Mr. Hyde you really have to think about your tests and write them such that you force the implementation to be correct. Bruce Williams spoke about Building View Frameworks and made the example code available at his site. I was really looking forward to this talk and Bruce didn’t disappoint. He started off discussion the traditional methods of DRYing up your views: Helpers, Block Helpers and Partials then he went into REST DRYing with the simply_helpful plugin. Next he went into some new territory for me, DRY interactions by creating a controller DSL, controller plugins and “big frameworks” as he called them. He gave examples of this from his work at Naviance: folder_for (which created a tabbed view for the different folders), paginated_index which was a controller DSL, roster_for (which was very similar to paginated_index) and a calendar which was a controller plugin. Bruce suggested using plugins and writing your own and contributing them back to the community as well as testing your views with Watir or Selenium. Following the presentations, were the lightning talks. I was unable to stay for all of them but some of the more notable ones were: Aaron from Revolution Health demo’ed their huge web app (or more accurately collection of integrated web apps) and spoke about their PluGems solution which has been document on their blog. It looks like they’re really doing some interesting work and having a lot of fun doing it (plus I’m jealous of their development environment — I wish my employer gave each of us MacBook Pros instead of Lenovo ThinkPads); Next Jared Richardon, author of Ship It, spoke about his consulting work on a new search engine site called ChaCha and how they scaled Rails by removing ActiveRecord in production. They use Rails as normal during development and then extract out all of the SQL queries and tune them for production; Mark Cornick gave a quick run-down on the service manager framework in Solaris and how he used it to launch his Rails app when the machine boots. Since we use a fair amount of Solaris at work and I’m not that familiar with this feature, I found his talk quite enlightening. The presenters have really been pimping Kent Beck’s book, Smalltalk Best Practice Patterns — so of course, I picked up a copy.
The Rails Edge Day 1
Recently, I attended The Rails Edge conference run by The Pragmatic Studio. It was a single track event with some of the best and brightest folks in the Rails and Ruby community. The speaker line-up was as follows:
- Dave Thomas
- Mike Clark
- James Duncan Davidson
- Chad Fowler
- Justin Gehtland
- Stuart Halloway
- Marcel Molina, Jr.
- Jim Weirich
- Bruce Williams
Read on for a description of the first day’s sessions. After a brief welcome from Mike Clark, Dave Thomas launched the conference with his first session entitled “Metaprogramming Ruby: Extending Ruby for Fun and Profit.” He showed how classes were open by re-opening the String class and adding a method to encrypt the contents of the string and then he reimplemented the Rails modifications to Fixnum (so that 3.days.from_now works). He showed how code could be executed in the context of a class as that class was loaded (i.e. we could conditionally include/exclude methods in the class). Adding macros to Rails controllers was achieved using the Module.included method to detect when the Module was included in a controller and then perform some actions on that controller (such as adding methods to it). Next the power of eval and instance_eval was displayed—though he cautioned that eval’ing user input could be very dangerous. Finally, he showed how define_method could be used to create new methods on a controller like so:
~~~~ {lang=“ruby”} class ApplicationController < ActionController::Base def self.search_action_for(table_name)
model = table_name.to_s.classify.constantize
define_method("search_for_#{table_name}") do
@title = "Your #{Inflector.humanize(table_name)}"
@results = model.find(:all, :conditions => ["name like ?", "%#{params[:term]}%"])
render :template => '/shared/search_results'
end
end end ~~~~
and you would use it like this:
{lang=“ruby”}
class UsersController < ApplicationController
search_action_for :users
end
Following a short break, Mike Clark gave an overview of what’s new in Rails 1.2. Mike started off by listing the various virtual machines that are under development for Ruby, such as YARV, JRuby, Rubinius, RubyCLR, Cardinal, and smalltalk.rb. Then he went on to discuss migrations, plugins, rich models, parameter filtering, deprecations, integration test (a testing DSL), running Rails in headless mode (via the console), form_for, RJS, serialization, respond_to, named routes, CRUD/REST, syndication, ActiveResource, Mongrel, Capistrano, full-featured scaffold, Amazon S3, and Rinda/DRB. Next Stu gave his talk on Ruby Idioms for Rails Programmers. He covered the explicit API (which was Java code) and the implict API of today and how the implict API is implemented as many small modules included into big classes. Personalized Object Models (POM) were next, this is done by augmenting other people’s code, implementing DSLs with method-on-demand, using method_missing sparingly, and being domain specific. His presentation is available at CodeCite. Chad was up next with his talk on The Meaning of CRUD. This presentation went into the meaning of CRUD (Create, Read, Update, Destroy), RESTful routes and the SimplyHelpful plugin. This topic has been discussed at length elsewhere so I won’t go into the details. But Chad is always a great speaker and I enjoyed his presentation immensely. Following lunch there was a switch to the schedule as Jim Weirich hadn’t arrived yet. So Justin stepped up and gave his talk on Rails and Ajax. This presentation is also available online at CodeCite. Justin started off with a discussion of the Prototype JavaScript library with some simple examples, then launched into the various effects possible with Script.aculo.us. To wrap up, RJS was described along with JSON. This led nicely into Marcel’s talk on Reusing RJS. He started off by showing some duplicated RJS code into two actions within the same controller. For the first pass he tried extracting out a new private method with the duplicate code, but unfortunately it didn’t work since it was in the wrong scope. So he extracted it out to a helper and ensured that it could be passed the page object. This worked, but calling the new method looked really ugly (Marcel called this Pythonic). His next approach was to monkey patch JavaScriptGenerator right in Rails — invoking the new methods looked great, but he decided it wasn’t worth it to abuse method_missing plus it became a maintenance headache. So Marcel went back to the origins of RJS and explained some of the design choices that he and Sam made and reminded us that << just adds raw JavaScript to the stream. So he decided just to wrap update_page in the helper and then reuse the code with << like so:
~~~~ {lang=“ruby”} module ArticlesHelper def replace_article(article)
update_page do |page|
page[article].replace :partial => article
page.replace_html :controls, :partial => 'shared/controls'
end
end ~~~~
and then he reused it:
~~~~ {lang=“ruby”} def show
render :update do |page|
page << replace_article(@article)
end
end def update
@article.update_attributes(params[:article])
render :update do |page|
page << replace_article(@article)
page.visual_effect :highlight, dom_id(@article)
end
end ~~~~
The great thing about this is that you can also reuse that JavaScript in your views as well:
{lang=“html”}
Edit Article
<% article_form(article) do |form| %>
<%= render :partial => ‘articles/form’, : object => form %>
<%= submit_tag ‘Save changes’ %> or
<%= link_to_function ‘Cancel’, replace_article(article) %>
<% end %>
After a short break, several conference attendees came up and demo’ed their apps. Some of the presenters were: Erik Hatcher who presented on his Solr.rb project (the acts_as_solr.rb plugin) and his work at UVA categorizing literature; Ryan Garver spoke about the AWS Console which makes it really easy to setup your server on Amazon Web Services EC2; Ken Collins spoke about Homemarks, simple project-based bookmarking, which he is open sourcing; Finally, someone from the FiveRuns team demo’ed their hosted systems management solution. While it certainly looks nice, I know my employer would never use it as it requires installing their software on your systems so it can report back to them. After dinner, Dave Thomas gave the opening keynote, entitled Fear of Flying. It was very good and I believe it was the same as the EuroRailsConf keynote that he gave, which is available online. Overall, the first day of The Rails Edge went very well and got me re-energized to work on my projects with several new ideas and a fresh perspective. I don’t think you can put a price on that.