Saturday, 29 March 2014

Rails Templates

We've all been there, the start of a new shiny project, we hit rails new and, well, we follow the same motions we do every time we create a new Rails app.

We install devise, or maybe minitest, then follow it up with shoulda matchers, bootstrap and more. We have our little preferred starting stack, but we waste hours reimplementing it in every new project that comes our way.

Rails gives us the capacity to create our own templates which will dictate our starting stack as well as enable us to get some of the tedious after bundle setups out the way. To start with, create a template file templater.rb

Once we have that out the way let's go and automate adding some gems to our gemfile, now we can do this in a few different ways, the first being:

gem "mysql"
# We can also give it the usual gem options like so:
gem "technoweenie-restful-authentication", :lib => "restful-authentication", :source => "http://gems.github.com/"
gem "rails", "3.0", :git => "git://github.com/rails/rails"

Another option is to plug your gems into a group:

gem_group :development, :test do
  gem "rspec-rails"
end

Finally we can start leveraging Thor to install our gems like so:

inside app_name do
  run 'bundle install'
end

Once our gems are installed the next steps in setting up our application usually involve a bunch of generators, no worries, we can handle this as well

generate 'devise:install'

generate 'cancan:ability'
We can also do some really nice things around file manipulation, for instance we use the bootstrap-sass gem and need to add to our application.css.scss the bootstrap requirements.
append_file 'app/assets/stylesheets/application.css.scss' , <<-EOF
 @import "bootstrap";
 @import "bootstrap/theme";
EOF 

Because the rails template api utilises Thor it means we have access to all of the usual suspects like remove_file, copy_file, but also really useful methods like inject_into_file

inject_into_file 'app/assets/javascripts/application.js', "\n//= require bootstrap\n", after: "//= require jquery_ujs"

This gives us the capacity to inject specific content within our files using only a regex match which is really useful especially for gems that will require adjustments to our spec_helper.rb file like the devise test helpers for instance.

We can also add some logic to our templates by using either the yes? method like so:

generate 'devise:views' if yes?("Generate Devise Views?")

Which will prompt the user to make a decision on whether or not we want to generate devise views for this particular project.

Additionally we can use the ask method to add some more complex logic to perhaps determine the extra individual capistrano environments we want to create:

environments = ask("What environments do you want in addition to production?, please separate with commas")

environments = environments.split(",")

environments.each do |env|
  create_file "config/deploy/#{env}.rb"
end

All these methods really mean we can not only have a well maintained template file all ready to use but really automate our entire new application process.

You can use a template to keep and maintain template files, eg: overriding the default view generators and replace them with haml templates. However, this does mean that you will no longer be able to use the one file for the template, which reduces your ability to be able to just call it from your github repo. It is possible in some cases to just use a string to store the file contents and create the file with them this way, but this has issues with maintainability over the long term.

Rails templates are a very easy way to minimise your ramp up time during the initial stages of a project, particularly if you are using the same stack over and over again.

No comments:

Post a Comment