Category Archives: rails

Script Away Your Annoyances – Removing Manual Project Setup Tasks

Don't make me think.
Don’t make me think. Image credit : Beth Tourek.

In recent years I’ve come to deeply appreciate the phrase “don’t make me think.” I will forget how to perform a setup step approximately 7 seconds after I do it, let alone 3 years after I’ve done it (and I know I’m not alone!).

Thus starting to work on an existing project will often give me anxiety—not because I’m worried about learning a new domain or existing system, but because getting the dang thing running can sometimes be the hardest part!

Of course, the best way to mitigate this pain is to codify setup tasks. Why rely on my memory when the computer can do something for me? In other words, don’t make me think. Below are two examples of where I scripted away my annoyances at setting up some projects.

Setting up YouTube Playlists

I worked on a Rails project that integrated with YouTube playlists. Our system created playlists, added, and removed videos from them via the YouTube API. Each system that interacted with YouTube—be it a production instance or local test instance—requires several API tokens in order to interact with YouTube. The tokens are read from the config/system_config.yml file at runtime.

After setting this up once locally, I knew I’d never want to do it by hand again. Who wants to create this file, go to YouTube, create a bunch of playlists with specific names, dig out the tokens, and then paste them back into the file? It’s boring, repetitive, and error prone. Thus I created a Rake task to generate config/system_config.yml on new machines.

I’m not going to paste the implementation here, as I am not here to discuss writing Rake tasks or the YouTube API. The point is that I used a script to replace my memory and opportunity for human error.

Generating Rails’s secrets.yml

Another Rails project I fired up required three generated tokens to be in the config/secrets.yml file. Thankfully the README documented how to generate the secrets—run rake secret, copy the output, and paste into the YAML file. But who wants to do that three times every time you setup the local repository?

In this case, I created another Rake task named generate:secrets that:

  1. Checks for the presence of an existing config/secrets.yml and aborts if it’s already there.
  2. Generates three secrets using the same library rake secret does. The secrets go into a Ruby hash.
  3. The hash is serialized to config/secrets.yml as YAML.

Script Away Your Annoyances

Now I don’t need to think about setup again in either project. As long as I can copy and paste a setup command from a README, I’ve saved my brain cycles for more valuable problems. I hope that this post has inspired you to script away your setup annoyances, whatever they may be!


Other posts in this series:

The post Script Away Your Annoyances – Removing Manual Project Setup Tasks appeared first on Atomic Spin.

Managing Complex Permissions in CanCanCan for Rails

We’re using the CanCanCan authorization gem to control access to resources in our current Rails project. It’s a great way to get started and covers a lot of ground with its basic and extended syntaxes, and it has decent support for adding more complex permissions checks that may not fit into more conventional patterns.

It’s very easy to express rules, like granting users the ability to manage their own User record:

can :manage, User, id: user.id

Indirect resource relationships can be traversed intuitively, say, to restrict WorkSchedule management solely to the owner of a Location:

can :manage, WorkSchedule, work_schedule: { location: { user_id: user.id } }

However, when it came time for us to support dynamic, domain-level permissions for the application, we needed slightly more complex, tailored code to get answers. For example, if we want to know whether a given User is permitted to manage pricing data when setting up Promotions at a given Location, we can figure that out by retrieving the relationship between user and location, and querying that relationship for the proper permission:

relation = LocationUser.where(user: user, location: location)

relation = LocationUser.new if relation.nil?
relation.can_manage_pricing?

This code answers the compound question: “Does this user have a managing relationship with the given Location, and if so, is she permitted to manage pricing?”

Some problems with this code:

  • It’s big, clunky, and repetitive. This is shorter, but not better:
    Manager.where(user: user, location: location) || Manager.new).can_manage_pricing?
  • It exposes details unnecessarily: users and locations are linked via a Manager class, how to find Managers properly in the database, and that permissions are accessed directly on the Manager objects.
  • Requires careful reading to determine the intent and function.

Contrast with the following equivalent code:

user.managing(promotion.location).can_manage_pricing?

This code is concise and clear: “Is the user allowed to manage pricing at the promotion’s location?” We’re also decoupled from the details of the LocationUser relationship.

Extend the User model by implementing the #managing method:

class User < ActiveRecord::Base

def managing(location)
managed_location(location) or Manager.new
end
# Helper method:
def managed_location(location)
Manager.where(user: self, location: location).first
end
end

Leverage #managing in your Ability file when expressing complex permissions that don’t fit the mold of straightforward user-resource access control:

class Ability

include CanCan::Ability
def initialize(user)
...
can [:show,:update], StoreHours do |store_hours|
currently = user.managing(store_hours.location)
currently.can_open_store? or currently.can_set_schedules?
end
can :manage, Promotion do |promotion|
user.managing(promotion.location).can_manage_pricing?
end
...
end
end

Though we first used this technique to improve the code in our Ability class, the ideas and code are not bound to CanCanCan, and stand alone as a neat little trick to improve our code in any context.

