nginx Maintenance Page for Rails

Wednesday, August 12th, 2009

I recently moved one of my main Rails projects from a Mongrel/Pound stack to Thin and nginx. During this process, I was attempting to set up a maintenance page that would display whenever Thin was offline, but there appears to be some confusion on this topic. Below you will find my minimal solution for displaying a maintenance page for an nginx based rails deployment.

nginx conveniently supplies an error_page configuration option which can be used to specify an html page to be displayed whenever certain errors occur. When the proxied server is offline, such as when Thin or Mongrel is restarting, or you have it stopped while performing maintenance, nginx will return a generic “502 Bad Gateway” error. To replace this page with your own more aesthetically pleasing version, simply place an html file in the public directory of your rails app, and then place this line somewhere in the server section of the nginx config file for the site (which should reside in /etc/nginx/sites-available).

error_page 502 /offline.html;

Simply replace offline.html with the name of your error page, restart nginx, and you’ll be good to go. Here is a bit more context from the configuration file.

server {
  listen 80;
  server_name www.example.com;

  error_page 502 /offline.html;

  location / {
    ...
  }
}

Render Rails Templates Anywhere (even in a model)

Monday, July 20th, 2009

I can only dream of actually having the time to properly update this blog, but for the moment I’m simply posting a snippet that has been very useful to me.

Even though I love Rails, I hate the way it locks you into only working within its paradigm, making it virtually impossible to break out of the MVC box even when it makes far more sense to do so. One particularly bothersome case is when you need (for whatever reason) to render an ActionView template outside of a controller.

For instance, in an application I’m working on I allow users to customize automatically sent emails. These emails are templated using a custom class that allows the user to insert predefined tags into the message that are automatically replaced with information such as the recipients name, address, etc. One such tag is replaced by a summary of all the users registration information, and this summary is simply an ActionView template. This leads to the sticky part. The template class is prepared by a class method of my model, which needs to provide a block to the template class capable of rendering this summary page.

Enter the render_anywhere method!

def render_anywhere(partial, assigns)
  view = ActionView::Base.new(Rails::Configuration.new.view_path, assigns)
  ActionView::Base.helper_modules.each { |helper| view.extend helper }
  view.extend ApplicationHelper
  view.render(:partial => partial)
end

Simply place this method in a file in your lib directory, or even in environment.rb, it really doesn’t matter. Then you can just call it (from literally anywhere) as shown below:

render_anywhere('/students/summary', { :student => student })

You can also add controller specific helpers if necessary, by simply adding more view.extend lines as above.

(thanks to Compulsivo for much of this code)

Better Redirects in Rails

Saturday, March 22nd, 2008

Its been a very long time since I posted to this blog, but I thought I might share some tricks I’ve developed for handling a few special types of redirects a bit more gracefully in Ruby on Rails.

Note: all of the code in this post, except for one view helper method, should be placed in your ApplicationController (app/controllers/application.rb) from which all other controllers inherit.

Most people who have read any book on Rails will probably have run into the redirect_to_index method, which goes something like this:

def redirect_to_index(msg = nil)
  flash[:notice] = msg if msg
  redirect_to :action => 'index'
end

This method is mainly useful when you the user has just edited an object, and you now want to display a message in the flash like “User updated successfully”, and then redirect them back to the index action. But what about if you don’t want to redirect the user back to the index action, or if you want to send them to another controller? Say hello to the flash_redirect method:

def flash_redirect(msg, *params)
  flash[:notice] = msg
  redirect_to(*params)
end

flash_redirect accepts both a message to be put in the flash, along with the params for redirect_to, so that you can flash a message and then send the user anywhere you please.

These two methods by themselves are pretty useful, but what about the common situation where a user attempts to go somewhere they don’t have permission to, or that they need to login before accessing? In the Rails book, this is handled by storing the original url in the session, and then redirecting to the other action, which then has to do special session processing when it returns the user to the original action. Encapsulating all this code into some easily reusable methods would look like this:

# redirect somewhere that will eventually return back to here
def redirect_away(*params)
  session[:original_uri] = request.request_uri
  redirect_to(*params)
end

# returns the person to either the original url from a redirect_away or to a default url
def redirect_back(*params)
  uri = session[:original_uri]
  session[:original_uri] = nil
  if uri
    redirect_to uri
  else
    redirect_to(*params)
  end
