Forum: Ruby on Rails Save method behaviour changed?

Posted by James Byrne (byrnejb)
on 2013-03-05 20:33
(Received via mailing list)
I have this code in a working RoR-3.1 app:

  # save
  #
  # Override AR save method to catch DBMS specific errors
  # such as uniqueness constraint violations
  def save
    super
    rescue ActiveRecord::StatementInvalid => this_exception
      errors.add( currency_code, hll_ar_exception( this_exception ) )
      false
  end

In RoR-3.2.12  this no longer works.  Once I pass a save involving a
duplicate record it never returns to the calling method.  For example:

  def save
    super
    fail( " die die die " )
    rescue ActiveRecord::StatementInvalid => this_exception

produces no output and does not throw an exception but in the log file I
see this none-the-less:

PG::Error: ERROR:  duplicate key value violates unique constraint
"idxu_currencies_currency_code"
DETAIL:  Key (currency_code)=(JPY) already exists.


How do I get the old behaviour back?  Calling save! instead super does 
not
change the outcome.
Posted by tamouse mailing lists (Guest)
on 2013-03-06 01:15
(Received via mailing list)
On Tue, Mar 5, 2013 at 1:32 PM, byrnejb <byrnejb@harte-lyne.ca> wrote:
>       false
> produces no output and does not throw an exception but in the log file I see
> this none-the-less:
>
> PG::Error: ERROR:  duplicate key value violates unique constraint
> "idxu_currencies_currency_code"
> DETAIL:  Key (currency_code)=(JPY) already exists.
>
>
> How do I get the old behaviour back?  Calling save! instead super does not
> change the outcome.

