the blog

ruby

11/19/2014

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
end

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:

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.

11/12/2014

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:

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
end
it 'should log non-permitted attributes' do
ActiveSupport::Notifications.
expects(:instrument).
with('unpermitted_parameters.action_controller', keys: ['body']).
once
@params.permit(:title).must_equal 'title' => 'Test'
end
end

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)
end
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'
end
end

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

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'
end

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
end

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)
end
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'
end
end

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

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:

08/29/2013

The vast majority of the time we don’t think much about the height of the web page we are building. Maybe we try to get the most important content “above the fold”, for whatever that’s worth these days, but otherwise we create complex frameworks for horizontal grids while letting the vertical dimension scroll as it wants.

And most of the time that’s just fine. But once in awhile the situation arises where you care about a defined height for a page. That happened to us recently with a metrics status board we have on our wall. This is a single-screen’s worth of our most important numbers, constantly updated throughout the day with no user interaction. After tweaking something or other to fit on the screen for the seven hundred and thirty-second time, and I got fed up and decided this thing should just understand it’s own height and the amount of space each row has within that. I wanted a framework that was just like the grid system we’re already using, only vertical…

So I made it. And I called it: vertical_grid. Maybe a little too on the nose, perhaps?

Visuals

Here's the gist with screenshots. With Bootstrap you have a horizontal grid system like this:

vertical_grid helps you expand it into a vertical grid system, so you get something like this:

(Basically we're mostly looking to avoid this:)

The Details

It’s based on Bootstrap because we’re already using that. Anything already taken care of by Bootstraps horizontal grid we don’t need to recreate. It’s also written using Sass because I don’t need to type the same stuff twelve times over.

The framework is working well for us, but it’s still fresh from the oven. If you try it and come up with some issues or improvements we’d love to see them. Hit us up on the GitHub with bugs and pull requests.

Check out the slides, check out all those amazing links. Have fun. That'll keep you busy for awhile.

One of those links is to Squeel. Even if you don't care to know what GIS stands for, check that baby out. All I'm going to say is it makes ActiveRecord better like you want it to be; just go scroll through those examples. Word up.

Ilya Grigorik gave a super talk called Making the Web Fast(er). It's all stuff you should know about, and one bit that was new to me was the Navigation Timing stuff from the W3C. (There's one picture in there, so obviously just scroll down to that.) "This specification defines an interface for web applications to access timing information related to navigation and elements." This covers, like, everything, which is cool, and is shows up in Google Analytics, which is even better. Content > Site Speed > Page Timings is the magical incantation, and also the Performance tab will show you histograms which are a cool blue.

Sarah Mei gave a nice shout out to our friends over at Meteor. Meteor is a cool new JavaScript framework for building web apps. I have to link to Meteor a lot because they don’t seem to understand how search crawlers work…