Hosting your Rails app – first look at Heroku

Introduction: You should really get professional help

I am building an app and needed to show an unfinished version to some guy. As I am building on a local (windows!) box, I decided that it’s time to invest some time in finding out what options there are to host a Rails app.

My first choice was my old PHP shared hosting for which I pay for the last 7 years and it just lies there. So, my hosting company said they support Rails, so after some fiddling with cpanel I’ve uploaded my RoR files… One hour later I found out from the customer service that they do not support any deployment tools. Further, to install any gems I need to send them a request via email… Given that Rails app can easily have 10-15 gems, I thought this was a show-stopper. This is what I think you will find with non-specialized Rails shared hosting environments – they will be too difficult for you to work with, so just don’t bother.

Ok, I’ve decided to shop around and one thing that I always wanted to try was Heroku. It’s a “different type” of hosting, but come to think of it, quite similar to how I already work with Rails (read: loads of console commands). The ease of deployment will very much depend on your application – how complex it is, what sort of gems you use, etc.

Heroku prides itself on making the deployment effortless. And for some projects it might as well be true. For me it was not a 5 minute job, I took 2 full days to transfer the project, because there were several things that needed to be changed in the code, and I also had to learn several things – like Git and S3, that were on my to do list anyway (so that’s all right 😉 ). But, now that I know the limitations of Heroku, I would be able to build my future apps with “Heroku compatibility” (more on this in Gotcha section) built-in.

Heroku – getting started

1 – Sign up. The best thing about Heroku is that you can start by using their free hosting plan. Just register on their site.
2 – Git and Rails installed. I assume you have Rails installed locally, and you should also have Git installed for Heroku to work.
3 – Run “gem install heroku” to install the heroku gem. It will add a “heroku” command tool to your command line that will be the way for you to work with your hosting – there will be no ftp and no web control panel (the control panel is still used to switch addons on and off, but majority of activities are done from the command line). After installing the gem, try running “heroku” – it should show you a list of available commands.
4 – Heroku actually has a good Quick start guide that you could follow easily. There are some tricks for a Windows user, so I will cover them here:

4.1. Using Git. First, you will need to initialize the Git repository for your code. If you never used Git for anything other than downloading plugins, you need to start learning to use it as your VCS of choice. If you are already using some VCS for Rails, you will need to move to Git in order to use Heroku. As I didn’t use a VCS, it was easy for me.

4.2. Switching Git on:

* Go to the root directory of your rails app (the one you want to host).
* Heroku has a 50mb limit on the size of your Rails project for a free hosting plan. So, before running any commands, remove any obvious garbage from the directory (old copies, big archives, graphic and video files you don’t need).
* If there are some things that you’d rather leave in the project directory but want Git to ignore, create a .gitignore file in the root of your project. Some useful info on .gitignore is here.
* Ok, if you are all set, run the following commands:

git init
git add .
git commit -m "first version"

The first line initializes a new repository. Second adds all files in the current directory to the repository. The last commits a “release”, and -m “text” provides a comment. Now is the time to invest into learning the basics of Git, as you will be using it a lot. A good introduction on Git is here.

4.3. Creating SSH keys. Now you need to create a public key to allow Git to work using SSH with the Heroku host. Here the Heroku documentation is sparse, so hopefully you will find these instructions helpful:

* Go to the Git\bin directory (for me it was in c:\Program Files) and run “bash” command. It will show you a unix-like prompt.
* Run this command in bash, providing your Heroku email after -C switch:

ssh-keygen -t rsa -C "your.email@here"

* When prompted to provide a name for the key, type a name “id_rsa” and hit enter.
* When asked for a password you can leave it blank or set one up – it’s up to you. If you set a password, you will be prompted to type it every time you upload to Heroku
* Now, in your Git/bin directory find the just created 2 keys – public and private.
* Move those files to your c:\Users\[your username]\.ssh directory
* Finally, upload the public file (by default with .pub extension) to Heroku by using this command:

