Ask A Question

Notifications

You’re not receiving notifications from this thread.

Form item disappearing when failing nested validations

Nino Rosella asked in Rails

I have a Rails 5 app, and I'm having a problem with validations using the Cocoon gem with nested, dynamic forms. 

When a validation on my Book model fails, and my create action renders :new, the Authorfield disappears from my new book form.

One thing I've noticed is that when the validation fails, rather than passing authors back into my form, it's passing book_authors back because of the line @book.book_authors.build(author_id: author.id) in my create action. Pretty sure this is the cause of my issue, but don't know how to fix it.

books_controller.rb

class BooksController < ApplicationController
...

def new
@book = Book.new
@book.authors.build
end

def create
@book = current_user.books.create(book_params)
params[:book][:authors_attributes].each do |k,v|
author = Author.find_or_create_by(name: v['name'], user_id: current_user.id)
@book.book_authors.build(author_id: author.id)
end

if @book.save
    redirect_to book_path(@book)
else
  render :new
end

end

private

def book_params
params.require(:book).permit(:title, :published_city, :description, author_ids:[])
end

def author_params
params.require(:book).permit(authors_attributes: [:id, :name, :_destroy])
end
end

book.rb

class Book < ApplicationRecord

has_many :book_authors
has_many :authors, through: :book_authors
belongs_to :user

accepts_nested_attributes_for :authors, allow_destroy: true
validates :title, :published_city, presence: true
validates_associated :authors, inverse_of: :book
end

book_author.rb

class BookAuthor < ApplicationRecord
belongs_to :book
belongs_to :author
end
author.rb

class Author < ApplicationRecord
has_many :book_authors
has_many :books, through: :book_authors

validates :name, presence: true
end

new.html.erb

<%= form_for @book do |f| %>
<%= f.text_field :title, required: true %>
<%= f.text_area :description %>
<div id='authors'>
<%= f.fields_for :authors do |author| %>
<%= render 'author_fields', :f => author %>
<% end %>
<div class='links'>
<%= link_to_add_association 'Add another author', f, :authors %>
</div>
</div>
<%= f.text_field :published_city %>
<%= f.submit %>
<% end %>

Reply
Hey your `create` action shouldn't need to loop over the `book_params` to create params.

I quickly created a sample app that shows how I use `cocoon` with many-to-many relationships.

It is at https://github.com/dylanpinn/rails-bookstore. Let me know how you go.
Reply
Hey Dylan,

Just want to thank you for going to the effort to build this! Love the GoRails community.

However, when I run that code and create a new book, but leave the author field blank, it doesn't seem to be hitting the validation. So I'm able to create a book with no author. Any ideas why this might be?
Reply
Try adding `validates :authors, presence: true` to the Book model.
Reply
Yep, works a charm.

Thank you so much Dylan.
Reply
Join the discussion
Create an account Log in

Want to stay up-to-date with Ruby on Rails?

Join 82,329+ developers who get early access to new tutorials, screencasts, articles, and more.

    We care about the protection of your data. Read our Privacy Policy.