I’ve had to rely at times on silence and on talking quick / Defending myself with nothing but my walking stick. —Buck65
Here are nine easy tips that will help you communicate better at your next conference.
Figure A Can you read me now?
Dan Grigsby’s presentation at RubyFringe was an intentional example of this. All the titles were at the top, with humorous stock photos below.
Keep it in the top third, if possible.
Figure B Takahashi-san frowns on your tiny fonts
Giles Bowkett is such an entertaining speaker that people once skipped the first 20 minutes of lunch to hear the remainder of his presentation at RubyFringe (which involved more than 400 slides).
He also used only the typefaces included with Mac OS X, including Futura Condensed Medium and Condensed ExtraBold, which work really well in bright colors on black. So even if you don’t choose to buy a single typeface, you can assemble a great-looking presentation.
Figure C Working well and looking good
It’s easy with either:
Copy as RTF – A TextMate plugin. You can paste the syntax-highlighted text and even edit it afterward in Keynote.
pygments – A command-line syntax highlighter written in Python. It’s used at GitHub to emit HTML but can also emit RTF from any source file. The resulting rich text can be pasted into Keynote.
pygmentize -f rtf -o out.rtf code.rb
Figure D Stay on target
Choosing just the right transition can soak up a lot of time and adds absolutely nothing to the content that people remember afterward.
Dan Grigsby also noted that transitions and multi-step builds make it difficult to go back and forth in the presentation since you have to wait for the transition to finish. Unless…
Figure E An unforced fumble while trying to backtrack
Useful Keynote shortcuts (while the presentation is playing).
| Key | Description |
| / | Show a list of keyboard shortcuts. |
| H | Pause the presentation and go to the last used application (useful for demos). Command-tab back to Keynote to resume the presentation. |
| = or - | Show a thumbnail menu that can be used to jump forward or backward to a specific slide. Use the arrow keys to select and the enter key to jump. |
| B | Pause and show a black screen. |
Figure F The conference wifi WILL fail when you need it most
I love live coding but often it goes awry, creating an awkward situation for both the presenter and the audience.
Give yourself some insurance and either record a short screencast that you can narrate during the presentation, or take screenshots that you can refer to.
Extra Credit!
Figure G Is grey a color?
If you’re speaking at a conference, you’re probably doing it to promote yourself, your projects, or your business. Make it stick in people’s minds by distinguishing yourself with a color scheme and a typeface that communicate the attitude you want to be remembered for.
Choose a color scheme and use it for all your presentations. Ideally, it would be the color scheme of your company or personal blog. If you’ve paid for a corporate identity, use it!
Resources
Figure H An easy way to stand out
Again, buy a typeface and use it on your blog and in your presentations.
They’re not as expensive as you might think! You can get a single font for $20.
Here are some nice condensed ones as mentioned above:
Or try these shops:
Figure I Free as in not chained to the spacebar
I saved my favorite for the end…
A presentation remote gives you the freedom to step away from the lectern and talk directly to the audience. The remote that comes with Mac laptops doesn’t count! It only works if you have a direct line of sight to the infrared receiver on the front edge of the laptop.
A radio frequency transmitter works much better. The Kensington Presentation Remote can be bought for about $40. It works out of the box without the need to install any drivers, and it’s less distracting than phone-based options.
See you in Berlin!I’ll be in Berlin at RailsConf starting this Sunday. Find me and get a free PeepCode t-shirt!
PeepCode Screencasts – Learn Ruby on Rails and Javascript! Hour-long screencasts for $9.Rails 2.2 is going to make it much, much easier to do internationalized sites. Check out Clemens Kofler’s sample app running live or peruse his code. Thread safety? Internationalization? What stock objections to Rails will we have left?!
That would be cool if we could soon start coding in Flex for the iPhone.
Enjoy!
Daniel.SQLite3-Ruby version 1.2.3 is now available. It is a maintenance release, fixing just a few things:
To install or upgrade:
| gem install sqlite3-ruby |
Thanks!
Juggernaut is a combination of a small Ruby server, a Flash bridge, and a plugin that makes it easy to do server-side push systems in Rails. I played with this idea with Rich Killmer a few years ago and even made a small demo system to present at a conference, but never made it to the finish line of something releasable. So it’s fantastic to see that the guys behind Juggernaut did.
Episode 044. We've decided to stop living the lie and are just letting OS X system speech say all names for us from now on.
The Rails Envy podcast is brought to you this week by NewRelic. NewRelic provides RPM which is a plugin for rails that allows you to monitor and quickly diagnose problems with your Rails application in real time. Check them out at NewRelic.com.
Call Us! You can reach the podcast voicemail line at 407 409-8440.
Subscribe via iTunes - iTunes only link.
Download the podcast ~16:00 mins MP3.
Subscribe to feed via RSS by copying the link to your RSS Reader
Here is a security announcement for the REXML library (links by me) in the Ruby news:
There is a DoS vulnerability in the REXML library used by Rails to parse incoming XML requests. A so-called "XML entity explosion" attack technique can be used for remotely bringing down (disabling) any application which parses user-provided XML. Most Rails applications will be vulnerable to this attack.
Impact
An attacker can cause a denial of service by causing REXML to parse a document containing recursively nested entities such as:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE member [
<!ENTITY a "&b;&b;&b;&b;&b;&b;&b;&b;&b;&b;">
<!ENTITY b "&c;&c;&c;&c;&c;&c;&c;&c;&c;&c;">
<!ENTITY c "&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;">
<!ENTITY d "&e;&e;&e;&e;&e;&e;&e;&e;&e;&e;">
<!ENTITY e "&f;&f;&f;&f;&f;&f;&f;&f;&f;&f;">
<!ENTITY f "&g;&g;&g;&g;&g;&g;&g;&g;&g;&g;">
<!ENTITY g "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx">
]>
<member>
&a;
</member>
M. Koziarski provides a Rails-specific solution to the problem:
The announcement contains details describing a monkeypatch which can
be applied to prevent the risk. These instructions are reproduced
below with more rails specific information:
** Versions 2.0.2 and earlier
# Copy the fix file into RAILS_ROOT/lib
# Require the file from environment.rb require 'rexml-expansion-fix'
** Versions 2.1.0 and edge
Copy the fix file into RAILS_ROOT/config/initializers, it will berequired automatically.
There is also a gem available which includes the fix file:
gem install rexml-expansion-fix
Once that command has completed add the following line to the bottom
of your environment.rb file:
require 'rexml-expansion-fix'
Bookmark to


