Search code examples
ruby-on-railsactiverecordruby-on-rails-4rails-activerecord

Retrieving a single record from an ActiveRecord/Rails query


I issue queries like the following that retrieve exactly 0 or 1 records:

car = Car.where(vin: '1234567890abcdefg')

What's returned is of course a list of cars of length 1. So I end up adding .first at the end of the query:

car = Car.where(vin: '1234567890abcdefg').first

Seems like there should be a better way in Rails. Does something like .onlyOne exist which would return just a single Car and throw an exception if there was more than 1?

car = Car.where(vin: '1234567890abcdefg').onlyOne

or

car = Car.onlyOne(vin: '1234567890abcdefg')

Solution

  • Rails 4

    You want find_by(vin: 123), and you can pass find_by a hash of any field/value names to find by.

    eg.

    Car.find_by(vin: '123')
    

    This will return nil if no car with that vin is found, or a single car matching that vin value. If you add a bang (ie. find_by!) it will raise an exception if no car with that vin is found.

    If you want to raise an error if more than one is found, that is something you'll have to write for yourself. If you should never get into the case where more than one car has the same vin, the best way to do this would be with a uniqueness validation on the Car model, eg.

    class Car < ActiveRecord::Base
      validates_uniqueness_of :vin # or validates :vin, unique: true
    end
    

    Rails 3

    You want find_by_vin (and you can replace vin with the name of any of your attributes.

    eg.

    Car.find_by_vin('123')
    

    This will return nil if no car with that vin is found, or a single car with that vin value. If you add a bang (ie. find_by_vin!) it will raise an exception if no car with that vin is found.

    For more information: http://guides.rubyonrails.org/active_record_querying.html#retrieving-objects-from-the-database