heroku keys:add

If it doesn’t find it, you can explicitly set a full path to your key, like this:

heroku keys:add c:\key\id_rsa.pub

Note.

If you did everything correctly, it will just work. If Git won’t find a local private key that matches the public key you uploaded, you will get an error like this: Permission denied (publickey).

Finally, I first tried to use puttygen to generate the keys but did not succeed.

5 – Creating your Heroku app. Now from your Rails project’s root directory run

heroku create

It creates the space for your application, provides a temp url (you can change it later) for you app, and so on. If it asks you for login / pwd, enter the ones you registered on Heroku with.
6 – Uploading app to Heroku. From the same project directory simply run

git push heroku master

It might ask you for a public key password from step 4.3. But other than that you’re all set. In theory after it successfully uploads, you can run “heroku open” to open your app in browser, but it doesn’t work for me in Windows. You can open it manually in your browser or from the Heroku web console.

7 – Heroku Gotchas – what you should know!

7.1. – Database access

After you upload your scripts, you will want to create the database based on your production database. There are two options. You can run “heroku rake db:migrate” to walk through each migration file. However, if during development you mishandled at least one migration file, it will be tough to fix. A better way is to just upload the schema – “heroku rake db:schema:load”.

Heroku does not allow you to work with the database (or files for that matter) directly, so it’s good if your development environment follows exactly that of Heroku. And Heroku runs on a somewhat less popular PostGres DB, so if you have some more advanced SQL in your code, you’re in for some fun trying to rectify the SQL errors that are working fine on MySQL and SQlite. For me, two plugins stopped working due to a PGError SQL error, and it took a couple of hours to fix.

Heroku also provides a way to push (and pull) data to the production database, but it didn’t really work for me, giving some cryptic error, so I raised a ticket with Heroku CS – let’s see how it goes.

7.2. – Logs and console

Both logs and console are accessible via heroku command. Run “heroku logs” to get the latest extract from logs and “heroku console” to load the console for debugging / testing purposes. These two commands will be your best friends debugging the hosted app.

There is another add-on that you can switch on, called Exceptional, that send you errors via email. But for me it worked with a huge 1-2 hour delay, so it’s not really useful.

7.3. – Installing gems

Heroku takes your vendor/plugins directory just fine, but the gems need some additional setting up to do. You need to list all gems your application requires in “.gems” text file in the root of your project. You can just list the names of gems or set a finer control, listing the version numbers and repositories. More info here.

7.4. – Your file space is read-only(!)

So, this might come as the biggest surprise to some of you, but apart from the scripts that you upload via Git you cannot write anything to disk. You need to host your uploads / userpics / videos, etc. elesewhere. The best alternative probably being S3. Of course, this will mean changing all your scripts to work with S3. Heroku even explains how for the most popular plugins – attachment-fu and paperclip.

7.5. – No mail / SMTP gateway provided
Heroku does not provide you with an SMTP gateway, you will need to find one yourself and modify the required config files accordingly.

7.6. – Configuration made differently
Heroku suggest you to provide it with the configuration variables using their own methods. More info here.

The verdict

Heroku seems to be a great way of deploying your Rails app. If you set it up according to the rules, deploying will be a breeze – a single line of code will take care of everything(!). If you haven’t been developing with the “cloud” architecture in mind, you’re in for some rewrites, but at least you do it only once.

One thing to note is that Heroku allows collaboration out of the box – this is the power of Git-based hosting for you.

Some things missing for me is the db console, and the db:push doesn’t work at the moment, so it feels like the debug is not fully possible.

I am also not sure about the performance of the application – there are several things added to the stack to allow for the magic. If you need some non-standard things, you most probably will want to have a hosting platform that’s open for you to do any hacks you need.

Still, as a “development box in the cloud” this is great, I recommend you to try it out for your hosting needs!

Advertisements

December 5, 2009 at 7:07 pm 11 comments

