A rubyist stranded on Martha’s Vineyard

How to Upgrade to Strong Parameters in Rails

December 10, 2014

This article was originally published in the blog of ActBlue Technical Services.

How to Upgrade to Strong Parameters in Rails

In the previous blog post, using a series of tests, we described how strong parameters work. In this post we detail the steps we followed to upgrade our main application in ActBlue.

Starting Point

To help with the process Rails provides the protected_attributes gem. This allows you to run your app on 4.1 without having to make any changes related to mass-assignment protection. The gem brings backwards compatibility by implementing attr_accessible, attr_protected and other methods.

Add these lines to your Gemfile, run bundle install and make all your tests pass (you have tests, right?)

gem 'rails', '~> 4.1'
gem 'protected_attributes'

There are other incompatibilities you will have to resolve, but this post is about strong parameters and we are assuming your tests run green at this point.

Mixing Both

It is unlikely you can make all the changes in a single release and therefore you will want to have both protected attributes and strong parameters working at the same time. So the next step is to add this line to Gemfile and run bundle install:

gem 'strong_parameters'

In every model you want to upgrade add this line to include the ForbiddenAttributesProtection module. This is the way to indicate Rails which models are using the new mechanism, for example:

class Book < ActiveRecord::Base
  include ActiveModel::ForbiddenAttributesProtection

In the model also remove all calls to attr_accessible and attr_protected, for example:

attr_accessible :isbn, :title
attr_protected :price

In the corresponding controller it is useful to create a private method that whitelists its parameters, for instance:

def book_params
  params.require(:book).permit(:isbn, :title)

For simple models and controllers it is going to be similar to this, but for more complex cases you can check our previous blog post or the documentation.

Dropping Protected Attributes

When you think you have upgraded all your models and controllers and feel you are ready to pull the plug on the old protected attributes, these are the steps we recommend:

Remove these 2 lines from Gemfile and run bundle install.

gem 'protected_attributes'
gem 'strong_parameters'

In Rails 4 the default is strong parameters, so there is no need to include the gem.

Remove the configuration for protected_attributes, this means removing from config/application.rb:

config.active_record.whitelist_attributes = false

Remove from config/environments/test.rb:

config.active_record.mass_assignment_sanitizer = :logger

Remove any include ActiveModel::ForbiddenAttributesProtection from models, added in the previous step.

In the default configuration of strong parameters, when you whitelist only a subset of the params passed to the controller, instead of raising an exception, Rails is going to generate a notification. You can see a test illustrating this.

It is better instead to always raise an exception. This is done by adding this line to config/environments/test.rb:

config.action_controller.action_on_unpermitted_parameters = :raise

Now run all your tests. If you have a large application and you are getting errors you do not understand or the code is not behaving the way you expect, check our previous blog post Understanding Strong Parameters, this is the part where this information is most useful.

Final Step

When you are done with the tests you can remove the line from config/environments/test.rb:

config.action_controller.action_on_unpermitted_parameters = :raise

The default value in Rails is to generate a notification in test and development environments, and ignore otherwise.

You are done! We hope the 2 articles helped you to make the transition smoother.

Understanding Strong Parameters in Rails 4

November 14, 2014

This article was originally published in the blog of ActBlue Technical Services.

Understanding Strong Parameters in Rails 4

Earlier this year, in ActBlue, we completed the upgrade of our main application from Rails 3.2 to 4.1. The last step in the process was incorporating strong parameters.

Several of our models are simple and we did not have a problem following the documentation, RailsCast and other articles. But a good number of models (and its controllers) are more complex or were using our own protection mechanism, and we were dragging our feet on them.

The main issue was that we did not really understand how strong parameters worked. Correction: I did not understand, which is the big realization that took place when I had to explain what I was doing to the rest of the team. The part that is missing from all the articles I read is what happens when you do not use strong parameters in the correct way. For this reason, the best solution was a series of tests, which is what we present here.

In order to minimize the dependencies, the tests were written in MiniTest::Spec, and the only additional gem required is mocha. Ruby version is 2.1.4 and Rails 4.1.6.

The full list of tests can be found in this github repo, following we go through the most important ones:

If you change the version of Rails in your Gemfile from 3.2 to 4.1, without making any other changes, parameters in the controllers will be passed untouched to methods new and update_attributes on your models, raising this error:

