Nick Hammond

Software Developer, Cyclist, & Traveler.

Setting up an Octopress/Jekyll blog in your Rails application

In little feedback, product, rails

Update: A much simpler way

For Little Feedback I wanted to have a blog to release new features on and post other updates to. It's a Rails application and I also wanted it to reside on the same top-level domain(www.littlefeedback.com/blog vs. blog.littlefeedback.com). There's a couple routes that come to mind for doing this.

  1. Setup Nginx/Apache rules to proxy requests to /blog to PHP and use WordPress
  2. Setup a mostly static blogging solution and link the projects via git

Option #1 won't really work for my setup since the Rails application is hosted on Heroku right now. I could setup a custom build pack with PHP and get that going possibly but it just doesn't really seem worth it.

Option #2 is a great fit as I can use Octopress which is also Rack based. I really enjoy Octopress the more I use it so I decided to go this route for Little Feedback.

First, let's get our Rails app setup. We'll create a project directory so that both the Rails application and blog can sit in the same directory.


$ mkdir ~/src/little-feedback
$ cd ~/src/little-feedback
$ rails new little-feedback

Now that we have the Rails application setup, let's go ahead and get our blog setup. For the latest install steps, check the Octopress setup guide. Octopress requires you have at least Ruby 1.9.3 installed, utilize rbenv to install if needed.


$ cd ~/src/little-feedback
$ git clone git://github.com/imathis/octopress.git blog
$ cd blog
$ bundle install

Since we'll be hosting this on Heroku we want to remove the public directory from .gitignore so that it gets committed properly. Your .gitignore file should have 'public' commented out or just completely removed.


.bundle
.DS_Store
.sass-cache
.gist-cache
.pygments-cache
_deploy
# public
sass.old
source.old
source/_stash
source/stylesheets/screen.css
vendor
node_modules
Gemfile.lock

Just to get things going with the blog, we'll install the default theme and generate a 'Hello World' post as well.


$ rake install
$ rake new_post['Hello World']
$ rake generate

The rake generate command is what outputs the static site to the public/ directory. We'll go ahead and commit what we have with the blog so that we have something to use as a submodule for within the Rails application. In order to deploy with Heroku you'll need the blog to be accessible via git submodules so go ahead and push it to a private or public repository somewhere. If pushing to a private repository and you're using Heroku then you'll need an API key to embed in the origin URL.


$ git add .
$ git commit -m "Setting up the first post"
$ git remote add origin git@github.com:nickhammond/lf-blog.git
$ git push -u origin master

Just to ensure the blog is functioning on it's own properly, startup a server and preview it in your browser.


$ rackup

You should see the default Octopress template and then a link to the first post that we created. If not, ensure that there's files in the public/ directory within the blog.

One last thing we'll do with the blog is create an executable Ruby file to run the blog from within our Rails application. We'll make some slight modifications to the default config.ru file and store it as run.rb within our blog application.

The only changes to be made are renaming the class to just Blog instead of SinatraStaticServer and then removing the run call at the very end of the file.


require 'bundler/setup'
require 'sinatra/base'

# The project root directory
$root = ::File.dirname(__FILE__)

class Blog < Sinatra::Base

  get(/.+/) do
    send_sinatra_file(request.path) {404}
  end

  not_found do
    send_file(File.join(File.dirname(__FILE__), 'public', '404.html'), {:status => 404})
  end

  def send_sinatra_file(path, &missing_file_block)
    file_path = File.join(File.dirname(__FILE__), 'public',  path)
    file_path = File.join(file_path, 'index.html') unless file_path =~ /\.[a-z]+$/i
    File.exist?(file_path) ? send_file(file_path) : missing_file_block.call
  end

end


$ git add . && git commit -m "Add run.rb to be used with Rack later on"

Now that we have the blog setup properly, let's go ahead and get it running within our Rails application. We'll add the blog repository as a submodule within our Rails application first and then we'll map things up properly with Rack.


$ cd ~/src/little-feedback/little-feedback
$ git submodule add git@github.com:nickhammond/lf-blog.git blog
$ git add .
$ git commit -m "Add blog submodule"

Our blog repository is now linked as a git submodule within our Rails application. This gives the benefit of not having to worry about dealing with updating the blog if you don't need to separate from the Rails application. Whenever you need to update the blog, you'll just need to do a git pull and commit within the blog directory.

Now we can go ahead and map things up in our Rails application with Rack's map function. Open up your Rails application in your favorite text editor. Octopress runs off a very simple rackup file which just requires Sinatra, this is a dependency that you'll have to define in your Rails application's Gemfile. Unfortunately this seems a bit hackish but Sinatra is a small requirement and being able to host the blog within the Rails application is enough of a win.

Update your Gemfile in your Rails application to match the Sinatra requirement defined within your version of Octopress.


group :blog do
  gem 'sinatra', '~> 1.4.2'
end

Once you've done that run bundle install to get everything setup in your Rails application. Now we'll modify the config.ru file within our Rails application to point to the proper rack applications based on the URL.


# This file is used by Rack-based servers to start the application.

require ::File.expand_path('../config/environment',  __FILE__)
require './blog/run' # Require the run.rb file that we created earlier which has the Rack setup for the blog

map '/' do # By default we want everything to hit our Rails application
  run LittleFeedback::Application
end

map '/blog' do # Anything at blog/ and beyond will then hit the blog
  run Blog
end

Run rails s and you should see your Rails application rendering on all the routes you've setup and blog/ now loads your Octopress blog.

P.S. We should keep in touch, subscribe below.