Thursday, May 28, 2015

Simplifying Rails views with pluralize

"2 User(s) been updated."

This is a silly problem that I kept running into before I found out about pluralize.

Now, instead of having to do a conditional checking for number of users and printing the line based on that number, I can do this using pluralize in Rails:

pluralize(@users, 'User')

Or, if I want to use the Ruby version of pluralize (or, more accurately, the ActiveSupport version):

require 'active_support/inflector'
"User".pluralize(@users)

If @users is more than one, outputs "Users". If @users is 1, outputs "User". This is nice for when you don't want to display the number, just the pluralized word (i.e. "Users updated").

Tuesday, May 26, 2015

Enumerating in Ruby like a BOSS

The other day I wanted to run collect on an array, but I needed the indexes of the elements collected as well. Essentially, I wanted an array of hashes with the index as the key and the element as the value. I could have sloppily hacked together something like this:

my_new_array = []
my_array.each_with_index do |element, index|
  my_new_array << { index => element }
end
return my_new_array

When doing some Googling, I found out that Ruby allows enumerator method chaining - in other words, I can take an array and run something like this:

my_array.each_with_index.collect do |element, index|
  { index => element }
end

I love my collect method, so anytime I can use it, I will. And apparently, in Ruby, any enumerable can be called on any other enumerable.

Tuesday, May 19, 2015

Beware reserved ENV names in Rails

Not all environment variable names are created equal.

For example, if you are using Ruby on Rails, do not declare a VERSION environment variable, there is already one a reserved. The reserved VERSION envar is used by Rails in migrating database changes, so if it is changed at all, you will have problems when making new migrations.

That was a fun error to debug...

Wednesday, May 6, 2015

Testing CSV exports/downloads in Ruby on Rails with Capybara

As low-tech as CSV is, it doesn't appear to be going away anytime soon. So, I've run into a few different Ruby on Rails projects that want import from/export to CSV capability, and because I like tests, I wanted to make sure I could test not only that the CSV is exported but that the content of the CSV is correct.

Here's how to do this using Capybara and Rspec:

First, switch the driver to something that works (webkit or rack_test, but not selenium). To do this, you can run this within your code block:

Capybara.javascript_driver = :webkit

Just make sure to change it back to your preferred driver after you're done. Another option is to do this in your spec_helper.rb:

config.before(:each, webkit: true) do
    Capybara.javascript_driver = :webkit
end

config.after(:each, webkit: true) do
    Capybara.javascript_driver = :selenium 
    # or whatever your preferred driver is
end

Then just tag any CSV tests with the webkit: true tag.
(Thanks to Kevin Bedell on StackOverflow for this one.)

Once you get the driver configured properly, you can check the headers and the actual content of the CSV trivially:

click_on 'Download as CSV'
# Make sure the page is a CSV
header = page.response_headers['Content-Disposition']
expect(header).to match /^attachment/
expect(header).to match /filename="my_file.csv"$/

# Then check the content
MyModel.all.each do |record|
  expect(page).to have_content record.field1
  expect(page).to have_content record.field2
end

(Props to Andrew on StackOverflow for this bit.)