Generating Static Pages with Rails

by

When working on Filedart we wanted some statically served pages, but to use our site template(s) to have them fit the look and feel. Updating our site’s assets (javascript, css, images, etc) should be easy to update in our static pages as well. Here is a brief overview of how I made this happen.

The approach I took to achieve this was to create a controller (I called it static)

$ rails g controller static page1 page2 page3 ...

Then I added some routes for development only:
config/routes.rb

  if Rails.env.development?
    get "static/page1"
    get "static/page2"
    get "static/page3"
  end

Then I wrote a rake task to generate the static pages:
lib/tasks/app.rake:

namespace :app do
	desc "Generate static pages"
	task static: [:my_pages]

	desc "Generates static pages"
	task my_pages: :environment do
		pages = {
			'static/page1' => 'page1.html',
			'static/page2' => 'page2.html',
			'static/page3' => 'page3.html'
		}
		app = ActionDispatch::Integration::Session.new(Rails.application)

		pages.each do |route, output|
			puts "Generating #{output}..."
			outpath = File.join ([Rails.root, 'public', output])
			resp = app.get(route)
			if resp == 200
				File.delete(outpath) unless not File.exists?(outpath)
				File.open(outpath, 'w') do |f|
					f.write(app.response.body)
				end
			else
				puts "Error generating #{output}!"
			end
		end
	end
end

Once that was in place, regenerating our static pages is as simple as running:

$ rake app:static

How it works

This works by using the integration testing features of rails to programmatically send requests to a controller, then writing the response to a string. The original static file is deleted, the request is generated, and the response is written to the destination file in public/.

Caveats

The static pages are only generated manually, so make sure you run the rake task when you want new pages built. This could be fixed by adding a capistrano task to run the generation on deploy (and removing the generated pages from vcs). Also be careful if you use things like request.host as you’ll get www.example.com or localhost.

We use this technique for some of our error pages, but also things that don’t change often.

Leave a Reply

Your email address will not be published. Required fields are marked *