The post Managing Complex Permissions in CanCanCan for Rails appeared first on Atomic Spin.

Deploying from Git with Capistrano

Justin and I provide operational support to the SME Toolkit project, an education portal for small to medium sized enterprises in developing countries sponsored by the IFC (which is the private sector development branch of the World Bank Group).

Recently, the source code for the Rails-based web application was migrated from Subversion to Git. This also changed how we deploy the application. Previously, we deployed a snapshot of code from a tarball placed on a bastion server. With a few changes to our Capistrano configuration, we are able to deploy directly from the source code repository.

Basic Deployment

First we switch from

set :scm, :none
to
set :scm, :git

and from

set :repository, "/path/to/unzipped/snapshot"
to
set :repository, "git@server:project/repository.git"

Then we’ll also want to use set :deploy_via, :remote_cache so that we’ll only need to pull down the commits since the last deploy each time rather than cloning the repository and pulling down the entire history every time.

Now we can deploy using a command like:
cap stage_name deploy -S branch=master

Deploying a Specific Tagged Version

But what if we want to deploy a specific tagged version? We should be able to use cap stage_name deploy -S tag=3.2.1.

Unfortunately, it’s the ‘branch’ variable that’s used as a ref by Capistrano internally to resolve the revision deployed. This is not well documented, but see: lib/capistrano/recipes/deploy/scm/base.rb:77, and lib/capistrano/recipes/deploy/scm/git.rb:119, and lib/capistrano/recipes/deploy.rb:L29.

The simplest way to address this is just to set :branch, tag in config/deploy.rb.
In order to run other tasks without specifying a tag however, we should probably qualify that with a conditional: set :branch, tag if exists?(:tag).

Updating the Version Number

There’s one last thing to be updated: the version number. Before, the developers would populate the REVISION file with a version number when creating a release tarball. Now the REVISION file is populated by Capistrano, with the SHA of the commit being deployed.

If we substitute a new file, say BUILD_VERSION for REVISION in environment.rb, then we can again control of the version number displayed in various places throughout the application. Rather than a long seemingly meaningless string of letters and numbers, we’d like to include the date the code was deployed and the semantic version number of the code.

We can do this with a small Capistrano task like:

  task :build_version, :except => { :no_release => true } do
    deploy_date = Time.now.strftime('%F')
    build_version = "#{deploy_date} #{tag}.build+#{current_revision}"
    put(build_version,"#{current_release}/BUILD_VERSION")
  end

If we put this task in the deploy namespace, we can ensure that it’s run at the end of each deployment with something like: after "deploy:create_symlink", "deploy:build_version"

Now when we deploy, the date and the tag are prepended to the SHA for a much more meaningful build version.

The post Deploying from Git with Capistrano appeared first on Atomic Spin.

Beyond Bundler: A Configuration Management Starter Kit

Configuration management or “infrastructure as code” can provide a common language for application developers and operations specialists alike to describe the infrastructure requirements of an application. By capturing these requirements in code, bootstrapping becomes a repeatable process, and insights from operations teams supporting the application in a production environment can be fed back to the developers in a virtuous cycle.

As an example of what this might look like with some current tools, I’ve created a starter kit for using vagrant, veewee, and a bit of puppet to automate the building of virtualized infrastructure for a Rails 3 application. The end result is a VirtualBox virtual machine described in code (from a Veewee basebox definition of the basic virtual hardware to a Puppet manifests describing the necessary packages and bootstrapping). This means that down the road, an environment in which your application will run can be repeatedly built and all of the steps of that process are both visible and modifiable, with changes captured in source control.

Find it on GitHub, here.

There are a few things I haven’t finished wiring together as of this writing, but it should be enough to see how the main pieces fit together.

The project makes as few assumptions as possible about your environment. It assumes that you have a recent version of VirtualBox installed, RVM installed, and ruby-1.9.3-p125 installed via RVM – from there the project rvmrc and bundler should take care of the remaining dependencies.

To run it (build a new VM from scratch and deploy your app to it), you’ll want to run the following commands:
vagrant basebox build demo-centos-box
vagrant basebox validate demo-centos-box
vagrant basebox export demo-centos-box
vagrant up
cap environment:vagrant deploy:setup
cap environment:vagrant deploy

As of this writing, I haven’t added the hooks to actually launch the application server, but you can start WEBBrick by hand like so:
vagrant ssh
…and then from within the VM:
cd sites/demo-app/current && RAILS_ENV=production bundle exec rails s

Then, in your browser visit 33.33.33.10:3000. Tada!

This was a weekend project, and it’s likely that I’ve overlooked some things, but I plan to continue honing it. Let me know in the comments (or in pull requests) what’s still broken. One of the major motivations of this approach is getting past the issue of “works for me” – so if it doesn’t work for you, I want to know! Thanks.

The post Beyond Bundler: A Configuration Management Starter Kit appeared first on Atomic Spin.