Fixing Rails’ “undefined method `map’ for nil:NilClass” errors for collection_selects

I had a weird problem. I defined a collection_select in my form, something like this:

<%= f.collection_select :campaign_id, @campaigns, :id, :title %>

When I went to the form, the page loaded, and the select populated correctly. However, when I submitted the form, I would get the “undefined method `map’ for nil:NilClass” error.

By mistake, I realized that the sometimes the form posted and sometimes it didn’t. Then I realized that there were Active Record validation errors with the submitted form, but the page wasn’t showing, so I couldn’t see that these errors occurred (even while looking at the logs).

I had to search how to fix this, and eventually found this Stack Overflow question.

The solution by Wes Foster, worked for me to ensure that the collection was getting determined when the new action was rendered (after the record didn’t create).

class MyController < ApplicationController
  before_action :set_select_collections, only: [:edit, :update, :new, :create]

  private
    def set_select_collections
      @campaigns = current_user.business.campaigns
    end
end

Incidentally, if you’re receiving this error and your form isn’t even loading, it probably means that you didn’t define the collection value in your controller (@campaigns in this example).

Editing credentials.yml.enc on Windows

Since credentials.yml.enc is encrypted, you have to edit it in a different way than most Rails files.

To open and edit it Windows, you have to assign an editor, and then open the file via console.

(1) In the console, assign the editor:

set EDITOR=notepad

(2) Next, edit the file

rails credentials:edit

(3) Save the notepad file and close

If you have different files for each environment in the credentials directory, you can edit it with:

rails credentials:edit -e development

Skipping to the End of Data in Rails Console

I used to get stuck in the Rails console when I had a query that returned a lot of data. I would just keep hitting the button to go to the next page which took a long time depending on the data returned.

I finally learned that if I just enter q, then I can skip past all of that.

Such a time saver, I should’ve figured this out much sooner.

Password Protect Staging

I wanted to password protect my staging environment on Heroku.  Here’s a simple way to do it.

In your application controller, enter:

if Rails.application.secrets.auth
  http_basic_authenticate_with \
  name: Rails.application.secrets.auth_name,
  password: Rails.application.secrets.auth_pass
end
Then in your environment variables in Heroku (for your staging app), enter these variables:
AUTH = true
AUTH_NAME = <user name you want to use>
AUTH_PASS = <password you want to use>

Abbreviating Numbers in Rails

I needed to abbreviate numbers in Rails so that they were shorter and easier to read.  Rails has a great built in method, number_to_human.  However, I didn’t like how number_to_human displays without any customization.

My main issue was that instead of spelling out the entire number, I just wanted to put a letter abbreviation.  In addition, I didn’t want a space between the number and its text description.

For example, “out of the box”, if you do:

number_to_human(1234)

You will get:

“1.23 Thousand”

Instead, I wanted 1.23K.

Luckily, I found this StackOverflow answer by jdoe.

To format it like this, you just need to add these values to config/locales/en.yml (or whatever you’re using as your 18n locale):

(under "en:")
  number:
    human:
      decimal_units:
        format: "%n%u"
        units:
          unit: ""
          thousand: K
          million: M
          billion: B
          trillion: T
          quadrillion: Q

Hiding Values from Appearing in Rails Logs

I had some fields that were sensitive, so I didn’t want the values appearing in the logs.  The solution was filtering them.  Doing that was easy.

In config/initializers/filter_parameter_logging.rb, and your fields, like so:

Rails.application.config.filter_parameters += [:password, :secret_field]

Now, when I look at the logs, I see this:

“user”=>{“password”=>”[FILTERED]”, “secret_field”=>”[FILTERED]”

NoMethodError undefined method `[]’ for “image”:Sass::Script::Value::String

When upgrading my Rails app to 4 (from 3), I was getting the error:

NoMethodError undefined method `[]’ for “image”:Sass::Script::Value::String

Eventually I found out that the asset-path / asset-url methods changed to only accept one argument.

For example,

asset-url(‘profile.png’, image)

now should be:

asset-url(‘profile.png’)

In my particular case, this code was in some of my css files.

Useful Rails Testing Gems

Here’s a list of Rails gems that have been helpful in testing for me:

RSpec Rails – for using the RSpec framework for testing

Capybara – for testing the app like a visitor would interact with the web app

Factory Girl Rails – makes it easy to create instances of models and associations

Shoulda Matchers – makes it easier to test and verify things with methods that use easy to understand language

Database Cleaner – to help keep your test environment from having a bunch of extra and redundant data

Warden – since I use Devise, this makes it easy to sign in in my Capybara tests without having to go to the login screen each time (and then to the pages I really want to test)

Guard – allows me to automatically test the code and specs that I change so I don’t need to remember to manually kick off a test each time a change is made

Launchy – useful with Capybara tests when I can’t figure out why a test is failing.  Launchy launches a browser so you can see the contents of the page.’save_and_open_page’ line to your spec when you want to do this.