undefined method for 1:Fixnum

Hi all,

What I am trying to do:

1) Search for books at a specific school 2) Iterate through each book and find all its related subbooks where the book state is of a specific type 3) Return an array of those subbooks for each book 4) Since the array will have subarrays of the subbooks, flatten them into one big array 5) then return the subbook with the lowest sequence number

What I did:

subbook = Subbook.get_for_assignment(site, :available_for_assignment)

def self.get_for_assignment(site,book_state)

    books = Book.where(:location_id => site, :location_type => 'Site').all

    available_books = books.each.map do |book|       book.subbooks.where(:book_state_id => BookState[:available_for_assignment].id)     end

    raise ApplicationError, "Book out of order" unless available_books.size > 0

    available_book = available_books.flatten.map(&:sequence).min #available_books.flatten.first (temporary although inaccurate fix)     if available_book.sequence > 100       available_book.book.update_attributes! :book_state_id => BookState[:distributed].id     end     available_book   end

The results:

"undefined method sequence for 1:Fixnum"

This line right here:

available_books.flatten.map(&:sequence).min

produces the above error. It's this part "map(&:sequence).min" that is causing it. Basically I am flattening the array of subbooks and then searching the one which has the lowest value for the sequence attribute, corresponding to a sequence field in the subbooks table.

thanks for response

The problem is that the "array of subbooks" isn't an array of subbooks, it's an array of something which includes some integers. Hence, when you iterate it, you get an undefined method for Integer.

I would be inspecting the available_books array in debug (or the console) and seeing what it really consists of.

BTW, I'd also suggest that the whole "get_for_assignment" method could be achieved by a scope with the appropriate conditions...

Thanks for response. I checked with logger and it is indeed an array:

logger.info "Is array? #{available_books.flatten.is_a?(Array)}" #outputs: true

It's an array of subbook objects: <Subbook:0x10bef7de0>#<Subbook:0x10bef7ca0>#<Subbook: 0x10bef7bb0>#<Subbook:0x10bef7ae8>#<Subbook:0x10bec0ed0>#<Subbook: 0x10bec0db8>#<Subbook:0x10bec0cc8>#<Subbook:0x10bec0840>#<Subbook: 0x10bea9140>#<Subbook:0x10bea8fd8>#<Subbook:0x10bea8e70>#<Subbook: 0x10bea8c90>#<Subbook:0x10be8a998>#<Subbook:0x10be8a678>#<Subbook: 0x10be8a268>#<Subbook:0x10be86c80>#<Subbook:0x10be780e0>#<Subbook: 0x10be78018>#<Subbook:0x10be77f28>#<Subbook:0x10be77e88>#<Subbook: 0x10be69b58>#<Subbook:0x10be69ab8>#<Subbook:0x10be699a0>#<Subbook: 0x10be698d8>#<Subbook:0x10be63d98>#<Subbook:0x10be63cf8>#<Subbook: 0x10be63b90>#<Subbook:0x10be63af0>#<Subbook:0x10be5d3d0>#<Subbook: 0x10be5cd90>#<Subbook:0x10be5c4f8>#<Subbook:0x10be5c3e0>#<Subbook: 0x10be53768>#<Subbook:0x10be53420>#<Subbook:0x10be532e0>#<Subbook: 0x10be531f0>#<Subbook:0x10be46180>#<Subbook:0x10be45e88>#<Subbook: 0x10be45ac8>#<Subbook:0x10be45960>

Now when I look at above, it appears to reference the class itself, and since Active Record converts fields to instance methods, the class itself doesn't have access to the sequence instance method, only instances of the class.

Is this the problem and how would I address it?

Thanks for response

hmmm, this returns true as well:

    logger.info "is true? #{available_books.flatten.first.respond_to? ('sequence')}"

This line right here:

available_books.flatten.map(&:sequence).min

produces the above error. It's this part "map(&:sequence).min" that is causing it. Basically I am flattening the array of subbooks and then searching the one which has the lowest value for the sequence attribute, corresponding to a sequence field in the subbooks table.

I suspect the error is actually being raised on the next line where you do

available_book.sequence > 100

since you've set available_book to available_books.flatten.map(&:sequence).min, ie available_book is the smallest sequence number

Fred

actually you are right. my intention was to get the object with the smallest sequence number, not return the sequence number itself. The ruby documentation says this: "Returns the object in enum with the minimum value. " for min. Hence, I thought it would return the object.

actually you are right. my intention was to get the object with the smallest sequence number, not return the sequence number itself. The ruby documentation says this: "Returns the object in enum with the minimum value. " for min. Hence, I thought it would return the object.

It depends what you are iterating over - because you first called map(&:sequence) the enumerable in question was the array of sequence numbers. If you want to get back the object with the smallest sequence value you should drop the call to map and either use the block form of min or min_by

Fred

Good catch, Fred.