Rails caching – resources

When you create anything serious on Ruby on Rails, you will most definitely need to start thinking about caching. As Ruby is a high-level language, a lot of crunching goes on to make the magic work. So in order for all this magic to work you should ensure that the heavy-lifting is done only once and after that you just use the results.

Good news is that caching in RoR is very powerful standard feature.

When should you start thinking about caching? It definitely pays off to know the proper ways to cache in RoR before you start coding anything serious. However, the optimization could be done at some later point, analyzing which queries, screens and views give you the most trouble.

Here’s how you should start with caching:

1 – View all the railscasts.com caching tutorials first. Although Ryan Bates does not go into details on the theory behind the caching, the ability to see a real-life example and get an easy explanation is priceless.

2 – After that read the “official” introduction to caching on the RoR site. You might want to skip some parts at the first reading.

3 – Finally, you should invest your time in the advanced video casts on Rails scaling by true experts NewRelic. These courses are made free for all to use – perfect!

October 31, 2009 at 2:02 pm Leave a comment

Ruby variables

Something that you might have to watch out for when working with Ruby is how it works with variables. Ruby variables are only references (pointers) to objects. Therefore, you might experience a subtle behavior that you probably don’t expect. Try this out in your irb:

irb(main):001:0> a = "some text"
=> "some text"
irb(main):002:0> b = a
=> "some text"
irb(main):003:0> a.object_id
=> 23109650
irb(main):004:0> b.object_id
=> 23109650
irb(main):005:0> a.gsub!(/ text/, "thing different")
=> "something different"
irb(main):006:0> b
=> "something different"
irb(main):007:0>

First, we assign a String object “some text”. We could have written it fully as a = String.new(“some text”).

Second, we say b = a, and for Ruby this means that b will now point to the same object as a, and you can verify it by running object_id on both variables. But now comes the catch – if you modify a, b will be automatically modified. So, by running gsub! on a, we also modify b.

However, if you assign a new value to one of those linked variables, the link breaks down, as now one of the variables points to another object. So, if you type a = “some new text”, b will not change, and actually a and b will now point to 2 different objects.

If you want to create a copy of an object and point a variable to it, instead of b = a, you could have cloned the object: b = a.clone.

September 24, 2009 at 9:17 pm Leave a comment

Timing attack? What’s that about?

If you are wondering, like me, what was the “timing attack” fix update in the latest 2.3.4 for, you can read this post here. Basically, if a comparison is made between two strings, it’s done one character at a time, and it stops when the first differing character is encountered. Therefore a potential hacker could measure how much time it takes to check a cookie hash to see if it’s correct or not.

It all seems far fetched, given that surely there must be the overhead in terms of routing from attacker’s PC to your server and Internet Protocol actually works that way that the packets are sent using different nodes, but there are guys who think it’s practical. It’s claimed that most Java programs are exposed under this theoretical vulnerability, so it’s actually not a problem particular to Rails.

However, the bad news about this 2.3.4 patch is that it doesn’t work under Ruby 1.9.1.

September 8, 2009 at 9:01 pm Leave a comment

Defining methods in Ruby

1 – Hashes in method calls

You must have seen this syntax in Rails a lot, for example when using this Paperclip plugin, you would put this in your model:

has_attached_file :photo, :url => "/:class/:attachment/:id/:style/:basename.:extension"

While it looks pretty natural, you might have harder time understanding that has_attached_file is really a method, and there’s a considerable amount of trickery involved to make this method call much easier on your eyes. This post will not only help you read the Ruby code better, but actually create the methods with flexible parameters yourself.

Consider this equivalent call:

has_attached_file(:photo, {:url => "/:class/:attachment/:id/:style/:basename.:extension"})

Now, it’s more clear that has_attached_file method passes 2 values, where a second value is a hash. Allowing hashes in method calls gives a great freedom for both the developer and user of the method – you do not need to remember what’s the correct sequence of the parameters for the method and it’s possible to omit some parameters altogether. So, instead of some_method(first, second, third), you can use a more flexible some_method :second => second, :first => first, :third => third.

