Gavin Morrice

is a web and iOS developer from Edinburgh, Scotland.

more about me ยป

Now running on Blogit: A Ruby on Rails blogging Engine

Over the past few weeks I've been working on a Ruby on Rails gem named blogit and today I've relaunched my own blog (this site) using blogit to handle pretty much everything.

The concept of blogit is simple: Add a blog to your Ruby on Rails application with as little effort as possible! The gem comes with everything you need to get started, and quite a few options which you can set to optimise your setup.

To Install Blogit

Add this to your Gemfile

gem "blogit"

...and run bundle install to install the gem.

Next, run:

# add an initializer to config/initializers with all of the configuration options
$ rails g blogit:install
# This will add the necessary migrations to your app's db/migrate directory
rake blogit:install:migrations
# This will run any pending migrations
rake db:migrate

then add the following to your routes.rb file:

# config/routes.rb
mount Blogit::Engine => "/blog"

... and finally, declare which of your models acts as blogger in your app (usually User).

class User < ActiveRecord::Base

  # This method adds all of the required associations etc.
  blogs

end

Configuration

Running rails g blogit:install will add an initializer file named blogit.rb. In here you can set various configuration options. Here's a quick rundown of the options currently available:

  • :include_comments - Should blogit provide comments too? (defaults to true)
  • :current_blogger_method - The name of the controller method we'll call to return the current blogger. (defaults to :current_user)
  • :blogger_display_name_method - what method do we call on blogger (User) to return their display name? (defaults to :username)
  • :datetime_format - Which DateTime::FORMATS format do we use to display blog and comment publish time (defaults to :short)
  • :posts_per_page - Number of posts to show per page using Kaminari (defaults to 5)
  • :highlight_code_syntax - Should code blocks be highlited using Pygments? (defaults to true)
  • :authentication_method - The name of the before filter we'll call in the controller to authenticate the current user. (defaults to :login_required)
  • :author_edits_only - If set to true, only the user who authored the post may, edit or destroy (defaults to false)
  • :ajax_comments - If set to true, the comments form will POST and DELETE to the comments controller using AJAX calls. (defaults to true)
  • :include_admin_actions - If set to true, the create, edit, update and destroy actions will be included. If set to false, you'll have to set these yourself elsewhere in the app (defaults to true)
  • :include_admin_links - If set to true, links for new posts, editing posts and deleting comments will be available. If set to false, you'll have to set these yourself in the templates. (defaults to true)
  • :default_parser - The default format for parsing the blog content. (defaults to :markdown).
  • :redcarpet_options - When using redcarpet as content parser, this is the options hash for Redcarpet
  • :cache_pages - Should the controllers cache the blog pages as HTML? (defaults to false).

Customisation

The view templates will probably need tweaking to suit your own site. For this reason, I've tried to break the views into as many modular partials as was practical. This means if you want to change only how the header is displayed, you only have to change the _post_head.html.erb. You can nosey around the blogit repository to see how the view templates are broken up.

Still in Beta...

The gem is still in beta while I settle on which configurations and features would suit most people. In the meantime, please feel free to try it out and suggest features you'd like to see.


Writing Rails helper tests/specs using MiniTest::Spec

So MiniTest has been receiving a lot of attention recently as being the testing framework for Ruby. Supporting TestUnit and Rspec syntax it appeals to both camps while also offering a much lighter, faster codebase.

This week I bundled together a gem with a bunch of helper methods and CSS classes that I always seem to re-write across every app that I work in. Since the gem is still pretty basic and subject to change a lot before I settle on a stable version 1 I figured this would be a good project to experiment with MiniTest::Spec.

Moving to MiniTest::Spec

I prefer the Rspec flavour so named and structured my test files like so:

spec/
  - spec_helper.rb
  - dummy # a dummy rails app for testing
  - helpers
  - support # extra files for spec support, more on these in a minute 

Note - Using this structure, you'll also have to update your Rakefile a little:

# Rakefile
Rake::TestTask.new(:spec) do |t|
  t.libs << 'lib'
  t.libs << 'spec'
  t.pattern = 'spec/**/*_spec.rb'
  t.verbose = true
end

... and modify spec_helper.rb to look like this:

# Configure Rails Environment
ENV["RAILS_ENV"] = "test"

