0

I'm new to RoR and I'm now confusing about updating data to databases. And I studied RoR just recently, if the question is unclear please let me know.

Assume I created a table "book", with 3 columns: "name", "price", and "author".

When implementing action update in rails, I'll do the following:

def update
  @book = Book.find(params[:id])
  if @book.update({'name': 'Ruby tutorial'})
    redirect_to @book
  else
    render 'edit'
  end
end

This will update the record in database by

if @article.update({'name': 'Ruby tutorial'})

In order to test some failure cases, I modified the database column "name" to "nane" on purpose, I thought the statement if @article.update will fail due to the wrong table field name and the code will go to else block. Because I thought the statement is for checking whether rails saves the record into the database successfully.

However, my code throws exception because of the wrong field name instead of going to the else block.

I got confused about this behavior, what kinds of situation will cause if @article.update(params) fail and go to the else block?

Is if @article.update(params) for just validating form data? i.e, checking whether the hash key sent from the form is correct, as for database side(field name or database connection error) , is not the business of this statement so it will throw exception.

Thanks a lot.

Wilson.Wang
  • 69
  • 1
  • 8
  • It goes to the else if the condition `@book.update` returns false, but in this case does not return any value because of the error. – iGian Jun 11 '18 at 12:02
  • I originally thought it would return false and I knew the behavior now. Thanks for your help. – Wilson.Wang Jun 12 '18 at 07:06

1 Answers1

2
@book.update(nane: 'name')

will throw an exception ActiveModel::UnknownAttributeError: unknown attribute.

if is not an exception handler.

The purpose of using if and else block here is to handle the negative scenario (update failed due to some validation failures).

update(name: '')

with presence validation on name column will not throw an exception. It will return false. If you do not have the if / else block here and simply update statement, you will not know whether the update has succeeded or not.

The other way of handling this is to use update with !. Adding ! makes the statement to throw an exception for any failures.

begin
  update!(name '')
rescue Exception
  render 'edit'
end

Rescuing exception like above is a bad style of handling exception.I have removed

rescue Exception
  //some action //
end

You must learn why from here Why is it bad style to `rescue Exception => e` in Ruby?.

You can also handle specific RecordInvalid exception like this.

begin
  update!(name '')
rescue ActiveRecord::RecordInvalid => invalid
   // some action //
end
Suganya Selvarajan
  • 962
  • 1
  • 11
  • 33
  • Rescuing `Exception` is [seldom a good idea](https://stackoverflow.com/questions/10048173/why-is-it-bad-style-to-rescue-exception-e-in-ruby) - not good advice for a newcomer to Rails. Perhaps update the answer to avoid using this? – SRack Jun 11 '18 at 15:00
  • Got it! Thanks for your clear explanation. So I have to do the exception handling if DB error occurs. – Wilson.Wang Jun 12 '18 at 07:08
  • @Wilson.Wang if you feel my post answers your question, you can mark it as the answer – Suganya Selvarajan Jun 13 '18 at 06:40
  • But how to test this false condition, don't we need to test `else render 'edit' ? – Meilan Apr 10 '20 at 01:33