Type mismatch because of misled array index


Most times I look up a list of books I want to know a page reference for
each one, so the views that display booklists expect an array of
two-element arrays, constructed via a method in the model like so:
(class Category)
def book
@book = Array.new
self.bookshelves.each { |x| @book << [x.book, x.pages] }
return @book

When I get the list of all books that a user has listed, I have no page
numbers in that table, nor do I want any. I tried to fill the second
slot with nils or empty strings, since that what x.pages would be for a
book with no page reference anyway.
(class User)
def book
@books = []
self.books.each { |b| @books << [b, nil] }
return @books

But when I call that method in my controller,

when ‘user’
@books = User.find(params[:id]).book

I get this error:

ActiveRecord::AssociationTypeMismatch in View#bookslist

Book expected, got NilClass
RAILS_ROOT: /Volumes/TRAVELDRIVE/sandcastle/script/…/config/…

Application Trace | Framework Trace | Full Trace
raise_on_type_mismatch' #{RAILS_ROOT}/vendor/rails/activerecord/lib/active_record/associations/association_collection.rb:24:in<<’
each' #{RAILS_ROOT}/vendor/rails/activerecord/lib/active_record/associations/association_collection.rb:23:in<<’
transaction' #{RAILS_ROOT}/vendor/rails/activerecord/lib/active_record/transactions.rb:91:intransaction’
transaction' #{RAILS_ROOT}/vendor/rails/activerecord/lib/active_record/associations/association_collection.rb:22:in<<’
#{RAILS_ROOT}/app/models/user.rb:106:in book' #{RAILS_ROOT}/app/models/user.rb:106:ineach’

I changed the nil in User.book to ‘’, and it said “Book expected, got
String”, so it’s clear that it is referring to the second argument
there. But I don’t even see how it knows to ‘expect’ a book from that
context. If I change User.book to put a book in the second array slot,
like so:

self.books.each { |b| @books << [b, b] }

then WEBrick starts churning up as much of my cpu as it can get
(60-70%), and mysqld also gets quite a workout (3% of cpu).

My suspicion is that I’ve once again run afoul of some reserved words,
because equivalent code seems to work elsewhere.