Hosting for fun and profit

Posted by JP Thu, 03 Jan 2008 06:11:00 GMT

Ok, mostly profit!

Here's the gist of it: you write web applications or make websites for a living. Eventually, your clients need to host them. This is an often overlooked opportunity for profit. Either they sign up with a host or, if they don't want to get their hands dirty, they let you handle it.

Either way, you're making money. Here's how:

Step 1

Sign up with a host like Site5, which offers an affiliate program. By the way, you can host your Ruby on Rails applications on Site5. So far, I've been extremely satisfied. There's also Dreamhost that offers 97$ per referral + 5$ per sub-referral (or a 10% of the referral's bill amounts + 5% of their sub-referrals). I haven't hosted any sites at Dreamhost so I can't vouch for the quality of their service, but I've heard that they're a good place to host. They support Ruby on Rails as well. I use 1and1 for sites that don't require Rails. They do a fine job of hosting PHP sites. 1and1 also offers affiliate rewards.

Step 2

Refer your clients, those who want to manage their own server, to that same hosting service. In the case of Site5, you get 85$ (or 97$) for each new customer you bring.

Step 3

Host your clients, those who don't want to bother with the details of a host. There's a few good reasons to do so.

First of all, you'll be the one doing future maintenances on the site or application. Second of all, since you actually have to babysit the website, you can charge a monthly fee for doing so. The amount is up to you, depending whether the client is high maintenance or not. This way, you end up actually billing for small tasks which are often touchy to bill (10 minutes here and there actually add up at the end of the year).

I suggest billing a fixed amount in advance (e.g.: 30$ per month, for hosting and babysitting). The amount is arbitrary and really depends on the situation at hand, but you get the idea

Step 4

Sit and wait for the money to come in. First of all, you'll be getting referral money, which will most likely cover your own personal and professional hosting expenses. Second of all, you'll be getting paid to host your other client's applications. First thing you know, you'll make some decent money.

You actually will end up doing some maintenance every now and then, but first thing you know, you will have a nice little revenue stream coming in, just for doing what you'd be doing anyways.

You're happy, and your clients are happy too.

In case you're wondering, my affiliates program revenue alone already covers all my hosting expenses, so basically, I'm making money while spending none.

Try it out and see for yourself.

Banner, 234x60px

Posted in  | Tags , , , ,  | no comments

Rendering partial .rxml templates

Posted by JP Mon, 28 May 2007 01:09:00 GMT

Partials are an essential part of the Rails philosophy. They are a key component of the (Don't Repeat Yourself) DRY principle. A partial is a page fragment that you can reuse. It's an important of part of Rails's views.

Let's say you're writing an application (yes I will too use the blogging application to write this example). You're rendering a blog post and you want to print its comments (as a partial) as well. You'll probably do something like this:

<!-- In post.rhtml -->
<h1><%= h post.title %></h1>
<p><%= h post.body %></p>
<h2>Comments</h2>
<%= render: partial => 'comments', :collection => post.comments %>

<!-- _comment.rhtml -->
<h3><%= h comment.title %></h3>
<p><%= h comment.body =><p>

There you go, partials. Then, if you have another page that needs to display blog comments, you can re-use the post partial instead of re-writing that code. DRY FTW!

Now, what if you want to do the same thing using a .rxml template instead of a .rhtml template:

# In post.rxml
xml.post do
  xml.title post.title
  xml.body post.body
  xml.comments do
    render :partial => 'comments', 
      :collection => post.comments
  end
end

# In _comment.rxml
xml.comment do
  xml.title comment.title
  xml.body comment. body
end

You would expect that to work, wouldn't you? Unfortunately, it doesn't. You won't get an error, but you won't get any output either; the section in your output document will be empty. How sad and unsatisfying!

The issue at hand is that - note that I'm not familiar with the template rendering's inner workings so let's pretend this is true - the xml object in the _comment.rxml partial has a different context than the xml object in the post.rxml file. It seems that Rails instanciates a new xml for every template it renders. In other words, your partial's output is not going where you're expecting it to go.

How to fix this? It's pretty simple actually. We need to tell the partial that we want it to use the same instance of xml. We do that by passing it the current instance of xml using render's :locals parameter and then by setting the value of xml by hand:

# In post.rxml
xml.post do
  xml.title post.title
  xml.body post.body
  xml.comments do
    render :partial => 'comments', 
      :collection => post.comments, 
      :locals => {:xml_instance => xml}
  end
end

# In _comment.rxml
xml = xml_instance unless xml_instance.nil?
xml.comment do
  xml.title comment.title
  xml.body comment. body
end

That's it! One note, you need to use a different name (I used xml_instance in that example) because if you use xml like this:

render [...], :locals => {:xml => xml}

It won't work. I suspect that the auto-instanciated xml object has a different scope, which superceedes the assignment made by the :locals parameter. Again, I'm not familiar with how things work under the hood, but I think the :locals variable assignments don't work if a variable with the same name already exists in the current scope.

That's it, I hope that was useful, and please Dont Repeat Youself. Always use partials!

Posted in  | Tags , , , , , , , ,  | 4 comments

Solving the Infamous Trailing Slash Problem

Posted by JP Thu, 24 May 2007 09:43:00 GMT

So yesterday, after upgrading Typo, I had this problem:

http://www.jponrails/blog/

would work but

http://www.jponrails/blog

wouldn't (400 Bad Request).

The problem is my blog runs with Mongrel FastCGI so in my public_html folder, I have a symbolic link that points to my application's public folder. Somehow, if you don't put the trailing slash, you get a 400 Bad Request error. I need to investigate this further, and I will as soon as I have some time.

I searched on the web for a mod_rewrite-based fix. All the fixes I found would work without the trailing slash, but they would break when you put the trailing slash! Not very useful...

That's until I found this blog entry on LavaFactory. That link I put is broken for some reason, so try clicking here and scrolling down a bit.

Here's the code I pasted in my public/.htaccess file:

# Trailing slash fix
RewriteBase /blog/
RewriteCond %{REQUEST_FILENAME} -d
RewriteRule ^(.+[^/]+)$ $1/ [R]
RewriteRule .*/blog/(.*)   http://www.jponrails.com/blog/$1 [L,R]
RewriteRule ^([^.]+)$ $1.html [QSA]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^(.*)$ dispatch.fcgi [QSA,L]

Posted in  | Tags , , , , , , ,  | no comments

Good Web Application Development Practices

Posted by JP Tue, 22 May 2007 02:03:00 GMT

Or, how to decrease the probability that you shoot yourself in the foot.

Here's a checklist of things you might want to do early on during a web application. Doing these simple things will save you trouble, save time and help you put out a better quality product. The earlier you do them, the more time you'll save.

1 - Commit Source Code to Subversion

If you prefer another source-control system, use another one. The point is, use source control software. If you don't, bad things can and will happen.

Source control will help you:

  • Track regression bugs.
  • Remember what your code looked like before after you change your mind.
  • Bring other people on board. Having more than one person modify a code base without source-control is a surefire way to attract problems.
  • Document what you did and when you did it.
  • Undo errors. Yours or others'.

2 - Write Automated Tests

Automated tests are a key component of Quality Assurance. If you can't hire QA people because you're running a small operation, fine - but do the minimum.

Automated tests let you:

  • Find bugs as soon as they are created.
  • Know when you break an interface.
  • Find bugs before you deploy.
  • Find bugs before your client/co-workers/boss finds them for you.
  • Test your code in a relatively thorough fashion in a fraction of the time you would do it by hand.
  • Increase the quality of your projects constantly.

3 - Set up a staging environment

Sooner or later, you'll need to deploy things that can't be tested in a development environment: server configuration changes, database server upgrades, whatever. The only way to test this reliably is to do it using a staging environment.

While testing your deployment on the staging environment, take note of everything you do so the real deployment will be smooth. To be safe, you can even stage the deployment twice. The second time around, you'll be sure that you didn't forget anything.

A staging environment will help you

  • Deploy your software easily.
  • Test the deployment procedure itself somewhere else than your production environment.
  • Document changes done to the production environment.
  • Get up and running quicker should you need to restore your entire production environment.

4 - Automate your deployment procedure

Scripts are faster than you are and if they're set up properly, they don't make mistakes. If your scripts are intelligent enough, they let you undo the deployment. Write them to be what you want them to be. My advice on the subject is to do it good enough so you save time without going overboard.

Automating your deployment procedure will let you:

  • Minimize your application's downtime.
  • Deploy urgent fixes quickly. It happens.
  • Deploy more often by removing overhead. The easier it is, the more you'll do it. Your product will be incrementally better, faster.

5 - Fix problems as soon as they show up

Procrastinating is bad. Procrastinating bug fixes is especially bad. Fix problems while they are fresh in you mind. Don't wait two months to fix something that you could fix now. That way, you won't forget it, and it will take less time ot fix.

Out of lazyness, no bullet list for this item!

6 - Backup everything

On-site, and off-site. Your local machine and the servers. On site backups aren't enough: they won't protect-you against theft, fire, or whatever mother nature can cook up these days.

My friend's father who's a graphic designer used to backup his work on a Zip Drive. Too bad his backup disk was in his computer when it was stolen. Not only did he have to deal with the theft itself, but he had to redo a few weeks worth of work, with the ensuing consequences. Let's all learn something from this anecdote. I know I have.


Now, Business consultants charge four figures to walk into a conference room and tell you the same things I just told you with PowerPoint slides. One could say that they are crooks for doing so. One could also say that the return on investment will make up for that cost.

Maybe your project isn't there yet, fine, but as soon as a project becomes a source of revenue - or expenses, you want do be following these tips to make sure you're not burning your profits, potential revenue, or even worst, money out of your pocket.

The bottom line is that if you're not doing these things, you're lazy, but in a bad way. Lazing is an art. Do it well.

Please share any other ideas/suggestions you might have.

Posted in  | Tags , , , , , , ,  | no comments

Useful Rails Plugins

Posted by JP Sat, 19 May 2007 07:24:00 GMT

I stumbled upon this list of useful Rails Plugins on Juixe TechKnow.

The first one in the list, acts_as_taggable is super useful. It lets you add flickr-like - or del.icio.us-like if you prefer - tags to any ActiveRecord object. It works great and I've used it in a few projects.

Nice to see that the community is sharing useful code. That's the thing with the RoR community: people are proud of the nice code they write and want other people to see and use it.

Posted in  | Tags , , ,  | no comments

Tip of the Day: Creating 'Back' Links in Rails

Posted by JP Thu, 01 Mar 2007 21:54:00 GMT

One of the things you need to do frequently in web applications is provide a link for the user to navigate back one page when the user enters a form.

For our example, let's consider you're building yet another blogging application and providing a page which lets the user add a new Post to the blog. From that page, you want to provide a link to the previous page, in case the user changes his mind.

The quick-and-dirty way of doing this would be linking to the list action, since the will usually come from a page listing all the Posts.

<%= link_to 'Back', :action => 'list' %>

This will work.

Oh, wait... maybe not. What if the previous page had an extra parameter, let's say to list all Posts belonging to a specific Category.

We can fix this:

<%= link_to 'Back', 
            :action => 'list',
            :category_id => @category_id %>

Ok, this will work, assuming that the link to the new action passed on the category_id parameter to the new action, which would be logical.

That's better.

But what if list had another parameter that wasn't passed on the the new action, like a sort_order parameter?

Things can easily get complicated and mistakes can easily be made, leading to unelegant broken links.

The proper way to do this is as follows:

<%= link_to 'Back', request.env['HTTP_REFERER'] %>

This will work in all situations, even when the previous list action was the result of a create or update, since these actions normally redirect to the list action. The 'Back' link will effectively link to that redirection, and not pop the unelegant The page you are trying to view contains POSTDATA message.

One last thing to consider. What if the new page is the first page the user visits after launching the browser (e.g.: followed a link in an email). Where will 'Back' link to? The browser will link to the current page! How useless. Let's reiterate our solution to avoid this irritation. There are two acceptable solutions:

<%= link_to_unless request.env['HTTP_REFERER'].nil?,
                   'Back',
                   request.env['HTTP_REFERER'] %>

will always display 'Back', but it won't be clickable if there is no referrer.

<%= link_to 'Back',
            request.env['HTTP_REFERER'] 
    unless request.env['HTTP_REFERER'].nil?

will not display 'Back' unless there is a referrer.

Both these solutions are good enough. Why good enough? If by clicking 'Back' you go back to a page that had a 'Back' link - for example, when you submit a form with invalid data, you only get one properly functioning link. It's a small caveat since once the user submitted a form with invalid data, it's unlikely that he'll want to go back and not edit at all. There's always the main menu and in last resort, the browser's own 'Back' button.

And for those users familiar with the Rails Recipe book, using link_to_unless_current conjointly with the Cleaning Up Controllers with Postback Actions recipe will not prevent the links from being displayed. I tried.

One question remains: why is HTTP_REFERER missing an 'R'? One would think mistakes like this wouldn't get through.

Posted in  | Tags , ,  | 3 comments