end

redirect_away handles sending the user away to another action, and redirect_back will send them back to either the action they were redirected away from, or to a default action. One possible use for these could be to require authorization before accessing an action:

class AdminController < ApplicationController
  before_filter :require_admin, :except => 'login'

  def index 
    # unauthorized people shouldn't be able to access this
  end

  def login
    # handle login
    if User.authorize(params[:username], params[:password])
      session[:admin] = true
      redirect_back(:action => 'index')
    end
  end

  private

  def require_admin
    unless session[:admin]
      flash[:notice] = "You must be logged in"
      redirect_away(:action => 'login')
      return false
    end
  end
end

So now we can redirect a user away from an action, and then send them back to it later on. But what if we want to let a user click a link to go somewhere, and then send them back where they came from later? With a simple helper method and a before filter, we can accomplish just that:

# app/helpers/application_helper.rb
def link_away(name, options = {}, html_options = nil)
  link_to(name, { :return_uri => url_for(:only_path => true) }.update(options.symbolize_keys), html_options)
end

# app/controllers/application.rb
before_filter :link_return

private

# handles storing return links in the session
def link_return
  if params[:return_uri]
    session[:original_uri] = params[:return_uri]
  end
end

Now in the view, you can write:

<%= link_away "Edit post", :controller => '/admin/posts', :action => 'edit', :id => post %>

And as long as the controller uses redirect_back, the user can click the link, and when they’re done editing, they will come right back to where they clicked the link. This trick is probably the most useful from a usability standpoint, given that nothing annoys a user more than having to manually navigate back to where they were after each change.

I hope you find these techniques useful for writing more user friendly and concise code!

WordPress Upgrade Madness

Tuesday, September 11th, 2007

Recently, I have been becoming increasingly annoyed at the frequency with which WordPress releases updates, most of which are proclaimed to be security updates so that users are encouraged to “upgrade immediately”.

While I am thankful that WordPress remains so on top of security problems, it is rather disconcerting that security flaws are being discovered with such frequency, possibly pointing to deep rooted flaws in the security methods it employs.

I do have one piece of good news however. From what I can tell, v2.2.3 (which was released little more than a month after v2.2.2) does not address any security problems that will affect the majority of users. The only security hole it plugs is the ability of a user (meaning someone who can write actual posts to the blog) to post unfiltered HTML when their preferences are set to prevent it. In other words, unless you allow hackers access to the admin area of your blog, don’t worry about it.

iReview iLife ’08

Friday, August 17th, 2007

Ever since my copy of iLife ’08 arrived this afternoon, I have been attempting to determine whether Steve Jobs was telling the truth as to how “cool” all the new features are.

After several hours of arduous product testing and evaluation, I have come to a difficult decision: you better believe it is!

Ok, seriously, iLife ’08, the release of which was announced by Jobs at an Apple special event on Tuesday, is a very nice upgrade to the entire iLife suite (at to the apps I use). This isn’t intended to be an exhaustive review, so I’ll only touch briefly on each of the iApps, excluding iWeb, which I have never even used, so I don’t consider myself qualified to comment on it.

iPhoto ’08

Let’s face it, iPhoto ’06 was just lousy, especially when compared with the strong competition given to it by Picasa on the PC. However, iPhoto ’08 has significantly reduced or eliminated the number of headaches I encountered while managing my photos.

The first improvement is speed. Scrolling through my photo library (which, albeit is rather small, consisting of only about 700 photos) is lightning quick, with no lag at all.

The “events” features is also an incredible improvement over the “rolls” based system used in iPhoto ’06. They are a much more logical user-friendly way of organizing photos, and the events index (shown below) is a fantastic way of quickly looking through all your photos. Furthermore, the “skimming” feature demonstrated by Jobs in his presentation, where dragging the mouse from left to right across the event thumbnail quickly flips through all its photos, really is as fast and cool as it looks like!

iPhoto events

One final improvement in iPhoto ’08 is to the way photos can be moved between albums/events. In iPhoto ’06, a photo had to be dropped directly onto the title of an album to move it, but now it can be dropped anywhere in the album. This means no more dragging an imported image up past 200 photos just to move it into the proper album.

iMovie ’08

