Eqbal
Eqbal

Reputation: 1879

find() with nil when there are no records

In my current rails program when I use something like

 user = User.find(10)

When there is no user with ID=10 , I will have exception like :

ActiveRecord::RecordNotFound: Couldn't find User with ID=10

Can I get nil instead of raising exception so when I do something like :

unless user = Challenge.find(10)
  puts "some error msg"         
end

I just want to get nil when there is no records and I don't want to use begin/rescue

Thanks

Upvotes: 128

Views: 63547

Answers (8)

Cristiano Mendonça
Cristiano Mendonça

Reputation: 1282

For those struggling with mongoid, it turns out that both find and find_by methods will raise exception - no matter your rails version!

There is an option (namely raise_not_found_error) which can be set to false, but when falsey makes find method doesn't to raise exception as well.

Thus the solution for mongoid users is the disgusting code:

User.where(id: 'your_id').first # argghhh

Upvotes: 4

apneadiving
apneadiving

Reputation: 115511

Yes, just do:

Challenge.find_by_id(10)

For Rails 4 and 5:

Challenge.find_by(id: 10)

Upvotes: 221

mohamed-ibrahim
mohamed-ibrahim

Reputation: 11137

just as simple as:

user = User.find(10) rescue nil

Upvotes: -1

Alanoud Just
Alanoud Just

Reputation: 337

You can use find_by with the required attribute (in your case the id) this will return nil instead of giving an error if the given id is not found.

user = Challenge.find_by_id(id_value)

or you could use the new format:

user = Challenge.find_by id: id_value

You could also use where but you have to know that where return an active record relation with zero or more records you need to use first to return only one record or nil in case zero records return.

user = Challenge.where(id: id_value).first

Upvotes: 1

morgler
morgler

Reputation: 1809

Why don't you simply catch the exception? Your case looks exactly like what exceptions were made for:

begin
  user = User.find(10)
rescue ActiveRecord::RecordNotFound
  puts "some error msg"
end

If you want to recover from the error in the rescue block (e.g. by setting a placeholder user (null pattern)), you can continue with your code below this block. Otherwise you might just put all your code for the "happy case" in the block between "begin" and "rescue".

Upvotes: 5

hattila91
hattila91

Reputation: 683

In Rails 4, dynamic finders - such as find_by_id which was used in the accepted answer - were deprecated.

Moving forward, you should use the new syntax:

Challenge.find_by id: 10

Upvotes: 37

beanie
beanie

Reputation: 1448

you can do this a bit hackish, just use the ActiveRecord Query Interface.

this will return nil, instead of raising a Exception

  User.where(:id => 10).first

Upvotes: 18

tonymarschall
tonymarschall

Reputation: 3882

You can try this Challenge.exists?(10)

Upvotes: 4

Related Questions