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