Controller testing in Active Scaffold

Problem

You need to have to functionally test your controller when you are using ActiveScaffold. There are pieces of code that tell you how to do that on a normal ror application (ie without ActiveScaffold), like recipe 7.17 on the Rails Cookbook, or a fragment of code in an Active Scaffold application, but they don’t have the full details.

Solution

Here is an attempt to give some more detailed step by step instructions on how to do it.

  1. The migration for the example customer model.
  2. class CreateCustomers < ActiveRecord::Migration
      def self.up
        # Create customers table
        create_table  :customers do |t|
          t.column  :customer_code, :string, :null => false
          t.column  :created_at, :datetime
          t.column  :updated_at, :datetime
        end
      end
    end
  3. The customer model, with the extra function to display the customer code
  4. class Customer < ActiveRecord::Base
    
      has_many    :numbers
    
      def to_label
        "#{customer_code}"
      end
    end
  5. The customer controller app/controllers/customers_controller.rb, using the Active Scaffold
  6. class CustomersController < ApplicationController
    
      active_scaffold :customer do |config|
        config.list.columns = [:customer_code, :numbers, :created_at, :updated_at]
        config.columns[:customer_code].inplace_edit = true
     end
    
    end
  7. The fixtures YML file test/fixtures/customers.yml
  8. first_customer:
      id:               1
      customer_code:    123
      created_at:       2007-09-26 11:17:07
      updated_at:       2007-09-26 11:17:07
    
    second_customer:
      id:               2
      customer_code:    456
      created_at:       2007-09-26 11:17:13
      updated_at:       2007-09-26 11:17:13
  9. And here are some functions to test some pages and a full CRUD test
  10. require File.dirname(__FILE__) + '/../test_helper'
    require 'customers_controller'
    
    class CustomerControllerTest < Test::Unit::TestCase
      fixtures  :customers
    
      def setup
        @controller = CustomersController.new
        @request = ActionController::TestRequest.new
        @response = ActionController::TestResponse.new
      end
    
      def test_index
        get :index
        assert_response :success
        assert_template 'list'
      end
    
      def test_new
        get :new
        assert_response :success
        assert_template 'create_form'
      end
    
      def test_edit
        get :edit, :id => customers(:first_customer).id
        assert_response :success
        assert_template 'update_form'
      end
    
      def test_show
        get :show, :id => customers(:first_customer).id
        assert_response :success
        assert_template 'show'
      end
    
      def test_customer_controller_CRUD
    
        # CREATE
        # Get the number of records
        record_no = Customer.count
        # Create a new record
        post  :create, {"commit"=>"Create", :record=>{"customer_code"=>"890"}}
        # Assert that the record is not nil
        assert_not_nil  assigns("record")
        # Look that the number of records has been increased by 1
        assert_equal  record_no+1, Customer.count
    
        # UPDATE
        # Get the number of records
        record_no = Customer.count
        # Update a record
        new_customer_code = "987"
        put :update, {"commit"=>"Update",:id=>customers(:first_customer).id,
                                          :record=>{"customer_code"=>new_customer_code}}
        # Assert that the record is not nil
        assert_not_nil  assigns("record")
        # Look that the number of records has stayed the same
        assert_equal  record_no, Customer.count
        # Check that the update took place
        customer = Customer.find(customers(:first_customer).id)
        assert_equal  new_customer_code, customer.customer_code
    
        # DELETE
        # Get the number of records
        record_no = Customer.count
        # Delete a record
        delete  :destroy, :id => customers(:first_customer).id
        # Look that the number of records has been decreased by 1
        assert_equal  record_no-1, Customer.count
      end
    
    end

:int and :integer problem in Ruby on Rails migration

After spending some time trying to make a migration work, and having the error message coming back:

You have a nil object when you didn't expect it!
You might have expected an instance of Array.
The error occurred while evaluating nil.[]

I’ve decided to do a google search for the specific problem, as it was working fine with other test migrations.

It turns out that if the migration is not model specific, but a different one (ie trying to add a new column to an existing table), the :int for the column doesn’t work!
It has to be :integer.
Full bug report and the article are here:
Migrations: :integer works, :int doesn’t – datatype discrepancy

dhtmlcalendar in ActiveScaffold

To control the date format in dhtmlcalendar within ActiveScaffold in Ruby on Rails, to make the date of 2 November 2007 appear like 02-11-2007, use:

i) if you want to affect the settings in all the application add the following to the top of your controllers/application.rb

ActiveSupport::CoreExtensions::Date::Conversions::DATE_FORMAT[:default] = ‘%d-%m-%Y’

ii) If you only want to affect the settings of the calendar in one specific controller, then add the same line only to the controller that you want:

ActiveSupport::CoreExtensions::Date::Conversions::DATE_FORMAT[:default] = '%d-%m-%Y'

File column plugin with ActiveScaffold upload branch

When using the file_column plugin in the active_scaffold upload branch, the documentation in the file_column doesn’t make it clear what we have to change to make it work.

In the example below the model is number and the file_column is intro.

1. In models/number.rb add:

file_column :intro

2. in controllers/numbers_controller.rb, make sure we have:

config.create.multipart = true
config.update.multipart = true

3. in helpers/numbers_helper.rb add:

def intro_form_column(record, input name)
  file_column_field 'record', :intro
end

def intro_column(record)
  record.intro ? link_to(File.basename(record.intro),
    url_for_file_column(record,'intro'), :popup => true) : "-"
end

4. in views/numbers/_intro_form_column.rhtml add:


  <%= file_column_field  'record', 'intro' %>