ActiveRecord rollback in Rails

Viewed 128
Rails 5.2

I have a partial:

views/authors/_add_author_comment.html/slim

= form_for :author_note, url: author_notes_url, method: :post do |f|
  = f.hidden_field :author, value: @book.author
  = f.text_area :comment
  button.btn.btn-primary type="button"
  = f.submit t('authors.show.submit_comment')   

In my controllers/author_notes_controller.rb, I have:

def create
  @author_note = AuthorNote.new(author: params[:author_note][:author], user_id: current_user.id, comment: params[:author_note][:comment])
  @author_note.save
end

When the form displays (part of a larger view), and I fill the comment out, and click on "Submit Comment", the comment is not saved. In the console, I see the following:

Processing by AuthorNotesController#create as HTML

Parameters: {"utf8"=>"✓", "authenticity_token"=>"Jju1cpsLjXLY/TaF9p/Zkh8JQ/+KajjxwQHgNU4tNU9bjL8BiZQ8xL3S7ske1KqflOPHVaB9UTWRvgxNqzLd7Q==", "author_note"=>{"author"=>"John Dow", "comment"=>"This is a test"}, "commit"=>"Save Note"}
User Load (0.4ms)  SELECT  `users`.* FROM `users` WHERE `users`.`id` = '5' ORDER BY `users`.`id` ASC LIMIT 1
↳ app/controllers/author_notes_controller.rb:23
User Load (0.3ms)  SELECT  `users`.* FROM `users` WHERE `users`.`id` = '5' LIMIT 1
↳ app/controllers/author_notes_controller.rb:23
 (0.2ms)  BEGIN
↳ app/controllers/author_notes_controller.rb:28
 (0.1ms)  ROLLBACK
↳ app/controllers/author_notes_controller.rb:28
No template found for AuthorNotesController#create, rendering head :no_content
Completed 204 No Content in 60ms (ActiveRecord: 10.6ms)

Why is it ActiveRecord rolling back, and not saving the note to the author_notes table?

Resolution:

the author_note.rb model, I had: belongs_to :book, I commented it out

3 Answers

You didn't include your AuthorNote model, there might be some validation constraints that prevents the author_note from being saved.

Your code also doesn't handle validation error, so you might want to do that. But you can simply check for errors like:

def create
  @author_note = AuthorNote.new(author: params[:author_note][:author], user_id: current_user.id, comment: params[:author_note][:comment])
  @author_note.save
  # puts works too
  logger.debug "author_note save error: #{@author_note.errors.full_messages.join(' ')}"
end

This is highly likely due to rails 5 making belongs_to association required by default.

What that means is from rails > 5, if you define belongs_to on a model and if the corresponding record is not present. In this case, book_id should be nil in the AuthorNote record. ActiveRecord will error it out and rollback the transaction.

To fix this, instead of commenting out the belongs_to relationship all together, you can make it optional (beacause, removing the relationship might break the system)

class AuthorNote < ApplicationRecord
  belongs_to :book, optional: true
end

Use ! along with the save or create that will show the error message Object.save! or Object.create!

def create
   @author_note = AuthorNote.new(author: params[:author_note][:author], user_id: current_user.id, comment: params[:author_note][:comment])
   @author_note.save!
end

OR

def create
   @author_note = AuthorNote.create!(author: params[:author_note][:author], user_id: current_user.id, comment: params[:author_note][:comment])
end
Related