describe 'completely unhandled params (i.e. no call to permit)' do
  before do
    @hash = { 'title' => 'Test', 'body' => 'test body' }
    @params = ActionController::Parameters.new @hash
  it 'should raise error' do
    -> { Article.new @params }.must_raise ActiveModel::ForbiddenAttributesError

The next step is to start whitelisting some parameters by calling the permit method. For sure, you will miss some, which will trigger this notification:

describe 'permit some elements from params and miss others' do
  before do
    @params = ActionController::Parameters.new @hash
  it 'should log non-permitted attributes' do
      with('unpermitted_parameters.action_controller', keys: ['body']).
    @params.permit(:title).must_equal 'title' => 'Test'

In Rails 3.2 when you create or update objects on a model and include attributes that do not exist they willl just be ignored. Version 4.1 raises an exception, which is a better way of handling it, no one would ever rely on the fact they are ignored, right?

describe 'call permit on attributes that do not exist in the model' do
  before do
    params = ActionController::Parameters.new @hash.
      merge('non_attr' => 'test')
    @permitted_params = params.permit(:title, :non_attr)
  it 'ActiveRecord should raise exception on non-attribute' do
    ex = -> { Article.new @permitted_params }.
      must_raise ActiveRecord::UnknownAttributeError
    ex.message.must_equal 'unknown attribute: non_attr'

The require method is useful when you want to make sure that certain parameter is present, if not it will raise an exception:

describe 'require something that is not present in params' do
  before do
    hash = {
      'article_attributes' => {'title' => 'Test', 'body' =>'test body'},
      'other_attributes' => {'amount' => '12', 'color' => 'blue' }
    @params = ActionController::Parameters.new hash
  it 'should raise exception' do
    ex = -> { @params.require(:category_attributes) }.
      must_raise ActionController::ParameterMissing
    ex.message.must_equal 'param is missing or the value is empty: ' +

Note that if there are other keys in the params hash they will be removed:

it 'should filter out everything but the required key' do
  @params.require(:article_attributes).must_equal 'title' => 'Test',
                                                  'body' =>'test body'

Additionally, requiring without calling permit will raise an exception:

it 'should raise error if we try to use it as is (without permit)' do
  -> { Article.new @params.require(:article_attributes) }.
    must_raise ActiveModel::ForbiddenAttributesError

Finally the “standard” way to use strong parameters, this is the form that you will see presented in other blog posts.

describe 'proper use' do
  before do
    @attributes = @params.require(:article_attributes).
      permit(:title, :body)
  it 'should be fine if we use require and permit combined' do
    @article = Article.new @attributes
    @article.title.must_equal 'Test'
    @article.body.must_equal 'test body'

Nested attributes on a model that has a one-to-one relation. In the example a comment belongs_to an article:

it 'shows how to permit nested params' do
  attributes = @params.
                  permit(:author, article_attributes: [:id, :title,
  attributes.must_equal "author" => "John Smith",
                        "article_attributes" => {
                          "title" => "Test",
                          "body" => "test body"}
  comment = Comment.new attributes
  comment.author.must_equal 'John Smith'
  comment.article.title.must_equal 'Test'
  comment.article.body.must_equal 'test body'

Nested attributes on a model with a one-to-many relation. The example shows an article that has_many comments. Note that the controller will receive an extra level of keys, the integers 0, 1, etc. Rails internally ignores these numbers so we don't have to include them in the call to permit:

describe 'nested attributes on articles (which has_many comments)' do
  before do
    @hash = {
      "article" => {
        "title" => "Test",
        "body" => "test body",
        "comments_attributes" => {
          '0'=>{"author" => "John", "content" => "great"},
          '1'=>{"author" => "Mary", "content" => "awful"}
    @params = ActionController::Parameters.new @hash
  it 'shows how to permit nested parameters' do
    attributes = @params.
      permit(:title, comments_attributes: [:author,
        must_equal @hash['article']['comments_attributes']

The repo has additional cases and also shows how the code looks when you are doing updates.

In the next blog post will show the specific steps we took during the upgrade of our application.

Introduction to Contributing to Open Source

September 02, 2013

This is the mini workshop I will be giving today at Project Night, the event organized by Boston Ruby Group and hosted by thoughtbot every first Tuesday of the month.

Many people starting in software development feel they would like to contribute to open source but they do not know how to do it. In this class we will review the basic workflow to make a change to an open source project. We will learn how to navigate github, how to open a ticket and how to send a pull request, the transaction by which we implement the update. The interaction that takes place between contributors and project owners will also be covered.

The open source project we will be working on is the RailsBridge Boston website, of which I am an owner. This way students will be able to have a real world experience with confidence, without fear of making mistakes.


You must have a GH account with SSH keys. If you do not have it, follow these steps:


This is a diagram of the workflow we will be following during the class.

github flow


a project in git/github, i.e. a bunch of files
ticket, conversation about bug, feature, idea
snapshot of a repository
Pull request
set of commits


  • Login to your github account.

  • Search for railsbridge boston, click on users and select that entry.

  • Select the repo railsbridge-boston.

  • Read the README.

  • Visit the production version of this website: http://railsbridgeboston.org/.

  • Click through this sequence in the top menu: Curriculum > Friday > Installfest > Install Ruby on Windows. This is the page we will be modifying.

  • Go back to github, find the list of commits and look for one from 7/2/13 called “Fixed typo on homepage”.

  • Click on this commit and check its content. It was done by a student of this same mini workshop two months ago. Note that although a commit is a snapshot of all the files we only have to handle the differences.

  • Check other commits on 7/2 and 7/6, note the granularity of the updates.

  • Make a fork of this repo. Check the diagram above to understand what happens when you perform this operation.

  • Make sure you are on the github page of your own repo and not railsbridge-boston.

  • Clone this repo, in the command line:

git clone git@github.com:myuser/railsbridge-boston.git
cd railsbridge-boston
  • Because this might take a few minutes, we will start doing something else. Leave this tab open in your browser, this is the project we are working on.

  • Go to the github page for the railsbridge-boston user and select the repo railsbridge-virtual-machine. This page contains the instructions we want to use to install a Windows machine, i.e. this is what we want to use instead of RailsInstaller in the next RBB workshop.

  • Create an issue saying that the instructions should be modified.

  • The project owner will show on the projector how the issue you just filed looks from his/her side and he/she will submit a response.

  • Review the thread of the conversation in your computer.

  • Go back to the git clone you left running.

  • Find the file in your laptop that contains the page you need to modify. This can be done with the grep command:

grep -r 'Installing Ruby and Rails on Windows is easy thanks to' *
  • Open your text editor and make the changes.

  • Before sending your update to github, review the changes you just made. Use these 2 commands:

git status
git diff

Push the changes to github. Check the diagram to understand what is happening.

git add .
git commit -m 'Use Vagrant instead of RailsInstaller'
git push origin master
  • Go to the page with your repo on github and make a pull request.

  • Watch the side of the project owner, how she makes a comment on the PR and also a comment under a specific line of code.

  • Experiment with the interaction between contributors and owners.

  • Watch how the project owner merges the PR and deploys into production.

  • Check that the update is visible in the production website.

How to install Doom on the Raspberry Pi

May 20, 2013
Raspberry Pi running Doom II

My kids were intrigued by what I was doing as I followed this SparkFun tutorial on how to install Doom on the Raspberry Pi, they were making questions and seem so motivated that I asked if they wanted to do it themselves, they accepted right away.

Although the instructions are good, they are a little outdated and some steps can be simplified. I decided to improve them and post them here.

List of hardware

  • Raspberry Pi model B
  • SanDisk SDHC 16 GB class 4 memory (all the software requires less than 2 GB)
  • Logitech K120 USB keyboard
  • USB micro cable
  • USB mouse
  • Ethernet cable

In case of problems with the peripherals, there's a list of compatible hardware and a separate list for the SD cards.

There's also a quick start guide with instructions on how to connect all the components.

Download Arch Linux ARM image

Download the Arch Linux ARM image from the Raspberry Pi website (scroll down to the Arch Linux ARM section).

I wasn't able to get the .zip file with the direct download and had to get a BitTorrent client from here. Once installed, just click the archlinux-hf-2013-02-11.zip.torrent link on the browser and it will open the BitTorrent client for you. The file is 200 MB and it took 8 minutes to download with my connection.

Raspberry Pi running Doom II

Write Linux image to SD card

These are instructions for the Mac, for other operating systems look here

These commands and actions need to be performed from an account that has administrator privileges.

(Optional) Verify if the the hash key is the same, in the terminal run this command and compare the long sequence of characters against the SHA-1 field below the link you just clicked (at the time of writing this post it was 1d2508908e7d8c899f4a5284e855cb27c17645dc)

$ shasum ~/Downloads/archlinux-hf-2013-02-11.zip

Extract the image:

$ unzip ~/Downloads/archlinux-hf-2013-02-11.zip

this will create file called archlinux-hf-2013-02-11.img in the current directory

From the terminal run df -h you'll get something like this:

Filesystem      Size   Used  Avail Capacity Mounted on
/dev/disk0s2   698Gi   89Gi  609Gi    13%   /
devfs          186Ki  186Ki    0Bi   100%   /dev
map -hosts       0Bi    0Bi    0Bi   100%   /net
map auto_home    0Bi    0Bi    0Bi   100%   /home

Insert the SD card, run df -h again and look for the new device that wasn't listed last time. Record the device name of the filesystem's partition, in my case it was /dev/disk2s1

Filesystem      Size   Used  Avail Capacity Mounted on
/dev/disk0s2   698Gi   89Gi  609Gi    13%   /
devfs          186Ki  186Ki    0Bi   100%   /dev
map -hosts       0Bi    0Bi    0Bi   100%   /net
map auto_home    0Bi    0Bi    0Bi   100%   /home
/dev/disk2s1    15Gi  2.3Mi   15Gi     1%   /Volumes/NO NAME

Unmount the partition so that you will be allowed to overwrite the disk, you need to enter your password

$ sudo diskutil unmount /dev/disk2s1

Using the device name of the partition work out the raw device name for the entire disk, by omitting the final “s1” and replacing “disk” with “rdisk” (this is very important: you will lose all data on the hard drive on your computer if you get the wrong device name). Make sure the device name is the name of the whole SD card as described above, not just a partition of it (for example, rdisk2, not rdisk2s1. Similarly you might have another SD drive name/number like rdisk2 or rdisk4, etc. – recheck by using the df -h command both before and after you insert your SD card reader into your Mac if you have any doubts!):

In our case, the partition is /dev/disk2s1 then the device is /dev/rdisk2

In the terminal write the image to the card with this command, using the raw disk device name from above (read carefully the above step, to be sure you use the correct rdisk# here!):

$ sudo dd bs=1m if=./archlinux-hf-2013-02-11.img of=/dev/rdisk2

This command will take around 4 minutes and will not feedback any information until there is an error or it is finished, in my case this is what I got back:

1850+0 records in
1850+0 records out
1939865600 bytes transferred in 229.546995 secs (8450843 bytes/sec)

Before taking the card out you must eject it with this command:

$ sudo diskutil eject /dev/rdisk2

Put the SD card into the Raspberry Pi. Connect your display, keyboard, mouse, ethernet cables to the Pi. Lastly, connect power through the micro USB cable. The Pi should boot up Arch Linux ARM and get to the log-in screen.

Log in with login: root and password: root


If at any time you want to cut the power to the Pi you must first shut it down. This is the command to do it:

$ shutdown -h now

System configuration

Login as root.

Change root password:

$ passwd

Edit the locale.gen file. All you need to know about the nano editor is here

$ nano /etc/locale.gen

Search for this line and make sure it's uncommented, i.e. there's no leading #

en_US.UTF-8 UTF-8

Generate locales:


To define your local timezone, find your region or country under this directory:

$ ls /usr/share/zoneinfo

Then find the file that best represents where you live inside that region, in my case:

$ ls /usr/share/zoneinfo/America

Using the full path create a symbolic link:

$ ln -sf /usr/share/zoneinfo/America/New_York /etc/localtime

When the system displays the date, it should contain the correct timezone:

$ date
Sun May 18 13:25:46 EST 2013

Using nano make sure the file /etc/locale.conf contains these 2 lines:


Define the name for your RPi:

$ nano /etc/hostname

Change alarmpi to doom or any name containing only lower case letters and numbers.

Modify /etc/hosts, look for the line localhost.localdomain localhost

$ nano /etc/hosts

Add at the end of that line the same name you used under /etc/hostnanme: localhost.localdomain localhost doom

Full system update

Verify that your Pi is connected to the Internet through the Ethernet port and login as root. If you forget to connect it's better to reboot with shutdown -r now and login again.

The package manager in Arch Linux is called pacman, perform a full system update by issuing this command (note this is a capital S).

$ pacman -Syyu

Once you provide confirmation, it will take several minutes (20 in my case) to download and install the software. Once complete, run this to verify the update was successful:

$ pacman -Syu

It should report nothing to do.

Install sudo and create a user account

The sudo command allows regular users to perform operations that require root priviledges. Install sudo:

$ pacman -Sy sudo

Allow users to run sudo:

$ EDITOR=nano visudo

Uncomment (take away the #) from the line that says: %wheel ALL=(ALL) ALL. Save and exit.

Create a regular user login (change mary for the desired user name, and assign it a password:

$ useradd -m -g users -G audio,lp,optical,storage,video,wheel,games,power,scanner -s /bin/bash mary
$ passwd mary

Reboot Pi:

$ shutdown -r now

Log back in with the user and password you just created.

Install sound drivers

Login as the newly created user.

Install Advanced Linux Sound Architecture (Alsa), required for sound:

$ sudo pacman -Sy alsa-firmware alsa-utils

The Pi has 2 audio outputs: HDMI and analog. If you have an HDMI monitor without sound capabilities, but have old fashioned speakers connected to the analog port, the audio won't work. This forces the Pi to use the analog output and sets volume to maximum:

$ amixer cset name='PCM Playback Route' 1
$ amixer cset name='PCM Playback Volume' 100%

To test the audio execute this command. It will play a “beach” sound that alternates between the left and right speakers.

$ speaker-test -c 2

To stop the test hit Control-C.

If you have trouble setting the audio this article can help.


Remember that you must shutdown before cutting power to the Pi, because you're logged in as a regular user you must run the command using sudo: 'sudo shutdown -h now

Install video drivers

Install Xorg, pre-requisite for GUI apps

$ sudo pacman -Sy xorg-server xorg-xinit xorg-utils xorg-server-utils

Install Xorg framebuffer video driver:

$ sudo pacman -Sy xf86-video-fbdev

Install Openbox and Xterm

Install Openbox and configuration utilities

$ sudo pacman -Sy openbox obconf obmenu lxappearance

Make initial configuration files for your Openbox user:

$ mkdir -p ~/.config/openbox
$ cp /etc/xdg/openbox/menu.xml ~/.config/openbox
$ cp /etc/xdg/openbox/rc.xml ~/.config/openbox

Create/Modify user's .xinitrc file

$ nano ~/.xinitrc

Add the following line to this file:

exec dbus-launch openbox-session

Before starting Openbox for the first time, let's install a terminal:

$ sudo pacman -Sy xterm

Check to see if Openbox works now:

$ startx

This is the graphical interface. All you see is an empty screen with a gray background. Right-click and a menu will pop-up. Select Terminals and then Xterm. This will open the same terminal you've been using, but inside a window.

If you want to exit the GUI select Log Out from the pop-up menu.

Desktop background

In the terminal window we just opened type the following command, it will install feh, an image viewer.

$ sudo pacman -Sy feh

Make a directory for your background, then go to it:

$ mkdir ~/wallpapers
$ cd ~/wallpapers

Find a wallpaper on the net then download with wget:

$ wget http://carreno.me/pi_wallpaper.jpg

Set your wallpaper (make sure to change destination to actual username and filename):

$ feh --bg-scale /home/mary/wallpapers/pi_wallpaper.jpg

To make your desktop load when starting Openbox, modify file autostart:

$ nano ~/.config/openbox/autostart

Add line:

$ sh ~/.fehbg &

Install programming environment

Install the base development package so you can compile C programs:

$ sudo pacman -Sy base-devel

This installs gcc and make plus other useful tools you may need for development.

Install Python 3 (python) or Python 2.7 (python2)

$ sudo pacman -Sy python python2

Install DOOM

Install chocolate-doom. Chocolate-doom is a shareware port for running DOOM game files (.wad files).

$ sudo pacman -Sy chocolate-doom

Get shareware wad file for playing DOOM demo (you can also use your full game .wad files if you own the game, I tested the Doom II wad file and it works fine):

$ cd /usr/share/doom
$ sudo wget http://www.jbserver.com/downloads/games/doom/misc/shareware/doom1.wad.zip

Unzip the file, but first install the zip/unzip utilities:

$ sudo pacman -Sy zip unzip
$ sudo unzip doom1.wad.zip

Run DOOM!!!!

$ chocolate-doom -iwad /usr/share/doom/DOOM1.WAD -window

Forget the -window if you want full screen but it will run slower. The smaller the window, the less math the GPU has to do.