Although iMovie ’08 has been the subject of much controversy, with many people claiming it is even a downgrade from iMovie ’06, I believe it is a great improvement. Honestly, iMovie ’06 never made much sense to me, titles were difficult to use and couldn’t be edited after being applied to a clip (or maybe I just couldn’t figure out how). A simple video taken with my digital camera would have to be “imported” to be used, a process which generally took about as long as the clip itself, and the program seemed generally slow and unstable.

In contrast, iMovie ’08 is extremely intuitive, easy to use, and lightning quick. Its video skimming feature is a joy to use, and is just as fast as in Jobs’ demonstration. Being able to simply select video segments and drag them into the timeline makes creating videos fast and easy. The program’s set of transitions, although small, is adequate and includes all of the most commonly used and professional looking favorites, such as cross fades and fades through black or white. Titles are quick and easy to apply, and can be edited afterwards just as easily.

On the downside, it is true that iMovie ’08 lacks any video effects (besides color correction) and does not allow the volume to be faded up and down inside a clip, although the audio level of each clip as a whole may be adjusted. Themes are also gone, although I personally never used them and won’t exactly miss them.

Rather than considering iMovie ’08 a “downgrade” from ’06, I would prefer to think of it as a “crossgrade”, if that is even a word. Although it does lack some of the editing power of iMovie ’06, it more than compensates for these deficiencies with what it gains in usability and speed.

iDVD ’08

I don’t have much to say about iDVD, besides that it is probably the most routine upgrade in the entire iLife ’08 package. Besides a few performance and usability enhancements, there really isn’t anything to exciting in it, although the new pro-quality encoding is probably exciting to some. Other than that, iDVD remains an incredibly easy way of creating high-quality DVDs quickly and easily. What more could one want?

GarageBand ’08

The iLife ’08 upgrade to garageband doesn’t appear to add anything too spectacular, although the magic garageband is rather fun to play with, even though it may not actually be very useful in composing actual music. It has some minor interface enhancements, and the arrangements feature will probably be useful in some instances, although I don’t know how often bands will simply swap verses around in a song. I am not exactly an expert in using Garageband, so I honestly don’t know how useful any of the new features will really be to those who actually record music.

Conclusion

Overall, iLife ’08 is quite a significant upgrade to the iLife suite, one which I think is well worth purchasing for the improvements in iPhoto alone. Although iMovie is still in its first version and lacks some power features, I believe that over time it will mature into an excellent editor for simple films and home movies, although its usefulness for making more advanced videos is severely limited. The changes to the other members of the iLife bundle are of less significance, although they are still useful in some ways.

But, you ask, should I buy it or not? I would reply with an unequivocal, probably ;). If you disliked iPhoto and iMovie ’06 as much as I did, then definitely yes, go buy the upgrade. But if you are satisfied with those two programs, the upgrades to the rest of the suite most likely aren’t significant enough to warrant immediate adoption.

Updated Ruby Tutorial

Friday, August 17th, 2007

I’ve just updated my Ruby tutorial with a ton of new content. Some of the added sections include:

  • A regular expression (regex) reference
  • An explanation of the rather confusing rules behind block scope
  • An example on the use of the Ruby case statement (similar to the C switch statement)
  • How to write your own attr_accessor method (and understand class_eval in the process)
  • Several new core functions and methods

I don’t know if anyone else is finding my reference helpful, but it has definitely aided me in understanding the intricacies of Ruby.

Fixing div.fieldWithErrors in Ruby on Rails

Saturday, May 5th, 2007

Rails’ form helpers are incredibly handy in quickly writing form code, however their error handling code leaves something to be desired. By default, when a field has errors associated with it, the input is wrapped in a div of class “fieldWithErrors”. Unfortunately, this behavior requires you to explicitly change the div to display inline so it doesn’t make the input appear on the next line after the name of the field. I have also had some trouble getting this setting to work in Safari, although that may just be my problem and not Safari’s.

Fortunately, fixing this annoying little gotcha is as easy as adding a single line to the end of your environment.rb file: (I’ve split it into two lines so it will fit on the page, just remove the line break)

ActionView::Base.field_error_proc = Proc.new { |html_tag, instance|
"<span class=\"fieldWithErrors\">#{html_tag}</span>" }

I know many people have already written about this problem, but I wanted to have my own record of it for easy reference 😉

Windows Vista Ad on AppleInsider

Thursday, May 3rd, 2007

