The key_len column in the EXPLAIN shows you how far it got through the index, based on the size of the columns. In your case it says 4 which if device id is of type INT it just read one column in the index (though there is probably only one column in that index)
If you have multiple single column indexes it won't help you here. The mysql query planner probably correctly guessed the table scan was a better option than hash joining the results of two seeks given the machine's limited memory. It also probably underestimated the cost of disk IO on a virtual machine though.
ActiveRecord is notorious for generating terrible, terrible SQL.
Edit: What I would expect to see would be index scan on device id, then sort + limit. So the important factor would be rows per device, not total rows.
The SQL was pretty simple I believe..select * from location where device_id = ? order by date_added desc limit 6...something like that.
Edit: Also, I don't know how much it matters, but MySQL probably only has ~256mb memory available to it (its hosted on a Xen box).
MySQL has a lot of very specific limitations about when it will and will not use the available indices. It also matters how you created the indices (one index on multiple columns vs multiple indices on individual columns).
For example, if you created a single index with the columns (date_added, device_id) MySQL would not be able to use the index since device_id is the second part of the index, not the first and thus not available for use in the WHERE clause.
See http://dev.mysql.com/doc/refman/5.1/en/mysql-indexes.html for more limitations.