Validation error handling on related models

James Byrne wrote:

When I try and add a new client - entity pair with a blank name, instead
of getting a nicely formated error on top of the entry page I get this:

Much SQL truncated
...
ActiveRecord::RecordInvalid (Validation failed: Entity legal name The
legal name
may not be blank., Entity name The name may not be blank.):

Can you show the truncated SQL? Also the parameters from the log file
sent to the #update method and also the content of the #update method...

Mark Bush wrote:

Can you show the truncated SQL? Also the parameters from the log file
sent to the #update method and also the content of the #update method...

Certainly:

log/development.log

Processing ClientsController#create (for 127.0.0.1 at 2008-03-08
15:55:12) [POST]
  Session ID: 8603979b1f6dcb80d723c29c0f7d7cf3
  Parameters: {"commit"=>"Update", "entity"=>{"entity_legal_name"=>"",
"entity_name"=>"", "entity_legal_form"=>""},
"client"=>{"changed_by"=>"", "created_by"=>"",
"client_credit_policy"=>"CASH", "effective_from"=>"Sat Mar 08 15:53:45
-0500 2008", "client_date_last_active"=>"Sat Mar 08 15:53:45 -0500
2008", "client_date_last_contacted"=>"Sat Mar 08 15:53:45 -0500 2008",
"superseded_after"=>"0", "changed_at"=>"", "client_credit_terms"=>"0",
"created_at"=>""},
"authenticity_token"=>"f201af86310713a8221d5b50c569c4d757453283",
"action"=>"create", "controller"=>"clients"}
  SQL (0.000000) SELECT a.attname, format_type(a.atttypid,
a.atttypmod), d.adsrc, a.attnotnull
FROM pg_attribute a LEFT JOIN pg_attrdef d
ON a.attrelid = d.adrelid AND a.attnum = d.adnum
WHERE a.attrelid = 'clients'::regclass
AND a.attnum > 0 AND NOT a.attisdropped
ORDER BY a.attnum

  Client Indexes (0.016000) SELECT i.relname, d.indisunique,
a.attname
FROM pg_class t, pg_class i, pg_index d, pg_attribute a
WHERE i.relkind = 'i'
AND d.indexrelid = i.oid
AND d.indisprimary = 'f'
AND t.oid = d.indrelid
AND t.relname = 'clients'
AND a.attrelid = t.oid
AND ( d.indkey[0]=a.attnum OR d.indkey[1]=a.attnum
OR d.indkey[2]=a.attnum OR d.indkey[3]=a.attnum
OR d.indkey[4]=a.attnum OR d.indkey[5]=a.attnum
OR d.indkey[6]=a.attnum OR d.indkey[7]=a.attnum
OR d.indkey[8]=a.attnum OR d.indkey[9]=a.attnum )
ORDER BY i.relname

  Client Indexes (0.000000) SELECT c2.relname, i.indisunique,
pg_catalog.pg_get_indexdef(i.indexrelid, 0, true)
FROM pg_catalog.pg_class c, pg_catalog.pg_class c2, pg_catalog.pg_index
i
WHERE c.relname = 'clients'
AND c.oid = i.indrelid AND i.indexrelid = c2.oid
AND i.indisprimary = 'f'
AND i.indexprs IS NOT NULL
ORDER BY 1

  SQL (0.015000) SELECT a.attname, format_type(a.atttypid,
a.atttypmod), d.adsrc, a.attnotnull
FROM pg_attribute a LEFT JOIN pg_attrdef d
ON a.attrelid = d.adrelid AND a.attnum = d.adnum
WHERE a.attrelid = 'entities'::regclass
AND a.attnum > 0 AND NOT a.attisdropped
ORDER BY a.attnum

  Entity Indexes (0.000000) SELECT i.relname, d.indisunique,
a.attname
FROM pg_class t, pg_class i, pg_index d, pg_attribute a
WHERE i.relkind = 'i'
AND d.indexrelid = i.oid
AND d.indisprimary = 'f'
AND t.oid = d.indrelid
AND t.relname = 'entities'
AND a.attrelid = t.oid
AND ( d.indkey[0]=a.attnum OR d.indkey[1]=a.attnum
OR d.indkey[2]=a.attnum OR d.indkey[3]=a.attnum
OR d.indkey[4]=a.attnum OR d.indkey[5]=a.attnum
OR d.indkey[6]=a.attnum OR d.indkey[7]=a.attnum
OR d.indkey[8]=a.attnum OR d.indkey[9]=a.attnum )
ORDER BY i.relname

  Entity Indexes (0.000000) SELECT c2.relname, i.indisunique,
