Wednesday, February 27, 2008

How to Disable Asset Timestamps in Rails

By default, Rails appends a timestamp parameter to asset urls to aid in cache management. If you need to disable this, simply add the following line to your config/environment.rb

ENV['RAILS_ASSET_ID'] = ''

Tuesday, February 26, 2008

Advanced puts Syntax in Ruby

The "puts" command can be used with sprintf syntax using the percent (%) sign as follows:

puts "ABC %2.2f" % 3.567
=> "ABC 3.57
"

puts "ABC %2.2f DEF %5s" % [3.567, "abcd"]
=>
"ABC 3.57 DEF abcd"



Saturday, February 16, 2008

Load Balance Rails Mongrel Clusters With Apache

A simple solution for load balancing a Ruby on Rails Mongrel cluster with an Apache front end is to use the randomizing feature in Apache module mod_apache’s rewrite map feature. Say, for instance, you have 3 Mongrel servers, running on ports 4000 to 4002 on localhost. First create a file map.txt containing these numbers:

ports 4000|4001|4002


Then ensure the following directives are present inside the VirtualHost stanza in your Apache configuration:

ProxyRequests Off
ProxyPassReverse / http://localhost:4000/
ProxyPassReverse / http://localhost:4001/
ProxyPassReverse / http://localhost:4002/
ProxyPreserveHost On
RewriteEngine On
RewriteMap servers rnd:/path/to/your/map.txt
RewriteRule ^/(images|stylesheets|javascripts)/?(.*) $0 [L]
RewriteRule ^/(.*)$ http://localhost:${servers:ports}/$1 [P,L]

Restart Apache, and that is it.

I have had great success using both the Pound load balancer, and Nginx, which I suggest highly, but Apache does a great job when necessary.

Wednesday, February 13, 2008

Using :db_file with attachment_fu

The README for attachment_fu says that accessing data using the :db_file backend is outside the scope of the document. Well here is my take on it. You will also need the "mimetype_fu" plugin. Follow the instructions with attachment_fu as usual, and do the following.

Assuming that your attachment model is called "Asset" add the following line to "config/routes.rb":
map.asset_data '/asset/:id', :controller => 'assets', :action => 'show'

Create an AssetController containing at least the following:
(The thumbnail of the original image is found if necessary, and mimetype_fu is used to determine the mime-type sent to the browser)
class AssetsController < ApplicationController
def show
asset = Asset.find(params[:id])
if params[:thumbnail]
data = asset.thumbnails.find_by_thumbnail(params[:thumbnail])
end
data ||= asset
send_data (data.db_file.data,
:filename => data.filename,
:type => File.mime_type?(data.filename),
:disposition => 'inline')
end
end

Add this method to app/helpers/application_helper.rb
  def assetpath(asset,thumb=nil)
"#{asset_data_url(:id => asset.id)}#{thumb.nil? ? '' : "?thumbnail=#{thumb.to_s}"}"
end


So now you may use the helper in your views (i.e.):
<%= image_tag(assetpath(asset_model_instance)) %>
<%= image_tag(assetpath(asset_model_instance,:thumb)) %>