Do note, that if you omit the round brackets, you should also omit the curly brackets, so that the hash is not confused for a block, which also uses the curly brackets.

Actually, if you look at how the method was defined in paperclip plugin, you will see this:

def has_attached_file name, options = {}
  ...
end

This method definition (def) uses the fact that Ruby makes brackets optional even for method definitions, so it’s equivalent to this definition:

def has_attached_file(name, options = {})
  ...
end

And what it means is that has_attached_file method expects 2 parameters. The one called options is a hash and it defaults to an empty hash. Actually defaults are quite powerful in Ruby – you can pass any arbitrary Ruby expression to them and call any variables in scope and link to any other parameters. You could have said, for example – def has_attached_file name, options = name.size.

So, how would you access those values passed in the hash? This is very easy, you would do something like this:

def has_attached_file(name, options = {})
  size = options[:size] || 0
  file = options[:file] || "undefined"
end

So, you would check for a hash element with a key :file and if it exists, assign it to the file local variable. If it does not exist, you will (by using ||) set a default.

2 – How many parameters do you want? – Splat arguments

Another common way to define a method is like this:

def some_method(*args)
  ...
end

This means that however many arguments can be provided and they will all be moved into array called args, so that you can access them as a normal array. You can also do something like:

def some_method(first, *args)
  ...
end

This will move the first parameter to first local var, all others (if any) will go into the args array.

Splatting comes in handy, if you want to define a method for your class that does a slight modification of the superclass’ method and then passes all the arguments to the superclass:

Class Child < Parent
  def some_method(*args)
     # your code here
     super
  end
end

If you use super without parameters, it will pass whatever parameters your method received to the parent class. And you can actually further shorten the way you define the method, by just using an asterisk in def, like this:

  def some_method(*)
     # your code here
     super
  end

3. Define your own method on fly?

Another thing you will notice a lot in Rails, is the possibility to define the methods on the fly. And great thing about it is that you can create the method name using any variables and Ruby expressions. Here’s another example from the Paperclip:

define_method "#{name}=" do
  ...
end

This will create a method using the name variable, so that you can have access to this method based on the name of your choice. For more info you can see Ruby docs.

September 6, 2009 at 6:50 pm Leave a comment

Rails 2.3.4 is out, security vulnerabilities fixed

Rails 2.3.4 is out, just a few weeks after the 2.3.3. There are no new features, the reason for this quick release are the 2 vulnerabilities found in the Rails code (one is a possible XSS epxloit and the other is a cookie hack. The release notes state that over 100 small bugs were fixed as well.

However, given the amount of problems some users have (see some comments here) – mostly as it seems with Ruby 1.9, you might want to just patch the vulnerabilities for now, or at least test before you upgrade on production ;).

September 5, 2009 at 10:12 pm Leave a comment

Updating Ruby / Rails

Updating Ruby, Rails and other installed gems is pretty easy.

1 – Run the command “gem outdated”, to see which of your installed gems need updating.

2 – Update the gems itself by running

gem update --system

3 – Then if you want to update all the gems, simply run the command “gem update”. If you’re running the command in Windows, you should probably run “gem update > result.txt”, which will output the results of the command in the text file, so that you can take a look if any error were reported in the process.

4 – Finally, if you made an update of Rails, you will need to manually change the version your project uses by going into config/environment.rb and finding and changing this line:

RAILS_GEM_VERSION = '2.3.3' unless defined? RAILS_GEM_VERSION

August 30, 2009 at 3:45 pm 4 comments

Older Posts Newer Posts


Recent posts

Starting to learn Rails?

Kindle

Get Kindle - the best e-book reader, that I personally use, and the only one that you can read on the beach - very useful: Kindle Wireless Reading Device (6" Display, Global Wireless, Latest Generation)