require File.expand_path("../dummy/config/environment.rb",  __FILE__)

require "rails/test_help"

require "minitest/rails"

Rails.backtrace_cleaner.remove_silencers!

# Load support files
Dir["#{File.dirname(__FILE__)}/support/**/*.rb"].each { |f| require f }

Creating a dummy class for the specs

Since Rails helpers are modules, we need to define a class to include the module in so we can test the methods. Your helper methods may also call Rails view helper methods so our class should behave just like a normal Rails view.

# spec/support/dummy_class.rb

# define a class that inherits from ActionView::Base
class DummyClass < ActionView::Base
  # include each of your Rails helpers here
  include MyHelper
end

Usually we access the helper through a method provided by rspec-rails named helper. We can recreate that same behaviour by defining this method:

# spec/spec_helper_methods.rb

def helper
  @helper ||= DummyClass.new
end

This method should now be available to all of our specs. We can call it like so:

require "spec_helper"

describe UsersHelper do

  describe :my_method do
    helper.my_method("arg").must_equal "<div class='someclass'>arg</div>"
  end

end

You can run your specs by running rake spec

Testing rails helper methods using MiniTest::Spec

The next problem I ran into was that, using MiniTest's must_equal I had to specify exactly what the output from the view helpers would be.

I find this is very brittle. For example, consider this method:

def bodacious_div(content, klass, id)
  %{<div class="#{klass}" id="#{id}">#{content}</div>}.html_safe
end

And this test:

  describe :bodacious_div do
    it "should return a div with class, id and content" do
      helper.bodacious_div("hello", "my_class", "my_id").must_equal %{<div id="my_id" class="my_class">#{content}</div>}
    end
  end

This test would fail because the ID and class attributes are in the wrong order. In other words, the method is behaving as I'd like it to but the test fails because the syntax isn't exact.

This is too brittle for my liking, I'd rather access a matcher like ActionController's assert_dom_equal.

To add a custom matcher, all we have to do is extend the MiniTest::Matchers module:

# spec/support/mini_test/assertions.rb
module MiniTest::Assertions

  def assert_dom_equal(expected, actual, message = nil)
    expected_dom = HTML::Document.new(expected).root
    actual_dom   = HTML::Document.new(actual).root
    message      = "expected:\n #{actual}\nto equal:\n#{expected}"
    assert_block(message) { expected_dom == actual_dom }
  end

end

This assertion isn't useful in Spec style MiniTests yet though, it's written in the UnitTest assertion syntax. To add it to the MiniTest::Spec expectations, we just need to call the method infect_an_assertion within MiniTest::Expectations

# spec/support/mini_test/expectations.rb

module MiniTest::Expectations

  infect_an_assertion :assert_dom_equal, :must_be_dom_equal, :reverse

end

The first argument refers to the assertion method we should call, the second argument is the name of the expectation we're defining. The reverse argument states whether or not we want to define an opposing expectation (wont_be_dom_equal)

So far, Miniest seems really cool. I'll posting more on this topic as I discover more in the near future.

If you'd like to check out the box_of_tricks gem, you can find it on github: github.com/KatanaCode/box_of_tricks


Manage your application version using per-version

At the moment my team are working on a client application that's gaining more and more public support.

Part of the contract between them and their business clients is regular software updates that are well documented and broadcast amongst the network of paying clients.

To make maintaining the application version easier I bundled together a simple Ruby gem that provides everything required to document versions.

Installation

Installing is straight-forward: add per-version to your Gemfile and then run bundle install.

# Gemfile

gem "per-version"

Once installed, you'll have to run this generator script:

$ rails g version_file

That will stick a file named VERSION in the root directory of your application which looks like this:

VERSION = "0.0.1"

Show current version

So anytime you're working away and you want to know the current working version of your application run rake version:show

$ Current Version: 2.0.1

Release a new version

Once you've added a bunch of awesome features and want to launch a new version.

  1. Make sure your git commits are up to date.
  2. Change VERSION to show the next version number.
  3. git commit -am "Updated version for new release"
  4. rake version:release

Simples!

The gem is still in it's infancy so I'd appreciate all/any feedback

To bring yourself up-to-date on semantic versioning check out Semver: Semantic Versioning