multiple object validation inconsistency

Hello,

I am updating two objects from a form with the code:

def update
    @court = Court.find(params[:id])
    @address = @court.address

    valid = @court.valid?

    if @address.valid? and valid and
@court.update_attributes(params[:court]) and
      @address.update_attributes(params[:address])
      flash[:notice] = 'Court was successfully updated.'
      redirect_to :action => 'show', :id => @court
    else
      render :action => 'edit'
    end
  end

If the address fails validation I get an error message like I would
expect and the information that the user just keyed is redisplayed to
the user.

If the court and address both fail validation, the error messages
appear, but the address data reverts to the state in the database and
the user changes are lost. I assume it is the way I am loading the
address, which doesn't look correct to me, but it does work when the
court information passes validation.

Any help would be appreciated.

Thanks,
Dan

Dan Munk wrote:

Hello,

I am updating two objects from a form with the code:

def update
    @court = Court.find(params[:id])
    @address = @court.address

    valid = @court.valid?

    if @address.valid? and valid and
@court.update_attributes(params[:court]) and
      @address.update_attributes(params[:address])
      flash[:notice] = 'Court was successfully updated.'
      redirect_to :action => 'show', :id => @court
    else
      render :action => 'edit'
    end
  end

If the address fails validation I get an error message like I would
expect and the information that the user just keyed is redisplayed to
the user.

If the court and address both fail validation, the error messages
appear, but the address data reverts to the state in the database and
the user changes are lost. I assume it is the way I am loading the
address, which doesn't look correct to me, but it does work when the
court information passes validation.

You want to update the attributes in the model objects (but not in
the DB) prior to the validation check:

@court = Court.find(params[:id])
@address = @court.address
@court.attributes = params[:court]
@address.attributes = params[:address]
valid = @court.valid?
if @address.valid? and valid
   @court.save(false) # false = skip validation
   @address.save(false)
   flash[:notice] = ...
   ...

Dan Munk wrote:
> Hello,
>
> I am updating two objects from a form with the code:
>
> def update
> @court = Court.find(params[:id])
> @address = @court.address
>
> valid = @court.valid?
>
> if @address.valid? and valid and
> @court.update_attributes(params[:court]) and
> @address.update_attributes(params[:address])
> flash[:notice] = 'Court was successfully updated.'
> redirect_to :action => 'show', :id => @court
> else
> render :action => 'edit'
> end
> end
>
> If the address fails validation I get an error message like I would
> expect and the information that the user just keyed is redisplayed to
> the user.
>
> If the court and address both fail validation, the error messages
> appear, but the address data reverts to the state in the database and
> the user changes are lost. I assume it is the way I am loading the
> address, which doesn't look correct to me, but it does work when the
> court information passes validation.

You want to update the attributes in the model objects (but not in
the DB) prior to the validation check:

I suggest wrapping the whole update in a transaction. It's the only
way you can guarantee that multiple objects are (only) updated
together, and also a lot easier to get right.

Isak

Great, thanks.