pg_catalog.pg_get_indexdef(i.indexrelid, 0, true)
FROM pg_catalog.pg_class c, pg_catalog.pg_class c2, pg_catalog.pg_index
i
WHERE c.relname = 'entities'
AND c.oid = i.indrelid AND i.indexrelid = c2.oid
AND i.indisprimary = 'f'
AND i.indexprs IS NOT NULL
ORDER BY 1

  SQL (0.000000) BEGIN
  SQL (0.000000) ROLLBACK

ActiveRecord::RecordInvalid (Validation failed: Entity legal name The
legal name may not be blank., Entity name The name may not be blank.):
    c:/usr/lib/ruby/lib/ruby/gems/1.8/gems/activerecord-2.0.2/lib/active_record/validations.rb:946:in
`save_without_transactions!'
    c:/usr/lib/ruby/lib/ruby/gems/1.8/gems/activerecord-2.0.2/lib/active_record/transactions.rb:112:in
`save!'
    c:/usr/lib/ruby/lib/ruby/gems/1.8/gems/activerecord-2.0.2/lib/active_record/connection_adapters/abstract/database_statements.rb:66:in
`transaction'
    c:/usr/lib/ruby/lib/ruby/gems/1.8/gems/activerecord-2.0.2/lib/active_record/transactions.rb:80:in
`transaction'
    c:/usr/lib/ruby/lib/ruby/gems/1.8/gems/activerecord-2.0.2/lib/active_record/transactions.rb:100:in
`transaction'
    c:/usr/lib/ruby/lib/ruby/gems/1.8/gems/activerecord-2.0.2/lib/active_record/transactions.rb:112:in
`save!'
    c:/usr/lib/ruby/lib/ruby/gems/1.8/gems/activerecord-2.0.2/lib/active_record/transactions.rb:120:in
`rollback_active_record_state!'
    c:/usr/lib/ruby/lib/ruby/gems/1.8/gems/activerecord-2.0.2/lib/active_record/transactions.rb:112:in
`save!'
    /app/controllers/clients_controller.rb:66:in `create'
    c:/usr/lib/ruby/lib/ruby/gems/1.8/gems/actionpack-2.0.2/lib/action_controller/base.rb:1158:in
`send'
    c:/usr/lib/ruby/lib/ruby/gems/1.8/gems/actionpack-2.0.2/lib/action_controller/base.rb:1158:in
`perform_action_without_filters'
    c:/usr/lib/ruby/lib/ruby/gems/1.8/gems/actionpack-2.0.2/lib/action_controller/filters.rb:697:in
`call_filters'
    c:/usr/lib/ruby/lib/ruby/gems/1.8/gems/actionpack-2.0.2/lib/action_controller/filters.rb:689:in
`perform_action_without_benchmark'
    c:/usr/lib/ruby/lib/ruby/gems/1.8/gems/actionpack-2.0.2/lib/action_controller/benchmarking.rb:68:in
`perform_action_without_rescue'
    c:/usr/lib/ruby/lib/ruby/1.8/benchmark.rb:293:in `measure'
    c:/usr/lib/ruby/lib/ruby/gems/1.8/gems/actionpack-2.0.2/lib/action_controller/benchmarking.rb:68:in
`perform_action_without_rescue'
    c:/usr/lib/ruby/lib/ruby/gems/1.8/gems/actionpack-2.0.2/lib/action_controller/rescue.rb:199:in
`perform_action_without_caching'
    c:/usr/lib/ruby/lib/ruby/gems/1.8/gems/actionpack-2.0.2/lib/action_controller/caching.rb:678:in
`perform_action'
    c:/usr/lib/ruby/lib/ruby/gems/1.8/gems/activerecord-2.0.2/lib/active_record/connection_adapters/abstract/query_cache.rb:33:in
`cache'
    c:/usr/lib/ruby/lib/ruby/gems/1.8/gems/activerecord-2.0.2/lib/active_record/query_cache.rb:8:in
`cache'
    c:/usr/lib/ruby/lib/ruby/gems/1.8/gems/actionpack-2.0.2/lib/action_controller/caching.rb:677:in
`perform_action'
    c:/usr/lib/ruby/lib/ruby/gems/1.8/gems/actionpack-2.0.2/lib/action_controller/base.rb:524:in
`send'
    c:/usr/lib/ruby/lib/ruby/gems/1.8/gems/actionpack-2.0.2/lib/action_controller/base.rb:524:in
`process_without_filters'
    c:/usr/lib/ruby/lib/ruby/gems/1.8/gems/actionpack-2.0.2/lib/action_controller/filters.rb:685:in
`process_without_session_management_support'
    c:/usr/lib/ruby/lib/ruby/gems/1.8/gems/actionpack-2.0.2/lib/action_controller/session_management.rb:123:in
`process'
    c:/usr/lib/ruby/lib/ruby/gems/1.8/gems/actionpack-2.0.2/lib/action_controller/base.rb:388:in
`process'
    c:/usr/lib/ruby/lib/ruby/gems/1.8/gems/actionpack-2.0.2/lib/action_controller/dispatcher.rb:171:in
