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


Jawaban:


172

Ya, lakukan saja:

Challenge.find_by_id(10)

Untuk Rails 4 dan 5:

Challenge.find_by(id: 10)

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

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

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".


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)


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

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

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
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.