What's the right kind of validation to include for subordinate models? For example, let's say you've got books with chapters. The number of chapters per book is determined when the book is first created.

class Book < ActiveRecord::Base
  has_many :chapters

  def build_chapters(count)
    (1..count).each do |i| => i)

class Chapter < ActiveRecord::Base
  belongs_to :book

  validates_presence_of :book_id, :sequence_number

class BooksController < ApplicationController
  def create
    @book =[:book])
    @book.build_chapters(4) #to simplify example, hardcode number of chapters
    # View-related code omitted for simplicity

When I run this I get one "chapters is invalid" error per chapter (4 errors when hard-coded like the example). Explicitly setting the :book_id in the build call doesn't help.

However, if I save the book before adding chapters it works, no errors. If I take out the validation in Chapter it works, no errors. But neither of those workarounds makes me happy. A book shouldn't be allowed to exist in the database without its chapters, and a chapter shouldn't be allowed to exist in the database without being linked to a book. What's the right way to enforce the relationship constraints?

I'm new to ruby and to rails, so it's entirely possible I'm just not thinking in rails-ese yet. Please edumacate me.

+1  A: 

This is how ActiveRecord works now. Validations work great but for single models only. Month ago I had a similar problem. But I haven't found any clean solution. Therefore I've voted for this idea. It seems that these problems are result of AR core design and cannot be easily solved.

I guess that someone can think up some tricky solution with transactions but in my opinion you should accept any workaround you can implement and move on. BTW I am not the duct tape programmer.

Greg Dan

Like you, I'm new to Ruby and Rails, but would validates_associated help? Details in the API docs at

Rob Wilkerson
Looks like that doesn't validate that the association is correct, only that associated objects are valid in their own right.