4.4. first, last and all

In certain cases, you may need the first record, or the last one, or perhaps even all records. Conveniently, there is a ready-made method for each case. Let's start with the easiest ones: first and last.
$ rails console
Loading development environment (Rails 3.2.9)
>> Country.first
  Country Load (0.1ms)  SELECT "countries".* FROM "countries" LIMIT 1
=> #<Country id: 1, name: "Germany", population: 81831000, created_at: "2012-11-14 11:14:55", updated_at: "2012-11-14 11:14:55">
>> Country.last
  Country Load (0.3ms)  SELECT "countries".* FROM "countries" ORDER BY "countries"."id" DESC LIMIT 1
=> #<Country id: 4, name: "Netherlands", population: 16680000, created_at: "2012-11-14 11:19:51", updated_at: "2012-11-14 11:19:51">
>>
And now all at once with all:
>> Country.all
  Country Load (0.4ms)  SELECT "countries".* FROM "countries" 
=> [#<Country id: 1, name: "Germany", population: 81831000, created_at: "2012-11-14 11:14:55", updated_at: "2012-11-14 11:14:55">, #<Country id: 2, name: "France", population: 65447374, created_at: "2012-11-14 11:16:49", updated_at: "2012-11-14 11:16:49">, #<Country id: 3, name: "Belgium", population: 10839905, created_at: "2012-11-14 11:18:21", updated_at: "2012-11-14 11:18:21">, #<Country id: 4, name: "Netherlands", population: 16680000, created_at: "2012-11-14 11:19:51", updated_at: "2012-11-14 11:19:51">]
>>
But the objects created by first, last and all are different. first and last return an object of the class Country and all of course returns an array of such objects:
>> Country.first.class
  Country Load (0.3ms)  SELECT "countries".* FROM "countries" LIMIT 1
=> Country(id: integer, name: string, population: integer, created_at: datetime, updated_at: datetime)
>> Country.all.class
  Country Load (0.3ms)  SELECT "countries".* FROM "countries" 
=> Array
>>
If Country.all returns an array, then we should also be able to use iterators (see the section called “Iterators” and the section called “Iterator each”), right? Yes, of course! That is the beauty of it. Here is a little experiment with each:
>> Country.all.each do |country|
?>   puts country.name
>> end
  Country Load (0.3ms)  SELECT "countries".* FROM "countries" 
Germany
France
Belgium
Netherlands
=> [#<Country id: 1, name: "Germany", population: 81831000, created_at: "2012-11-14 11:14:55", updated_at: "2012-11-14 11:14:55">, #<Country id: 2, name: "France", population: 65447374, created_at: "2012-11-14 11:16:49", updated_at: "2012-11-14 11:16:49">, #<Country id: 3, name: "Belgium", population: 10839905, created_at: "2012-11-14 11:18:21", updated_at: "2012-11-14 11:18:21">, #<Country id: 4, name: "Netherlands", population: 16680000, created_at: "2012-11-14 11:19:51", updated_at: "2012-11-14 11:19:51">]
>>
So can we also use .all.first as an alternative for .first? Yes, but it does not make much sense. Have a look for yourself:
>> Country.first
  Country Load (0.2ms)  SELECT "countries".* FROM "countries" LIMIT 1
=> #<Country id: 1, name: "Germany", population: 81831000, created_at: "2012-11-14 11:14:55", updated_at: "2012-11-14 11:14:55">
>> Country.all.first
  Country Load (0.3ms)  SELECT "countries".* FROM "countries" 
=> #<Country id: 1, name: "Germany", population: 81831000, created_at: "2012-11-14 11:14:55", updated_at: "2012-11-14 11:14:55">
>> exit
$ 
Even in our mini database, we can already see that there is a difference in speed of 0.1 milliseconds. With Country.first, the first record is retrieved via SQL in the database with a LIMIT 1 and output by ActiveRecord as individual object of the country class. With Country.all.first, the whole table is first read in as array via SELECT "countries".* FROM "countries" and the first element of this array is pulled out. This is a luxury you can afford in this tiny application, but just imagine what would happen if you had a database with many millions of records.

Warning

SQL databases do not normally sort the results of a SELECT * FROM xyz automatically. The database can determine the order of the records itself. As a result, with a LIMIT 1 and such an amount of data we can not be completely sure that we get the record that we humans would logically consider to be the first record. This effectively means that with a Country.first we would also not necessarily get the first record. It is up to the SQL database to decide whether to sort records in a different order, for example for performance reasons. If we want to be absolutely sure that we get the record that is the first one in our logic, we need to work with the method order (see the section called “order and reverse_order”):
$ rails console
Loading development environment (Rails 3.2.9)
>> Country.order(:id).first
  Country Load (0.1ms)  SELECT "countries".* FROM "countries" ORDER BY id LIMIT 1
=> #<Country id: 1, name: "Germany", population: 81831000, created_at: "2012-11-14 11:14:55", updated_at: "2012-11-14 11:14:55">
>> exit
$
As you can see in SQL, the SELECT "countries".* FROM "countries" ORDER BY id LIMIT 1 first sorts the table by id and then outputs the first line.
Usually, the SQL database works exactly as you would expect and you get the first record with Country.first. But if you want to be absolutely sure, you should always use an order.
The easiest way of doing this is via default_scope. For that you have to declare a default_scope in the model file app/models/country.rb
class Country < ActiveRecord::Base
  attr_accessible :name, :population

  default_scope order(:id)
end
Once that is done ActiveRecord takes care of it automatically:
$ rails console
Loading development environment (Rails 3.2.9)
>> Country.first
  Country Load (0.1ms)  SELECT "countries".* FROM "countries" ORDER BY id LIMIT 1
=> #<Country id: 1, name: "Germany", population: 81831000, created_at: "2012-11-14 11:14:55", updated_at: "2012-11-14 11:14:55">
>> exit
$

Updates about this book will be published on my Twitter feed.