Showing posts with label rails. Show all posts
Showing posts with label rails. Show all posts

Mar 25, 2008

Before Filtering HTTP Method Types

Previously I wrote the post 'Method Not Allowed' which is about how I decided to handle unsupported HTTP request method types in my actions. Today I realized I should DRY up my code and put this logic into a before filter.

Mar 23, 2008

Bzr to Git

I think it's safe to say that the Rails community has decided git is the distributed revision control tool of choice. Unfortunately for me I've been using bzr for the last year or so. Lucky for me it's easy migrate from bzr to git using svn as an intermediary.

svnadmin create --fs-type fsfs /path/to/svn/project
cd /path/to/bzr/project
bzr svn-push /path/to/svn/project/trunk
git-svn clone -T /path/to/svn/project/trunk /path/to/git/project

Feb 24, 2008

Marketing Open Source

Zed Shaw gives a talk about Mongrel where he touches heavily on how to market an Open Source project. It's worth watching if these things interest you at all, at the very least you'll learn what yak shaving is.

http://www.infoq.com/presentations/zed-shaw-mongrel-loc-economics

Feb 22, 2008

Method Not Allowed

Quite a bit of my old code just redirects when an action gets a request with an unsupported method, for example; 'get' requests to 'destroy' actions. While my old approach prevented anything bad from happening it always seemed wrong. It also made maintaining my tests a tiny bit more complicated because each seemed to have a different location they redirected to.

So I decided to clean up the code in my current project today. The obvious choice was to render an error template and return the proper status code.


# file: app/controllers/parts_controller.rb
def destroy
unless request.delete?
render :layout => false, :template => "errors/405", :status => 405
return
end
begin
Part.find(params[:id]).destroy
flash.now[:success] = "The part has been successfully deleted."
rescue
flash[:failure] = "Unable to delete part."
end
end
This also simplified my tests.

# file: test/functional/parts_controller_test.rb
def test_destroy_get
get :destroy
assert_response 405
assert_template("errors/405")
end

Feb 1, 2008

My Apache Setup

I've been using Apache2 with mod_fcgid for quite a while because it's good enough. I use it primarily because it's really simple to administer and I'm hosting internal business applications with very little load on them. Here's my setup...

Installation is really straight forward

$> sudo apt-get install apache2 libapache2-mod-fcgid
$> a2enmod fcgid


default config
# serve everything from /var/www/ and use /var/www/default as the document root

ServerAdmin webmaster@hostname

# setup logs
ErrorLog /var/log/apache2/error.log
CustomLog /var/log/apache2/access.log combined
LogLevel warn\

# limit the amount of info about server
ServerSignature Off

# default permissions to all files
<Directory />
Options FollowSymLinks
AllowOverride None
</Directory>p;

# setup document root and permissions
DocumentRoot /var/www/default
<Directory /var/www/default>
Options +FollowSymLinks +MultiViews
AllowOverride None
Order allow,deny
allow from all
</Directory>

# define environment for fcgid processes
DefaultInitEnv PATH "/opt/ruby/bin"
DefaultInitEnv RAILS_ENV "production"


per application config
# run the app from /var/www/appname and serve it aliased as http://hostname/appname

Alias /appname "/var/www/appname/current/public"
<Directory /var/www/appname/current/public/>

Options -Indexes +MultiViews +FollowSymLinks +ExecCGI
AllowOverride None
Order deny,allow
Allow from all

RewriteEngine On

# provide support for cap deploy:web:disable
RewriteCond /var/www/appname/current/public/system/maintenance.html -f
RewriteCond %{SCRIPT_FILENAME} !maintenance.html
RewriteRule ^.*$ /appname/system/maintenance.html [L]

# standard rails rewrite with support for alias directory
RewriteBase /appname
RewriteRule ^$ index.html [QSA]
RewriteRule ^([^.]+)$ $1.html [QSA]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^(.*)$ dispatch.fcgi [QSA,L]

# define error documents
ErrorDocument 500 500.html
</Directory>

Jan 18, 2008

Obfuscating IDs in URLs with Rails

There are a number of valid reasons to obfuscate IDs in URLs but it's not a replacement for authentication!

My approach to this problem is to allow the database to assign a normal serial ID, which means I don't have to maintain any extra state or use special database features. Then after it's created I save the obfuscated value of the id which I can use on later lookups.

I use Knuth's integer hash because it ensures there will be no collisions and the full range of values will be used.

In this example I'm using a signed 32 bit integer for the hashed_id because it's supported by all common Rails databases. You could however adjust MAXID to any number of bits you want but then you may have to deal with storage and conversion issues.

Model:

class Part < ActiveRecord::Base
PRIME = 2654435761
MAXID = 2**31-1
def after_create
self.hashed_id = (self.id * PRIME & MAXID)
self.save
end
end

Controller:
class PartsController < ApplicationController
def show
@part = Part.find_by_hashed_id(params[:id])
end
end

Dec 23, 2007

A Caching Current User Method Call

Quite a while back when I first seen RailsCast Episode #1, I implemented a current_user method exactly as it's presented in the video. The problem with this method is that it assumes that the user_id session variable is always set, obviously this is not always the case.

This snippet addresses the problem

class ApplicationController < ActionController::Base
def current_user
session[:user_id] ? @current_user ||= User.find(session[:user_id]) : nil
end
end