Jack Chu

Retrying a Block of Ruby Code if It Fails

| Comments

I have a piece of code that needs to remove (rm -rf) a directory, but sometimes FileUtils#rm_rf will fail and return an Errno::ENOENT with the message “Directory not empty.” Maybe a file in that directory is locked by the OS, but for whatever reason, it can fail. So in such a case, I retry it a few times and exit if it fails to remove that directory after those attempts.

The code might be familiar, it looks like this:

1
2
3
4
5
6
7
8
9
10
11
12
directory = Pathname.new("/path/to/somewhere")
retry_count = 0
begin
  FileUtils.rm_r(directory)
rescue Errno::ENOENT => e
  retry_count += 1
  if retry_count > 3
    raise
  else
    retry
  end
end

The retry counting and incrementing bit can be verbose and if you need similar functionality elsewhere in your code, it can get kind of messy. I have another piece of code that uses Grit to clone a git repo and that can time out so I retry that code a few times too. This type of retry code can be useful when accessing external apis or anything that can possibly time out that you might want to retry.

Mongoid Doesn’t Preload Models in Rake Tasks

| Comments

I have a Rails application with an initializer that accesses my Mongoid models. This works fine locally when I run rails s, but when I deploy to Heroku, the deployment will eventually timeout as Heroku tries to run:

1
rake assets:precompile

It’s not just Heroku though. If I run that rake task locally, it will also just seem to freeze or lock up when it tries to access any Mongoid model. I’ve verified this with the ruby debugger.

It turns out that Mongoid only preloads your models when $rails_rake_task is false (ie. not a rake task). Here’s the Github issue where this change was made. I’m not sure why this was changed. I guess most rake tasks don’t need to eager load the models since they don’t need to access them. To work around this, I’ve just put a condition also checking for $rails_rake_task. In my case, the initializers need to access the models when the app starts up, not when rake tasks are run.

Update 10/12/2011 - Looks like I posted this too soon. This is coming back.

Rails Asset Pipeline Live Compilation Mode

| Comments

Rails 3.1 comes with a live compilation mode for serving static assets, but in order to describe what it does we’ll need to go over the recommended method of serving up static assets in Rails.

Normally, after a deploy, it’s recommended you run:

1
rake assets:precompile

This will run in the production environment even without specifying a RAILS_ENV. This rake task compiles all your static assets to:

1
public/assets

Usually, you’ll do this via a post deploy hook. Then your Rails app will serve the files via the ActionDispatch::Static rack middleware.

Let’s say you decide to not precompile your assets. Any requests to a static asset will return a 404 because it can’t find the asset. However, if you turn on live compilation, Rails will compile static assets on the fly. To turn it on:

config/environment/production.rb
1
config.serve_static_assets = true

By default, around line 12, you’ll see that this is set to false. This isn’t recommended, since there’s more processing involved than the precompile route.

Rails Asset Pipeline, Content Delivery Networks and Rack::Cache

| Comments

So you have a brand new Rails 3.1 app and you’re using the new asset pipeline feature. You’re also using a content delivery network (CDN) like Amazon CloudFront or Cloudflare to serve up static assets. Everything’s working great, but little do you know, Rails is polluting your cache storage with static assets!

When you use a CDN, a request for a static asset will hit the CDN first. If the CDN doesn’t have that asset on its servers, it will request the asset from your Rails app and then store it across it’s global distribution network. The next time the asset is requested, it will be served up from the closest geographical data center to the user. This hopefully gives the effect that your website is loading faster.

Fixing Sluggishness With Mongoid in Development

| Comments

I’ve been migrating a project from Postgres to MongoDB, where dynamic fields would help tremendously. We went with Mongoid for our ORM since it seems to have the most support and activity on Github. However, one thing I’ve noticed after migrating all my models is that the app was instantly slower. Everything felt sluggish, but when I deployed to a staging box, everything was fast and snappy. One of the first things I started to do was to switch on some production environment settings to see if some of these flags could give me a hint as to what the issue was.

Easily Deploy Static Sites Into the Cloud With Nanoc Deploy

| Comments

Updated July 14, 2011: As of Nanoc 3.3, nanoc-deploy will be integrated into nanoc core.

Recently at work, we’ve needed to deploy some static websites. The designers had been hand coding these in raw html for months, but I thought it’d be great if we could bring in some HAML and SASS goodness since they’ve been using it extensively on our Rails apps. I’ve been dabbling with static website generators months ago for my parent’s restaurant website. I looked at Jekyll, Toto, and StaticMatic, Webby, but ultimately I found the best for me was nanoc. This was in part due to @h3rald blogging about it.

Jekyll is great, but it’s mainly aimed at blogging. Toto was too simple. StaticMatic and Webby aren’t actively maintained. Nanoc is pretty actively maintained and it’s great for building any kind of static site, not just blogs.

Automated Heroku Database Backups to Amazon S3

| Comments

At work, we’ve recently switched from Engine Yard AppCloud to Heroku. One of the things we’ve been missing is daily database dumps. Heroku does provide you with an addon called PG Backups. The basic free version will retain 2 postgres backups, which you have to kick off manually.

There’s a gem created by @ddollar (now maintained by @joemsak) called heroku_backup_task. This gem adds a rake task that captures a new database backup in the PG Backup addon and expires the oldest one.

Named Parameter Scopes and Form_for

| Comments

I’m working on a Rails 3 app that hosts many projects and every resource within the app is scoped by a project. So wallpapers, videos, polls, etc. belong to a project. Ideally, I want my routes also scoped by a project. It’s easy to configure nested resources that give you routes that look like:

1
/projects/:project_name/videos

But since everything is scoped by the project name, why don’t I just drop the /projects prefix?

config/routes.rb
1
2
3
scope ':project_name' do
  resources :videos
end

So this gives us params[‘project_name’] in each video action. Now our routes can look like this:

1
/:project_name/videos