find () dengan nil jika tidak ada record

96

Dalam program rel saya saat ini ketika saya menggunakan sesuatu seperti

 user = User.find(10)

Ketika tidak ada pengguna dengan ID = 10, saya akan memiliki pengecualian seperti:

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

Bisakah saya mendapatkan nihil alih-alih meningkatkan pengecualian jadi ketika saya melakukan sesuatu seperti:

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

Saya hanya ingin mendapatkan nol jika tidak ada catatan dan saya tidak ingin menggunakan begin / rescue

Terima kasih

Eqbal
sumber

Jawaban:

172

Ya, lakukan saja:

Challenge.find_by_id(10)

Untuk Rails 4 dan 5:

Challenge.find_by(id: 10)
apneadiving
sumber
11
aneh! Saya tidak pernah menyangka bahwa hasilnya .find_by_*akan nihil dan .findtidak.
ddavison
Ini telah berubah di rel 4, lihat jawaban stackoverflow.com/a/26885027/1438478 ini untuk cara baru menemukan item dengan atribut tertentu.
Fralcon
Saya menemukan masalah aneh dengan Rails 4.2 di mana ketika Anda meneruskan hash sebagai 'x' untuk Something.find_by(id: x)itu akan membuat pernyataan SQL dengan semua pasangan atribut / nilai dari hash sebagai bagian dari klausa WHERE. Sepertinya Rails bug bagi saya.
Tilo
Rails (3, 4 atau 5) menghasilkan find_by_...pencari dinamis untuk setiap atribut yang dimiliki model :id. Jadi, Challenge.find_by_id(10)harus bekerja terlepas dari versi Rails.
Arta
Seperti yang ditentukan oleh @MohamedIbrahim di bawah ini, Anda juga dapat melakukan:Challenge.find(10) rescue nil
Hallgeir Wilhelmsen
31

Di Rails 4, pencari dinamis - seperti find_by_idyang digunakan dalam jawaban yang diterima - tidak digunakan lagi.

Ke depannya, Anda harus menggunakan sintaks baru:

Challenge.find_by id: 10
hattila91
sumber
4
Jika ada orang lain yang bingung dengan ini seperti saya: Challenge.find_by(id: 10)apakah cara lain untuk menulis ini
Devin Howard
14

Anda dapat melakukan ini sedikit hackish, cukup gunakan Antarmuka Kueri ActiveRecord.

ini akan menghasilkan nol, bukannya memunculkan Exception

  User.where(:id => 10).first
beanie
sumber
Alasan untuk menggunakan ini daripada find_by_idkarena portabel dari Rails 3 ke 4. Di rel 4, ini find_by(:id => 10).
Gene
5

Mengapa Anda tidak menangkap pengecualian saja? Kasus Anda terlihat persis seperti pengecualian yang dibuat untuk:

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

Jika Anda ingin memulihkan dari kesalahan di blok penyelamatan (misalnya dengan mengatur pengguna placeholder (pola nol)), Anda dapat melanjutkan dengan kode Anda di bawah blok ini. Jika tidak, Anda mungkin hanya memasukkan semua kode Anda untuk "kasus bahagia" di blok antara "mulai" dan "penyelamatan".

morgler
sumber
Btw: Anda bahkan tidak memerlukan begin…endblok, jika Anda sudah memiliki blok seperti metode pengontrol. Dalam hal ini, satu-satunya saluran tambahan yang Anda butuhkan adalah rescuesaluran tersebut. Jauh lebih elegan dan lebih mudah ditangani daripada memeriksa nildengan ifpernyataan.
morgler
4

Anda bisa mencobanya Challenge.exists?(10)

tonymarschall.dll
sumber
7
itu akan menjadi permintaan sql ekstra
fl00r
Meski begitu saya pikir ini lebih baik mencari pengujian
SomeSchmo
gunakan jika Anda tidak peduli dengan nilai yang dikembalikan tetapi hanya tentang keberadaan catatan di DB
Filip Bartuzi
4

Bagi mereka yang berjuang dengan mongoid , ternyata keduanya finddan find_bymetode akan menimbulkan pengecualian - tidak peduli versi rel Anda!

Ada opsi (yaitu raise_not_found_error ) yang bisa disetel ke false, tetapi ketika falsey membuat findmetode tidak memunculkan eksepsi juga.

Jadi solusi untuk pengguna mongoid adalah kode yang menjijikkan:

User.where(id: 'your_id').first # argghhh
Cristiano Mendonça
sumber
Apa pendapat Anda tentang solusi penyelamatan nihil oleh mohamed-ibrahim? Tampak lebih elegan dari .where(email: params[:email]).firstpada saya.
Wylliam Judd
1
Saya lebih suka tidak menggunakan rescuesintaks itu karena dapat menyembunyikan masalah seperti kesalahan ketik
Cristiano Mendonça
Saya akhirnya menggunakan solusi @ morgler.
Wylliam Judd
2

sesederhana:

user = User.find(10) rescue nil
mohamed-ibrahim
sumber
1
Saya lebih suka lebih spesifik tentang kesalahan apa yang diharapkan bisa diselamatkan, ActiveRecord :: RecordNotFound dalam kasus ini. Seperti yang ditunjukkan pada jawaban ini oleh @morgler
luizrogeriocn
2
Saya pribadi menemukan ini sebagai jawaban terbaik. Saya sudah memberi tahu kode saya apa yang harus dilakukan jika pengguna tidak ditemukan diif user...else
Wylliam Judd
0

Anda dapat menggunakan find_by dengan atribut yang diperlukan (dalam kasus Anda id) ini akan mengembalikan nil daripada memberikan kesalahan jika id yang diberikan tidak ditemukan.

user = Challenge.find_by_id(id_value)

atau Anda bisa menggunakan format baru:

user = Challenge.find_by id: id_value

Anda juga dapat menggunakan where tetapi Anda harus tahu bahwa where mengembalikan relasi record aktif dengan nol atau lebih record yang perlu Anda gunakan terlebih dahulu untuk mengembalikan hanya satu record atau nil jika record nol kembali.

user = Challenge.where(id: id_value).first
Alanoud Just
sumber