jedidja.ca

There's always something new to learn today

Testing JSON Error Results From Rails Functional Tests

At the end of Chapter 8 of Agile Web Development With Rails, there is a seemingly innocuous exercise that says:

Write some functional tests for the product maintenance application ...

Sounds easy enough :) And I like writing tests. Yes, I'm weird that way.

The existing tests are all happy-path.

require 'test_helper'

class ProductsControllerTest < ActionController::TestCase
setup do
  @product = products(:one)
  @update = {
    title: 'Lorem Ipsum',
    description: 'Wibbles are fun!',
    image_url: 'lorem.jpg',
    price: 19.95
  }
end

test "should create product" do
  assert_difference('Product.count') do
  post :create, product: @update
end

  assert_redirected_to product_path(assigns(:product))
  end
end

And so I decided to try adding a test for when you can't create a product

@invalid_product = {
  price: 0.00,
  title: 'abc'
}

test "should not create product" do
  post :create, product: @invalid_product
  assert_template :new
end

And all was well. Or, almost. There were no tests for the JSON path in the controller:

# POST /products
# POST /products.json
def create
  @product = Product.new(params[:product])

respond_to do |format|
  if @product.save
    format.html { redirect_to @product, notice: 'Product was successfully created.' }
    format.json { render json: @product, status: :created, location: @product }
  else
    format.html { render action: "new" }
    format.json { render json: @product.errors, status: :unprocessable_entity }
  end
end
end

Thinking this would be easy enough to do, I ended up reading an untold number of Stack Overflow posts on the subject; it seems like it's changed between different versions of Rails. Finally, after about an hour, I ended up with something that worked. It seems perfectly simple and obvious in hindsight, but in case anyone else's mind works like mine, here it is :)

test "should not create product (JSON)" do
  post :create, :data =>     @invalid_product.to_json, :format => "json"
  assert_response :unprocessable_entity
end

Note: This is what currently works on Rails 3.2.8 and Ruby 1.9.3p194.

Installing Rails on Mountain Lion Without Xcode

I admit it: I'm a Rails noob. 100%. Totally. As a result, this post may be useful to 0.000001% of all starting Rails developers out there.

A while ago*, I pre-purchased Agile Web Development With Rails and for some reason decided to try it out this morning. Of course, as the book says, "neither Snow Leopard nor Lion prepackage Ruby 1.9.3, you’ll need to download and build it yourself." Goody. And neither does Mountain Lion (10.8). I'm also quite used to living in a Windows world where you just install whatever you need. 

After a bit of searching, here's what you need to do to get Rails up and running without worrying about Xcode.

  1. Install the Command Line Tools (115 Mb). You will need an Apple Developer Account.
  2. Open Terminal and run the following commands
    1. curl -L https://get.rvm.io | bash -s stable --ruby
    2. (Optionally) rvm current should display ruby-1.9.3-p194 (or later)
    3. gem install rails

Note: You can skip steps 2.2 and 2.3 if you replace step 2.1 with curl -L https://get.rvm.io | bash -s stable --rails; I was trying to mimic the instructions in the book a bit.

At this point you should be able to run rails -v and get a response (e.g. Rails 3.2.8).

*Pragprog.com claims I bought it March 18, 2011 (520 days ago). I think it's trying to make me feel bad.