I wonder if microsoft is purposely advertising on Mac websites to try to drum up some converts. Sorry microsoft, I think the road to Mac only goes one way 😉

Windows Vista Add on AppleInsider

The Dangers of Direct Assignment in Rails with User.new(params[:user])

Monday, April 30th, 2007

Although it is used in the vast majority of Ruby on Rails tutorials, putting data from a form directly into an object using a statement such as User.new(params[:user]) can actually be an extreme security risk.

To understand why, it is necessary to first explain how this statement works. Forms generated by Rails’ default form helpers look something like this:

Username: <input type="text" name="user[username]" />
Password: <input type="password" name="user[password]" />

The user[name] format is automatically converted by rails into a hash in the params variable, which would contain the following if this form were submitted:

params[:user] = {
    :username => "Bob"
    :password => "Secret"
}

Since User.new accepts a hash of key/value pairs that will become the initial values of all the attributes of the returned object, User.new(params[:user]) is simply taking the hash of values passed in from the HTML form for the user, and directly setting them in the new object. The simplicity of this operation is also its downfall. For instance, a user could modify your registration form (either using a browser plugin our by downloading it to their computer) to the following:

Username: <input type="text" name="user[username]" />
Password: <input type="password" name="user[password]" />
<input type="hidden" name="user[admin]" value="1" />

If your user model used a boolean attribute called admin to specify whether a user had admin privileges, when the form is submitted your code would unwittingly grant the user admin access. Because params[:user][:admin] was set to 1 in the hash passed in from the form, it is automatically set to 1 in the user object and saved to the database.

The Solution

Fortunately, this security hole is easy to fix using either of two simple statements provided by ActiveRecord in your model code. The first is attr_protected, which can be used thus:

class User < ActiveRecord::Base
    attr_protected :admin
end

This simple statement, which can accept multiple parameters, sets up a blacklist of attributes that cannot be set from the hash passed to User.new, effectively filtering the input and patching the security hole.

The second alternative, attr_accessible, uses a white-listing approach instead. Only those attributes explicitly given to attr_accessible can be set from the hash passed to User.new, any others will be ignored.

class User < ActiveRecord::Base
    attr_accessible :username, :password
end

Which approach you use depends entirely on preference, whether you think you are more likely to forget to protect sensitive attributes or to allow access to non-sensitive ones. Whichever method you choose, protected attributes can always be set by calling their accessor method, such as user.admin = 1.

For more information on this topic, see the Ruby on Rails manual.

A Further Warning on Associations

According to this article, the mass assignment security hole also affects collections and associations, such as a User having many Articles. By specially crafting a form submission, a user could claim any article as their own, simply using something similar to:

<input type="hidden" name="user[article_ids][]" value="5" />

This is because rails automatically creates attribute accessors like article_ids for has_many associations, which accept an array of ids to associate the object with. The form snippet above would add a new id to that array, and give the user ownership/authorship of that article. The author of the above article makes the case that, because of this hole (and other possibly others opened up by associations and other rails magic), it is a better idea to explicitly white-list attributes using attr_accessible, rather than attr_protected. This way, something like article_ids, which most developers don’t know about (myself included), won’t open up your application to exploitation. Ignorance is not always bliss.

Although this methodology is somewhat more in the spirit of Python than Rails, it is undoubtedly the safest. Explicitly defining which variables can be passed in through a form is also the method taken by Formencode, a widely used validation library for Python.

Ruby – A Lightning Tutorial

Saturday, March 31st, 2007

Whenever I’m learning a new programming language, I find it helpful to keep notes on what I learn. Ruby is no exception, except this is the first time I have tried compiling these notes into more of a tutorial.

You can see the first draft of it (or the Alpha version), over here.

Its style is based on the assumption that you can always find out about the practical usage of the language, its classes, functions, and methods, later. Lightning Tutorials (yes, I intend to write more) attempt to teach only the absolute essential parts of the language, its syntax, idioms, features, and gotchas. Because they do not explain anything but the most fundamental parts of the language, they can be very concise. However, you must already be a relatively competent programmer to understand them. I don’t explain what terms such as “instance variables” or “classes” mean, as they are not intended to be an introduction to programming, but rather a quickstart guide for experienced programmers who wish to get up and running on a new language quickly. After all, you can always read the language docs later.