This is Part Three of a series of articles on Java.next. In Part Three, I will explore how the Java.next languages (JRuby, Groovy, Clojure, and Scala) support dispatch.
For my purposes here, dispatch is a broad term covering various methods of dynamically choosing behavior: single dispatch, switch/case, pattern matching and multiple dispatch. These concepts are not generally grouped together, but they should be. They are used to solve similar problems, albeit in very different ways.
Single dispatchLet me start with single dispatch. In Java, methods can be selected based on the type of the object they are invoked on. All the Java.next languages support single dispatch, too:
; clojure (fly vehicle speed) // Java, Groovy, or Scala vehicle.fly(speed) # ruby vehicle.fly speedIn all of these languages, the actual implementation of fly can vary depending on the run-time type of vehicle. (Clojure also supports multiple dispatch, where the implementation can vary based on the type of speed -- more on that later.)
Better switchingAnother way to dynamically choose behavior is with a switch statement. Java has a simple switch statement, based on its historical kinship with C and C++. Switch statements have gotten a bad name, so much so that programmers are encouraged to replace them with polymorphism where possible.
This anti-switching bias is based on the limited kind of switching allowed in languages such as Java. In Java.next, there is a different story. The Java.next languages all have powerful switching capabilities, allowing you to switch on any criteria you like. As an example, consider a method that calculates a letter grade, taking input that is either a number or letter grade.
Ruby's case statementHere is letter_grade in Ruby:
def letter_grade(val) case val when 90..100: 'A' when 80...90: 'B' when 70...80: 'C' when 60...70: 'D' when 0...60: 'F' when /[ABCDF]/i: val.upcase else raise "Not a valid grade: #{val}" end endIn Ruby, the switch/case variant is called case. The Ruby when clause can take arbitrary expressions. Above you see ranges and regular expressions side-by-side in the same case expression. In general, the when clause expects objects that implement a well-known threequals method, ===. Many Ruby objects have sensible === implementations: ranges match numbers in the range, regular expressions match strings containing the regular expression, classes match instances of the class, etc. But any object can implement ===, so you can implement arbitrarily complex dispatch with Ruby case.
Groovy's switch statementHere is letterGrade in Groovy:
def letterGrade(val) { switch(val) { case 90..100: return 'A' case 80..<89: return 'B' case 70..<79: return 'C' case 60..<69: return 'D' case 0..<59: return 'F' case ~"[ABCDFabcdf]": return val.toUpperCase() default: throw new IllegalArgumentException("Invalid grade: $val") } }In Groovy, the switch/case variant is called switch. If you compare this code with JRuby, you will see minor syntactic differences:
The general ideas are the same. Both JRuby and Groovy provide far more powerful and general approaches than Java's switch.
Clojure's cond functionIn clojure, as in many Lisps, you can switch on arbitrary functions using cond. One possible approach to letter-grade would be:
(defn letter-grade [grade] (cond (in grade 90 100) "A" (in grade 80 90) "B" (in grade 70 80) "C" (in grade 60 70) "D" (in grade 0 60) "F" (re-find #"[ABCDFabcdf]" grade) (.toUpperCase grade)))In Clojure, regular expressions look like #"...". The in function above is not part of Clojure. I wrote the code the way I wanted it to read, and then wrote this function:
(defn in [grade low high] (and (number? grade) (<= low grade high)))In Clojure, I probably wouldn't use a regular expression for the letter-matching step, but I wrote the example that way for symmetry with the others.
Clojure's cond is just the tip of the iceberg. Clojure-contrib includes a set of macros for other variants of switch/case, and later in this article I will demonstrate Clojure's multiple dispatch.
Scala's pattern matchingScala's pattern matching is a powerful generalization of the switch/case idiom in many programming languages. Scala provides out of the box support for pattern matching on
With pattern matching, implementing letterGrade is a snap:
val VALID_GRADES = Set("A", "B", "C", "D", "F") def letterGrade(value: Any) : String = value match { case x:Int if (90 to 100).contains(x) => "A" case x:Int if (80 to 90).contains(x) => "B" case x:Int if (70 to 80).contains(x) => "C" case x:Int if (60 to 70).contains(x) => "D" case x:Int if (0 to 60).contains(x) => "F" case x:String if VALID_GRADES(x.toUpperCase) => x.toUpperCase() }In this implementation, numeric grades and letter grades are both matched first by type. Then, case expressions also allow a guard that limits possible matches to some condition. So, for example, the first case above matches only if value is an Int (type match) and between 90 and 100 (the guard).
Scala's guard expressions are cool, but the combination of type+guard does not exactly parallel the other implementations of letterGrade, which rely on arbitrary predicates in case expressions. Scala can do this too: Scala extractors allow you to create arbitrary patterns. Here is one approach to letterGrade using extractors:
def letterGrade(value: Any) : String = value match { case NumericA(value) => "A" case NumericB(value) => "B" case NumericC(value) => "C" case NumericD(value) => "D" case NumericF(value) => "F" case LetterGrade(value) => value }Behind the scenes, NumericA and friends are objects that implement an unapply method to determine if and how a value should match the pattern.
A more complex exampleScala's pattern matching is much more general than the letter grade example shows. To see this, check out Daniel Spiewak's series introducing Scala for Java programmers. In Part 4, he gives an example of pattern-matching working in conjunction with case classes, which I will explore below.
Scala's case classesCase classes offer several interesting properties when compared to regular classes:
These properties are so useful that Scala programmers use case classes for all kinds of things. But their true purpose is revealed in conjunction with patterns: Case classes work directly with pattern matching, without having to write an extractor as in the previous example.
class Color(val red:Int, val green:Int, val blue:Int) case class Red(r:Int) extends Color(r, 0, 0) case class Green(g:Int) extends Color(0, g, 0) case class Blue(b:Int) extends Color(0, 0, b) def printColor(c:Color) = c match { case Red(v) => println("Red: " + v) case Green(v) => println("Green: " + v) case Blue(v) => println("Blue: " + v) case col:Color => { print("R: " + col.red + ", ") print("G: " + col.green + ", ") println("B: " + col.blue) } case null => println("Invalid color") }The printColor method pattern-matches Red, Green, and Blue to provide special behavior for basic colors. Because these are case classes we can capture the actual color value v. All other colors fall through to a general Color, which prints a more generic message.
Clojure's defmultiScala's pattern-matching is a signature feature of the language. How do the other Java.next languages compare? To implement printColor in Clojure, I begin by defining a structure to capture a color:
(defstruct color :red :green :blue)Where the Scala example defined basic colors with case classes, in Clojure I can use functions:
(defn red [v] (struct color v 0 0)) (defn green [v] (struct color 0 v 0)) (defn blue [v] (struct color 0 0 v))Now for the fun part. I will define a multimethod named color-string, which dispatches based on which basic colors are present in the color struct.
(defmulti color-string basic-colors-in)basic-colors-in is a dispatch function that reports which colors have nonzero values:
(defn basic-colors-in [color] (for [[k v] color :when (not= v 0)] k))Now I can define multiple implementations of color-string. The basic syntax is
(defmethod method-name dispatch-value function-body)So for the three pure colors, I can define color-string as
(defmethod color-string [:red] [color] (str "Red: " (:red color))) (defmethod color-string [:green] [color] (str "Green: " (:green color))) (defmethod color-string [:blue] [color] (str "Blue: " (:blue color)))I can also provide a catch-all implementation by specifying a dispatch-value of :default:
(defmethod color-string :default [color] (str "Red: " (:red color) ", Green: " (:green color) ", Blue: " (:blue color)))Multimethods are more powerful than polymorphic single dispatch in two important ways:
Like Scala's pattern matching, Clojure's defmulti provides an extremely powerful and extensible dispatch mechanism.
Accidently blueBoth the Scala and Clojure code above take special action for colors that are declared to be pure blue:
// Scala scala> printColor(Blue(10)) Blue: 10 ; Clojure user=> (color-string (blue 10)) "Blue: 10"What about colors that are not declared as blue, but are, nevertheless, purely blue. These colors are accidentally blue:
// different result for accidental blues scala> printColor(new Color(0, 0, 10)) R: 0, G: 0, B: 10 ; all blues equal user=> (color-string (struct color 0 0 10)) "Blue: 10"The Scala example was written to dispatch based on type, so it treats accidentally blue colors different from "real" Blues. The Clojure example, on the other hand, dispatches based on the actual color values, so all solid blues are treated the same, no matter how they are created.
Of course, nothing stops me from "fixing" the Scala example, e.g. by dispatching on something other than type:
case class Color(val red:Int, val green:Int, val blue:Int) object ColorDemo { def zeroes(values: Int*) = values.forall(item => item == 0) def colorString(c:Color) = c match { case Color(r,g,b) if zeroes(g,b) => "Red: " + r case Color(r,g,b) if zeroes(r,b) => "Green: " + g case Color(r,g,b) if zeroes(r,g) => "Blue: " + b case col:Color => { "R: " + col.red + ", " + "G: " + col.green + ", " + "B: " + col.blue } case null => "Invalid color" } }Or, I could "break" the Clojure example by adding a type tag, and dispatching on that instead. Rich Hickey posted this example on the Clojure mailing list:
(defstruct color :red :green :blue) (defn color-class [name r g b] (assoc (struct color r g b) :tag name)) (defn red [v] (color-class :red v 0 0)) (defn green [v] (color-class :green 0 v 0)) (defn blue [v] (color-class :blue 0 0 v)) (defmulti color-string :tag) (defmethod color-string :red [c] (str "Red: " (:red c))) (defmethod color-string :green [c] (str "Green: " (:green c))) (defmethod color-string :blue [c] (str "Blue: " (:blue c))) (defmethod color-string :default [{:keys [red green blue]}] (str "Color, R: " red ", G: " green ", B: " blue))This version now works like the original Scala version, treating "accidental" blue differently from things marked with a :tag of :blue.
Note that multimethods are open. I can add new colors later without having to modify the existing code:
(defn orange [r g] (color-class :orange r g 0)) (defmethod color-string :orange [{:keys [red green]}] (str "Orange, R: " red ", G: " green)) Dynamic Scala?If you are a dynamic language programmer fearing the tyranny of the Scala compiler, pattern matching is a cause for rejoicing. With pattern matching, you can bypass static typing and get the flexibility of much more dynamic dispatch. Consider: Scala's pattern matching can be used to dispatch on arbitrary predicates. These predicates are not limited to type relationships known at compile time, so a Scala program that uses pattern matching as the cornerstone of its dispatch strategy can be as dynamic as an extremely dynamic Ruby program. Put another way: Scala's catch-all match default (_) is the moral equivalent of Ruby's method_missing.
ConclusionsDispatch takes many forms. Single dispatch, switch statements, pattern matching, and multiple dispatch all meet similar needs: Selecting runtime behavior in response to varying runtime conditions.
Flexible dispatch is a key element of Java.next. All of the Java.next languages support dispatch strategies that are far more flexible than Java's single dispatch. These strategies are not perfectly interchangeable, but have a great degree of overlap. For example, Clojure's multimethods and Scala's pattern matching look quite different on the surface but can be used to solve similar problems.
Dispatch can be based on criteria more dynamic than the type system, even in Scala.
NotesAre you currently using Capistrano 1.4.1? If so, drop everything (I mean it, do this RIGHT NOW) and install Capistrano 1.4.2.
Why, you ask?
Capistrano 1.4.1 will work just fine, right up until you decide you want to experiment with Capistrano 2. When you do that, Cap 2.3+ will install net-ssh 2.x, which kills Capistrano 1.4.1 in all kinds of really obscure ways.
The good news is that Cap 1.4.2 is completely compatible with Cap 1.4.1. It adds no new features. The only “bug” it fixes is that if you ever install net-ssh 2.x, Cap 1.4.2 will still happily continue to work.
Ultimately, an upgrade to Cap 2 is recommended, but I understand it’s not feasible for everyone. So, if you’re one of those who can’t go cap2 yet, please please please PLEASE PLEASE FOR THE LOVE OF ALL THAT IS HOLY upgrade to Cap 1.4.2. It’ll make your life easier, and it’ll make my life easier (because I won’t have to keep troubleshooting the same issues over and over). Thanks!

As you may already be aware, Jason and I have been working on our own paid Screencasting website, called Envycasts.
We’re releasing the website into the wild today, with our first envycast Advanced ActiveRecord. Definitely check out the website and view the flash preview of this first screencast.
How are we different then the other screencasters?
Well, the biggest difference is that we built a green screen. So basically you see us in front of the code, instead of just our voices. This makes for a more engaging, and I think entertaining experience, but I’ll let you be the judge.

Both Jason and I owe big props to the other big screencasters in the Ruby / Rails world, Railscasts, Peepcode, Pragmatic Screencasts, the Learning Rails Podcast/Screencast, amongst others. If it wasn’t for these guys, I doubt we’d have done a website like Envycasts.
If you’ve enjoyed the content we’ve put out here on Rails Envy, even if you don’t buy the screencast, maybe consider doing us a favor and help us promote the website (feel free to steal the images here). We love producing media for the community, and admittedly it isn’t as profitable as just coding, so hopefully with your help we can keep on doing what we do.
Referring to the late 1800's:
The principles of engineering may have brutally contradicted those of architecture, but a vocal minority of nineteenth-century architects nevertheless perceived that the engineers were capable of providing them with a critical key to their salvation—for what these men had, and they so sorely lacked, was certainty. The engineers had landed on an apparently impregnable method of evaluating the wisdom of a design: they felt confidently able to declare that a structure was correct and honest in so far as it performed its mechanical functions efficiently; and false and immoral in so far as it was burdened with non-supporting pillars, decorative statues, frescos or carvings.
Exchanging discussions of beauty for considerations of function promised to move architecture away from a morass of perplexing, insoluble disputes about aesthetics towards an uncontentious pursuit of technological truth, ensuring that it might be as peculiar to argue about the appearance of a building as it would be to argue about the answer to a simple algebraic equation.
—Alain de Botton, The Architecture of Happiness, p51 (referring to changes in the late 1800s)
Needless to say, the promise was a false one: for most things, there is no pure level of function. Especially not something as intimately related to our daily, messy lives like a home.
And referring to, well, right now:
If one gets past the patina, the quaintly burnished woodwork, the problem is that Steampunk is far too enamored of the look, the surface skin of an derivatively small chunk of the Victorian era filtered through Terry Gilliam’s Brazil and Jules Verne, whose illustrated “scientific romances” seem to have formed the ur-aesthetic for Steampunk.
—Randy Nakamura, "Steampunk'd, Or Humbug by Design", Design Observer (July 2, 2008)
Nothing has changed.
Of almost any building, we ask not only that it do a certain thing but that it look a certain way, that it contribute to a given mood: of religiosity or scholarship, rusticity or modernity, commerce or domesticity. We may require it to generate a feeling of reassurance or of excitement, of harmony or of containment. We may hope that it will connect us to the past or stand as a symbol of the future, and we would complain, no less than we would about a malfunctioning bathroom, if this second, aesthetic, expressive level of function were left unattended.
—Alain de Botton, The Architecture of Happiness, p62
When you read a unilateral polemic, whether by Le Corbusier or some punk on Design Observer, beware.
Typically such frothing attempts to hide some deficiency in the author.
Look for the hidden chip on the shoulder. The author may be suffering—knowingly or unknowingly—from an inability to understand or succeed in a certain aspect of work or life (e.g. aesthetics, or personal relationships), the value of which becomes the target of his attack. She may be afraid of uncertainty, and thus promote formulas. Or maybe he just knows that people vote, with their attention and their money, for the comfort of exactitude—regardless of whether the exactitude is scientific or even useful.
Phusion has recently released a library for robust daemon management. Check it out. Description and tutorials are available on that page.
I just released cinabox. It is intended to be The Simplest Thing That Could Possibly Work to set up a Continuous Integration (CI) server, using cruisecontrolrb (CCRB).
Watch the Screencast!
In addition to being a (hopefully) useful tool to help people easily set up CI systems for various platforms and languages, it is also an experiment in simplicity and minimalism:
I'm pretty pleased with how this turned out. I hope it will lower the barrier for people to start trying out Continuous Integration, as well as provoke some thought about simplicity and minimalism. I've tried it out on a few flavors of Ubuntu VMs and my personal box, and it works for me. Please let me know what you think, and feel free to offer any suggestions for improvement.
The ruby-security team have published an advisory about a DoS bug affecting REXML users. Most rails applications will be affected by this vulnerability and you’re strongly advised to take the mitigating steps recommended in the advisory.
The announcement contains details describing the monkeypatch solution, but to summarise:
Versions 2.0.2 and earlierCopy the fix file into RAILS_ROOT/config/initializers, it will be required automatically.
The fix will be made available as a gem in the next 24 hours to aid distribution, this post will be updated with revised upgrade instructions at that time. If you wish to access the gem early you can build it for yourself from the source. After installing the gem you should require it from environment.rb. The fix file and the gem are identical.
Figure A Back yard
For the third year in a row, it’s the Seattle.RBBQ at Geoff’s house in Seattle!
Shopify got profiled last week in Practical E-Commerce as cart of the week . According to them they found 300 different Shopping cart packages, I know our market was big but that’s pretty insane.
Anyways, their Cart of the Week feature pits one Cart against another by asking a competitor to comment on the software, CNN style. In our case they asked Rick Wilson of Miva Merchant to comment on Shopify. Here is what he dislikes:
The obvious weaknesses I saw were the limits on what they called ‘enterprise’ level offering of only 10,000 SKUs. The other major weakness is the product is built using Ruby On Rails. Ruby On Rails seems to be a development environment with a lot of future possibilities, but as a general rule you don’t want your revenue-generating product to be based on cutting edge technology. There’s a lot of unforeseeable pitfalls in that area.
(emphasis mine).
So to deconstruct the first part of this argument let me just say that we have millions of products in Shopify right now and it’s a pure business decision to limit SKUs to 10k and has nothing to do with the software. There are millions of products in the database. In fact i’d buy Rick lunch if Shopify isn’t right now handling twice the traffic any given Miva Merchant store has ever sustained.
What’s left is the advice that you shouldn’t run a revenue-generating web site based on cutting edge technology. I don’t think I have to point out how ridiculous that statement is. First of all I presume that perl was pretty cutting edge ( definitely more than ruby is today ) in 1998 when Miva was written and also we are talking about bloody Miva Merchant here, the e-commerce system that runs on a proprietary closed source database that is known for corruption issues after several hundred products. Not only that, it seems to be one of their main sources of revenue: For 129$ setup + 20$ a month you can get some support and basic database recovery. Unfortunately:
** Due to the nature of database problems not all database corruption can be covered under this package
Isn’t it nice that you never have to worry about such tactics with hosted systems and SaaS packages like Shopify?
Episode 043. What's an Australian Rails developer's worst nightmare? Listen to the podcast all the way to the end to find out.
The Rails Envy podcast is brought to you this week by NewRelic. NewRelic provides RPM which is a plugin for rails that allows you to monitor and quickly diagnose problems with your Rails application in real time. Check them out at NewRelic.com.
Call Us! You can reach the podcast voicemail line at 407 409-8440.
Subscribe via iTunes - iTunes only link.
Download the podcast ~16:00 mins MP3.
Subscribe to feed via RSS by copying the link to your RSS Reader
Yesterday I challenged people to look at sandbox.phusion.nl’s HTTP headers and check whether they notice anything weird. The HTTP response header of the front page is:
HTTP/1.1 200 OK
Server: nginx/0.6.32
…
X-Powered-By: Phusion Passenger (mod_rails/mod_rack) 2.1.0
X-Runtime: 0.00173
…
Wow, I got a lot more responses than I expected.
Sorry guys, there’s a reason why I didn’t post this on the Phusion blog, but on my personal blog instead.
Chu Yeow said:
Wow Passenger on Nginx (I think that’s it - doubt you’d run Nginx on top of Apache+Passenger ;)).
Well actually… we are running Nginx on top of Apache+Passenger.
The first reaction of many people is probably “WTF, are you out of your mind? Why would you do such a thing?” Let me explain a little bit about our server.
Initial motivation: securityThis server is shared by many users, including a few which we don’t fully trust. It not only runs Rails applications but also a bunch of PHP applications, and in the not too distant past some mod_perl applications. In the usual Apache setup, all those PHP/mod_perl applications will run under the same user and have the same rights. This means that there is no security between different people’s web applications: Jane’s PHP script can read Joe’s forum database password file. Not so nice.

Now, how do we solve this? These days, server virtualization is the latest hype: just give Joe and Joe different virtual machines! But virtualization wastes a lot of memory. Joe and Jane’s websites are really low-traffic compared to mine. The server “only” has 1 GB of RAM, and allocating a fixed amount of RAM (which must be at least 128 MB for a more or less usable server OS) is really wasteful.
Our solution was simple. Each user got his own Apache installation and runs all his web applications under his own user account. Users cannot read from and write to other users’ home folders. Each of these backend Apache installations are firewalled, and a frontend web server proxies requests to these backend Apache installations.

But the setup is of course not limited to one-Apache-per-real-user. blog.phusion.nl is running on Wordpress, which doesn’t exactly have a good security track record. My personal Wordpress installation had been hacked once: apparently some spam bot changed the file upload folder to /tmp and put a .exe in there. It also disabled Akismet. I wouldn’t be surprised if someone one day finds a remote shell code execution vulnerability. One really wouldn’t want to run Wordpress with the same rights as all the other web applications. So we gave Wordpress its own user account and Apache installation. Wordpress is now completely sandboxed and cannot do any harm to the other websites.
EfficiencyIndeed, what about efficiency? We’ve been using this setup for almost 2 years now, and it’s actually running quite well. Not too long ago, this server hosted a website which got about 30 000 unique visitors per day (about 120 000 requests per day on this server; we load balanced that website over multiple web servers) and it was able to handle the load with ease. We noticed no delay in response times compared to when the website was running on the frontend web server directly. That said, we did go through several stages of optimization:
Finally, we used Apache with the worker MPM and Phusion Passenger development version (from the git repository) for hosting our Rails applications. The worker MPM, which uses a combination of threads and processes, is a lot more memory efficient than the default prefork MPM, which only use processes. This is our Apache worker MPM setup:
StartServers 1 ThreadsPerChild 10 MaxClients 10 MinSpareThreads 1 MaxSpareThreads 1 MaxRequestsPerChild 50000 ThreadStackSize 500000This tells Apache to use only one process. That process is multi-threaded and will have 10 threads for serving requests. Furthermore, each thread will have a stack size of 500 KB. The default system stack size is usually something along the lines of 8 MB, so setting such a small stack size reduces Apache’s VM size a lot. 500 KB has proven to be sufficient for Apache.
Now, let’s compare the memory usage between Nginx and our Apache installation:
USER PID %CPU %MEM VSZ RSS TT STAT STARTED TIME COMMAND root 11700 0.0 0.2 3452 2012 ?? Is 6:23AM 0:00.00 nginx: master process /usr/local/sbin/nginx www 11701 0.0 0.3 3452 2880 ?? S 6:23AM 2:28.91 nginx: worker process (nginx) www 11702 0.0 0.3 3452 2880 ?? S 6:23AM 2:47.10 nginx: worker process (nginx) app 82548 0.0 0.3 7656 3572 ?? Ss Tue03PM 0:05.79 /home/app/apache/bin/httpd -k start app 89467 0.0 0.4 10144 4632 ?? I 5:11AM 0:02.45 /home/app/apache/bin/httpd -k startThe server’s running on FreeBSD, not Linux, so we can’t measure memory usage excluding any copy-on-write savings (i.e. the private dirty RSS). But let’s compare the total Resident Set Sizes (RSS):
Not a big difference.
Apache’s slowness and Nginx’s performance, both overrated?People commented:
Pretty fast runtime?
X-Runtime: 0.00171
and
Damn!! It is impossible!
0.00173 per request?!
So the Rails application is running in Apache and behind an Nginx reverse proxy, and it’s still fast.
FastCGILighttpd and Nginx both support PHP via FastCGI, so why didn’t we use that instead? The answer is ease of use. Setting up a PHP-FastCGI process pool for every user is quite a hassle. Plus, the user might be running CGI or mod_perl applications as well. Giving each user his own Apache installation is by far the easiest way. Apache also supports .htaccess, which Lighttpd and Nginx don’t support. Wordpress’s URI rewriting feature writes mod_rewrite rules to .htaccess. Configuring the same rules in Lighttpd was a total pain, and I wouldn’t want to do that again.
ConclusionI believe that all the fuss about web server performance is usually overrated. As we can see, Apache can be memory-efficient. Running Rails applications on Phusion Passenger behind an Nginx reverse proxy is viable. You just need to know how to tweak and mix-and-match the two.
What we’re doing is not very unlike proxying to a Mongrel cluster from Nginx. Instead of proxying to a Mongrel cluster, we proxy to Apache. This still makes Rails deployment a lot easier because Phusion Passenger will take care of managing the Rails processes for me. The only redundant thing that I have to do now is having to setup 2 virtual host definitions: one in Apache and one in Nginx.
Morale of the story: it’s all HTTP, you can proxy everything in any way you want. Some people on the Phusion Passenger mailing list asked how to horizontally scale Phusion Passenger. The answer is: the same way you’re used to when you were using Mongrel clusters.
This also shows that it is possible to run multiple Apache installations on the same server. It’s only a matter of specifying different configuration files for each installation. It seems that a lot of people aren’t aware of that. In a recent Google talk about Rails scalability, a speaker claimed that there is a limit to the amount of hardware resources that Apache can utilize. He said that if you have 16 cores and 20 GB of RAM, one Apache instance cannot utilize all those resources, and that in order to make full use of your hardware, one must virtualize. But why? It’s easier and more efficient to run multiple Apache instances on the same machine.
By the way, we use the following Nginx config snippet for Phusion Passenger-powered hosts:
proxy_set_header Host $http_host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $remote_addr; proxy_redirect http://localhost/ $scheme://$http_host/; server { listen 80; server_name sandbox.phusion.nl; root /u/apps/sandbox/current/public; location / { proxy_redirect http://localhost:1234/ $scheme://$http_host/; if (!-f $request_filename) { proxy_pass http://localhost:1234; break; } if ($request_method != GET) { proxy_pass http://localhost:1234; break; } } }This forwards all non-static-asset requests to Apache. Static assets are served directly by Nginx.
I challenge you to type the following command:
curl -i http://sandbox.phusion.nl/ | headThis shows the HTTP output of http://sandbox.phusion.nl/ (which is, unsurprisingly, a Rails app), including HTTP headers.
Do you notice anything strange about this HTTP header?
(I’m not going to comment for a few days. I’ll let you guys speculate.)
Merb is definitely the next big thing in the Ruby world. I don't think that it will ever displace Rails as king of modern web frameworks, but Merb's popularity for smaller web projects and simple web services is hard to ignore. By signing Foy Savas to write The Merb Way, I am hoping to continue the Addison-Wesley Professional Ruby Series tradition of giving readers the best possible information from experienced practitioners.
Foy has been actively involved in the Merb open-source ecosystem for over a year, particularly with DataMapper. He uses Merb in his day-to-day activities as a full-time application developer and is an enthusiastic evangelist for the framework. He will be working on The Merb Way book full-time, and we hope to have it published early next year.
Incidentally, you can meet Foy in person in Boston on November 17-20 at the Addison-Wesley Voices that Matter: Professional Ruby Conference where he will be introducing the audience to the wonders of Merb development.
It's not the choice of language that determines the success of a project, but the people behind it. Can a Rails app serve 3 million dynamic pageviews a day? Absolutely, causes.com is doing it on a daily basis. After stumbling across several great open-source projects by Keith Rarick (beanstalkd, curl-multi, and others), I've reached out to learn about their story, and the architecture behind causes.com.
What is your background, how and why did you pick up Ruby?I have a degree in Electrical Engineering and Computer Science from UC Berkeley, and I've worked as software engineer for just over six years. I'm interested in making usable tools for engineers to create maintainable, reliable, secure systems. (Most people call that "programming language design", but my interests are more nebulous.) Although my native language is Lisp, I'm a pretty big Python fan -- it is the most beautiful among the popular languages. I've dabbled in Django since mid-2006; I started using Rails in the beginning of 2007. I also wind up writing plenty of C when the need arises.
I first looked at Ruby in 1999 as a possible alternative to Perl for some projects, but I dismissed it pretty quickly for two reasons: its variable scoping rules seemed poorly designed, and, more importantly, it didn't have much of a community (compared to Python and Perl). Around the same time, a friend introduced me to Python and I fell in love. I've been a heavy Python user ever since.
Then, in January 2007, I signed on with Causes as an engineer. The company had officially existed since October 2006, and the other engineer, Jimmy Kittiyachavalit, had already begun some work. Jimmy was pretty set on using Rails. I wasn't yet familiar enough with any web framework to say whether this was a good or bad idea, so we all went with it.
What is causes.com, how did it start?
Causes aims to streamline the process of fund-raising for charitable organizations. Billions of dollars are donated every year in the United States alone; few of them online. We're changing that. The efficiency of communication on the internet has the potential to let non-profit organizations spend less money on fund-raising, reach a bigger, more interested audience, and raise more money.
We started by writing a standalone web site, but we quickly changed gears and focused on a Facebook app when we heard of their new platform. There are a few reasons for this; essentially, it's easier for someone who's already on Facebook to add an app than it is for someone to become a regular user of a new web site. Our first public release was 24 May 2007, when Facebook launched its app platform. We've reached around 15 million Facebook users so far.
We expanded to MySpace when they opened up their platform. Combined, we serve about three million dynamic page-views per day.
What has been the biggest challenge in scaling your application, where did Ruby help, where did it hinder?
We must distinguish scalability from speed. Those are two distinct requirements, and they often have different solutions. The only piece of a website that's hard to parallelize at scale is the database. (Though projects like Hypertable are changing this.) Other pieces are easy: if your traffic exceeds the capacity of your app servers, you can add more app servers. If your static data exceeds your storage capacity, you can add more storage. This can get expensive, but it's easy to do.
So our biggest scalability challenge, just as with most other web sites, has been the database. Ruby and Rails are fundamentally no better or worse than other platforms for scaling, as long as you make sure the database access patterns are reasonable. If you are using MySQL you must pay extra attention - MySQL isn't a very smart database, so it's only fast if you use it carefully.
We've found speed to be more challenging than scaling. Adding tons of app servers isn't going to make a single, lonely HTTP request go any faster. So what can you do? You cheat. A lot of the work that results from a request (especially a POST request) doesn't need to happen until later. You can put items on a work queue and give the response sooner. Unfortunately, when we set out to adopt this strategy, there were no existing tools that could operate at the scale and speed we needed and integrate smoothly into Rails and the application. So we made Beanstalkd. Developing beanstalk meant writing a lot of new Ruby code and changing some of our existing application code. Ruby helped immensely by being a flexible, dynamic language that eased our architectural changes.
On the other hand, we've been frustrated with Ruby's memory use patterns and the efficiency of its garbage collection. Some of the memory profiling tools aren't very stable on a 64-bit OS, so fixing
memory leaks and reducing memory use in Ruby is difficult.
Well, our desire to use Ruby is obvious. And in each case, we used C out of necessity. For beanstalk, we needed speed and interoperability. Designing a work queue to hold thirty million jobs in memory is easier when you can control memory use down to the last byte. For curl-multi, we simply needed to wrap libcurl, which is written in C.
There will be more, though future projects will probably be pure Ruby. We've got a slick time-tracking tool by Kristján Pétursson that's almost out the door. It's called Clockblock. We've also got a very powerful stats/analytics/log-analysis tool that, unfortunately, needs some pretty heavy work to extract. But it will happen sooner or later.
If you could start over, what would you have done differently with Causes? Would you still use Ruby?Our architecture is pretty standard; I wouldn't change much of it. As for tools, it's hard to say. Community and support are just as important as technical merit when choosing a platform. The best-designed language in the world will eventually become a problem if it lacks robust debuggers and profiling tools.
You can be very successful with Ruby and Rails, as we have been; I have no complaints there. However, I must consider the possibility that our lives could have been easier along the way. Rails has a large and vigorous community (compared to Django), which makes finding answers and fixing bugs easier. Ruby has a small and inexperienced community (compared to Python), and the quality of Ruby's implementation is not great (yet).
If I were starting over, I would probably use Python because the community is stronger, I personally have more expertise with Python, and its design leads to cleaner, more maintainable code.
Technology aside, any advice for budding entrepreneurs and web developers?You must love both the product you build and the act of building it. Successful companies take hard work, long hours, and perseverance; those are hard to muster if you lack passion. But if you have passion, the long hours will be fun and rewarding and well worth the work!
Neal and I have been talking a lot about Essence vs. Ceremony this summer. In most of the examples I give, it is easy to tell which is which.
But that isn't always true. Consider this example from Scala. Does the application trait improve essence, or lead to more ceremony? I will post my answer next week.