`handle_request'
    c:/usr/lib/ruby/lib/ruby/gems/1.8/gems/actionpack-2.0.2/lib/action_controller/dispatcher.rb:115:in
`dispatch'
    c:/usr/lib/ruby/lib/ruby/gems/1.8/gems/actionpack-2.0.2/lib/action_controller/dispatcher.rb:126:in
`dispatch_cgi'
    c:/usr/lib/ruby/lib/ruby/gems/1.8/gems/actionpack-2.0.2/lib/action_controller/dispatcher.rb:9:in
`dispatch'
    c:/usr/lib/ruby/lib/ruby/gems/1.8/gems/rails-2.0.2/lib/webrick_server.rb:112:in
`handle_dispatch'
    c:/usr/lib/ruby/lib/ruby/gems/1.8/gems/rails-2.0.2/lib/webrick_server.rb:78:in
`service'
    c:/usr/lib/ruby/lib/ruby/1.8/webrick/httpserver.rb:104:in `service'
    c:/usr/lib/ruby/lib/ruby/1.8/webrick/httpserver.rb:65:in `run'
    c:/usr/lib/ruby/lib/ruby/1.8/webrick/server.rb:173:in `start_thread'
    c:/usr/lib/ruby/lib/ruby/1.8/webrick/server.rb:162:in `start'
    c:/usr/lib/ruby/lib/ruby/1.8/webrick/server.rb:162:in `start_thread'
    c:/usr/lib/ruby/lib/ruby/1.8/webrick/server.rb:95:in `start'
    c:/usr/lib/ruby/lib/ruby/1.8/webrick/server.rb:92:in `each'
    c:/usr/lib/ruby/lib/ruby/1.8/webrick/server.rb:92:in `start'
    c:/usr/lib/ruby/lib/ruby/1.8/webrick/server.rb:23:in `start'
    c:/usr/lib/ruby/lib/ruby/1.8/webrick/server.rb:82:in `start'
    c:/usr/lib/ruby/lib/ruby/gems/1.8/gems/rails-2.0.2/lib/webrick_server.rb:62:in
`dispatch'
    c:/usr/lib/ruby/lib/ruby/gems/1.8/gems/rails-2.0.2/lib/commands/servers/webrick.rb:66
    c:/usr/lib/ruby/lib/ruby/site_ruby/1.8/rubygems/custom_require.rb:27:in
`gem_original_require'
    c:/usr/lib/ruby/lib/ruby/site_ruby/1.8/rubygems/custom_require.rb:27:in
`require'
    c:/usr/lib/ruby/lib/ruby/gems/1.8/gems/activesupport-2.0.2/lib/active_support/dependencies.rb:496:in
`require'
    c:/usr/lib/ruby/lib/ruby/gems/1.8/gems/activesupport-2.0.2/lib/active_support/dependencies.rb:342:in
`new_constants_in'
    c:/usr/lib/ruby/lib/ruby/gems/1.8/gems/activesupport-2.0.2/lib/active_support/dependencies.rb:496:in
`require'
    c:/usr/lib/ruby/lib/ruby/gems/1.8/gems/rails-2.0.2/lib/commands/server.rb:39
    c:/usr/lib/ruby/lib/ruby/site_ruby/1.8/rubygems/custom_require.rb:27:in
`gem_original_require'
    c:/usr/lib/ruby/lib/ruby/site_ruby/1.8/rubygems/custom_require.rb:27:in
`require'
    script/server:3

Redirected to http://localhost:3000/500.html

client_controller.rb

  # POST /clients
  # POST /clients.xml
  def create
    @client = Client.new(params[:client])
    @entity = Entity.new params[:entity]
    @entity.save!
    @client.entity_id = @entity.id
    @client.save!

    respond_to do |format|
      if @client.save
        flash[:notice] = 'Client was successfully created.'
        format.html { redirect_to(@client) }
        format.xml { render :xml => @client, :status => :created,
:location => @client }
      else
        format.html { render :action => "new" }
        format.xml { render :xml => @client.errors, :status =>
:unprocessable_entity }
      end
    end
  end

  # PUT /clients/1
  # PUT /clients/1.xml
  def update
    @client = Client.find(params[:id])

    unless @client.active?
      flash[:notice] ='You may not edit an inactive client'
      return(redirect_to :action => 'edit', :id => params[:id])
    end

    respond_to do |format|
      if @client.update_attributes(params[:client])
        flash[:notice] = 'Client was successfully updated.'
        format.html { redirect_to(@client) }
        format.xml { head :ok }
      else
        format.html { render :action => "edit" }
        format.xml { render :xml => @client.errors, :status =>
:unprocessable_entity }
      end
    end
  end