Question

I am building a simple book check out application. One of the things that I need to do is determine if a book is checked out. I have my associations between my people and book classes setup through a book_check_out class. My goal is to use the checked_out property of book to determine if a book is presently checked out. However, in my present implementation when a book is not checked out and I reference book.checked_out.XXX I receieve the error "You have a nil object when you didn't expect it!" My goal is to use book.checked_out for two purposes in some views show that yes, that book is checked out and in other views show who it is presently checked out to.

class Person < ActiveRecord::Base
  has_many :book_check_outs
  has_many :books, :through => :book_check_outs
end

class Book < ActiveRecord::Base

  has_many :book_check_outs
  has_many :people, :through => :book_check_outs

  def checked_out
    book_check_outs || false
  end
end

class BookCheckOut < ActiveRecord::Base
  belongs_to :book
  belongs_to :person
end
Was it helpful?

Solution

When you've got a boolean outcome, something that can either be true or false (for instance, a book can either be checked out or not), you need to assume a default for the outcome. In this case, we can assume it's false (the book is not checked out by default).

In the book model, remove your has_many :checked_out line and create a method with the same name:

def checked_out
  book_check_outs || false
end

This should return either the BookCheckOuts, or if there are none associated with the instance, FALSE. It gives you a quick, easy, foolproof method of checking an association and removing the nasty nil object error.

Edit You could also just return TRUE or FALSE, and not return the most recent checkouts by checking that book_check_outs is nil or not. Rails provides a method called blank? which calls both nil? and empty?

def checked_out
  !book_check_outs.blank?
end

I love Ruby :)

OTHER TIPS

I forget if it actually matters or not, but for clarity's sake you might want to put the has_many relation above the has_many :through relation.

I am also not sure you should be declaring in the Book class that it has_many :BookCheckOuts AND it has_one :checked_out, since the checked_out actually is a BookCheckOut which you declared it having many of above.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top