I don't know the answer to your question, but I'm wondering if you can
circumvent the exception altogether by using valid? to see if it's a
valid record before attempting the save?
Posted by James Byrne (byrnejb)
on 2013-03-06 02:35
(Received via mailing list)
On Tue, March 5, 2013 19:13, tamouse mailing lists wrote:
>>       errors.add( currency_code, hll_ar_exception( this_exception )
>>     fail( " die die die " )
>>
>> How do I get the old behaviour back?  Calling save! instead super
>> does not
>> change the outcome.
>
> I don't know the answer to your question, but I'm wondering if you can
> circumvent the exception altogether by using valid? to see if it's a
> valid record before attempting the save?
>

Rails validation for duplicate records is, to put it bluntly, a joke.
The code I wrote is intended to compensate for that fact by using the
DBMS as it is intended to be used.  Up to the current version of Rails
this worked as I intended.  Now it does not.  I simply want to
discover what has changed and how I get around it.


--
***          E-Mail is NOT a SECURE channel          ***
James B. Byrne                mailto:ByrneJB@Harte-Lyne.ca
Harte & Lyne Limited          http://www.harte-lyne.ca
9 Brockley Drive              vox: +1 905 561 1241
Hamilton, Ontario             fax: +1 905 561 0757
Canada  L8E 3C3
Posted by Frederick Cheung (Guest)
on 2013-03-06 10:55
(Received via mailing list)
On Tue, Mar 5, 2013 at 7:32 PM, byrnejb <byrnejb@harte-lyne.ca> wrote:

> I have this code in a working RoR-3.1 app:
>
>   # save
>   #
>   # Override AR save method to catch DBMS specific errors
>   # such as uniqueness constraint violations
>

Where is this code? in a model, in module that is included into various
models, somewhere else?

As an aside recent versions of rails raise ActiveRecord::RecordNotUnique 
in
such cases, although this is a subclass of 
ActiveRecord::StatementInvalid
so shouldn't change behaviour as far as you're concern. You're also
changing the signature of save although I don't think that is related to
the problem at hand.

Fred
Posted by James Byrne (byrnejb)
on 2013-03-06 15:46
(Received via mailing list)
On Wed, March 6, 2013 04:54, Frederick Cheung wrote:
> Where is this code? in a model, in module that is included into
> various models, somewhere else?

It is contained in a model:

class Currency < ActiveRecord::Base
  include HLLActiveRow

  after_save( :save_errors )
.  .  .
  # save
  #
  # Override AR save method to catch DBMS specific errors
  # such as uniqueness constraint violations
  def save( * )
    begin
      puts( "I go" )
      super
      puts( "I return" )
      rescue ActiveRecord::StatementInvalid => this_exception
        errors.add( currency_code, hll_ar_exception( this_exception ) )
        # errors.add_to_base(hll_ar_exception(this_exception))
        false
    end
  end
.  .  .

I see that in the new persistence layer save is now deifined thus:



# File activerecord/lib/active_record/persistence.rb, line 82
def save(*)
  begin
    create_or_update
  rescue ActiveRecord::RecordInvalid
    false
  end
end

Which bears some similarity to what I was doing for previous versions.
 The rescue was added to persistence.rb in this commit two years ago:

https://github.com/rails/rails/commit/656e7b08073f...


But my code has been working subsequent to this up to v3.2. Something
else has changed to cause the effect I am now experiencing.  The main
problem from my point of view is that I expect the save call to return
to the invoking method immediately after the point super is invoked
and that is not happening.  That is what I find astonishing.

>
> As an aside recent versions of rails raise
> ActiveRecord::RecordNotUnique in
> such cases, although this is a subclass of
> ActiveRecord::StatementInvalid
> so shouldn't change behaviour as far as you're concern. You're also
> changing the signature of save although I don't think that is related
> to the problem at hand.

As far as I can see, save rescues but does not re-raise such
exceptions so I do not know where it is being returned from.


--
***          E-Mail is NOT a SECURE channel          ***
James B. Byrne                mailto:ByrneJB@Harte-Lyne.ca
Harte & Lyne Limited          http://www.harte-lyne.ca
9 Brockley Drive              vox: +1 905 561 1241
Hamilton, Ontario             fax: +1 905 561 0757
Canada  L8E 3C3
Posted by James Byrne (byrnejb)
on 2013-03-07 09:36
(Received via mailing list)
On Wed, March 6, 2013 04:54, Frederick Cheung wrote:
>
> As an aside recent versions of rails raise
> ActiveRecord::RecordNotUnique in
> such cases, although this is a subclass of
> ActiveRecord::StatementInvalid
> so shouldn't change behaviour as far as you're concern. You're also
> changing the signature of save although I don't think that is related
> to the problem at hand.
>


On: Tue Mar 5, 2013 1:48 pm ((PST)), "Les Nightingill"
codehacker@comcast.net lesnightingill wrote:
>
> perhaps the exception being raised is not
> ActiveRecord::StatementInvalid.
>
> suggest trying rescue with no exception specified to see if there is a
> different exception being raised.
>
> Les


Bingo!  Rails-3.2.12 implements code similar to that I was providing
in  hll_ar_exception( this_exception ) ) and actually returns the
exact message from PG that I was checking for therein.

  def save( * )
    begin
      puts( "I go" )
      super
      puts( "I return" )
    rescue => e
      puts( e.inspect )
      false
    end
  end


Using the default profile...
.................I go
#<ActiveRecord::RecordNotUnique: PG::Error: ERROR:  duplicate key
value violates unique constraint "idxu_currencies_currency_code"
DETAIL:  Key (currency_code)=(JPY) already exists.
: INSERT INTO "currencies" ("changed_at", "changed_by", "created_at",
"created_by", "currency_code", "currency_name", "discount_factor",
"effective_from", "fx_accounting_factor", "fx_accounting_margin",
"is_payable", "is_receivable", "premium_factor", "superseded_after")
VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14)
RETURNING "id">
..F-

(::) failed steps (::)

Mystery solved.  Thanks.

--
***          E-Mail is NOT a SECURE channel          ***
James B. Byrne                mailto:ByrneJB@Harte-Lyne.ca
Harte & Lyne Limited          http://www.harte-lyne.ca
9 Brockley Drive              vox: +1 905 561 1241
Hamilton, Ontario             fax: +1 905 561 0757
Canada  L8E 3C3
Please log in before posting. Registration is free and takes only a minute.
Existing account (Switch to SSL-encrypted connection)
NEW: Do you have a Google/GoogleMail or Yahoo account? No registration required!
Log in with Google account | Log in with Yahoo account
No account? Register here.