Saya ingin 'memalsukan' halaman 404 di Rails. Dalam PHP, saya hanya akan mengirim header dengan kode kesalahan sebagai berikut:
header("HTTP/1.0 404 Not Found");
Bagaimana itu dilakukan dengan Rails?
sumber
Saya ingin 'memalsukan' halaman 404 di Rails. Dalam PHP, saya hanya akan mengirim header dengan kode kesalahan sebagai berikut:
header("HTTP/1.0 404 Not Found");
Bagaimana itu dilakukan dengan Rails?
Jangan membuat 404 diri Anda sendiri, tidak ada alasan untuk melakukannya; Rails sudah memiliki fungsi ini. Jika Anda ingin menampilkan halaman 404, buat render_404
metode (atau not_found
seperti yang saya sebutkan) ApplicationController
seperti ini:
def not_found
raise ActionController::RoutingError.new('Not Found')
end
Rel juga menangani AbstractController::ActionNotFound
, dan ActiveRecord::RecordNotFound
dengan cara yang sama.
Ini melakukan dua hal lebih baik:
1) Ini menggunakan rescue_from
handler bawaan Rails ' untuk membuat halaman 404, dan 2) itu mengganggu eksekusi kode Anda, membiarkan Anda melakukan hal-hal baik seperti:
user = User.find_by_email(params[:email]) or not_found
user.do_something!
tanpa harus menulis pernyataan kondisional yang jelek.
Sebagai bonus, ini juga sangat mudah untuk ditangani dalam tes. Misalnya, dalam tes integrasi rspec:
# RSpec 1
lambda {
visit '/something/you/want/to/404'
}.should raise_error(ActionController::RoutingError)
# RSpec 2+
expect {
get '/something/you/want/to/404'
}.to raise_error(ActionController::RoutingError)
Dan terkecil:
assert_raises(ActionController::RoutingError) do
get '/something/you/want/to/404'
end
ATAU rujuk info lebih lanjut dari Rails render 404 yang tidak ditemukan dari aksi pengontrol
ActionController::RecordNotFound
ini pilihan yang lebih baik?expect { visit '/something/you/want/to/404' }.to raise_error(ActionController::RoutingError)
/ via stackoverflow.com/a/1722839/993890Status HTTP 404
Untuk mengembalikan header 404, cukup gunakan
:status
opsi untuk metode render.Jika Anda ingin merender halaman 404 standar, Anda dapat mengekstrak fitur dalam suatu metode.
dan menyebutnya dalam tindakan Anda
Jika Anda ingin tindakan membuat halaman kesalahan dan berhenti, cukup gunakan pernyataan kembali.
ActiveRecord dan HTTP 404
Juga ingat bahwa Rails menyelamatkan beberapa kesalahan ActiveRecord, seperti
ActiveRecord::RecordNotFound
menampilkan halaman kesalahan 404.Itu berarti Anda tidak perlu menyelamatkan tindakan ini sendiri
User.find
memunculkanActiveRecord::RecordNotFound
ketika pengguna tidak ada. Ini adalah fitur yang sangat kuat. Lihatlah kode berikutAnda dapat menyederhanakannya dengan mendelegasikan ke Rails cek. Cukup gunakan versi bang.
sumber
Jawaban yang baru dipilih yang dikirimkan oleh Steven Soroka sudah dekat, tetapi tidak lengkap. Tes itu sendiri menyembunyikan fakta bahwa ini tidak mengembalikan 404 yang benar - itu mengembalikan status 200 - "sukses". Jawaban aslinya lebih dekat, tetapi berusaha membuat tata letak seolah-olah tidak ada kegagalan yang terjadi. Ini memperbaiki semuanya:
Berikut ini adalah serangkaian tes khas saya untuk sesuatu yang saya harapkan akan kembali 404, menggunakan pencocokan RSpec dan Shoulda:
Paranoia yang sehat ini memungkinkan saya untuk menemukan ketidakcocokan tipe-konten ketika segala sesuatu tampak sangat bagus :) Saya memeriksa semua elemen ini: variabel yang ditugaskan, kode respons, tipe konten respons, template yang diberikan, tata letak yang diberikan, pesan flash.
Saya akan melewatkan pemeriksaan jenis konten pada aplikasi yang benar-benar html ... terkadang. Lagi pula, "skeptis memeriksa SEMUA laci" :)
http://dilbert.com/strips/comic/1998-01-20/
FYI: Saya tidak merekomendasikan pengujian untuk hal-hal yang terjadi di controller, yaitu "should_raise". Yang Anda pedulikan adalah hasilnya. Tes saya di atas memungkinkan saya untuk mencoba berbagai solusi, dan tes tetap sama apakah solusi meningkatkan pengecualian, render khusus, dll.
sumber
render :text => 'Not Found', :status => :not_found
.config.consider_all_requests_local
parameter yang disetel ke true dalamenvironments/development.rb
file Anda . Jika Anda memunculkan kesalahan, seperti dijelaskan dalam solusi yang diterima, dalam pementasan / produksi, Anda pasti akan mendapatkan 404, bukan 200.Anda juga dapat menggunakan file render:
Di mana Anda dapat memilih untuk menggunakan tata letak atau tidak.
Pilihan lain adalah dengan menggunakan Pengecualian untuk mengendalikannya:
sumber
Jawaban yang dipilih tidak berfungsi di Rails 3.1+ karena penangan kesalahannya dipindahkan ke middleware (lihat masalah github ).
Inilah solusi yang saya temukan yang cukup saya sukai.
Dalam
ApplicationController
:dan di
application.rb
:Dan di sumber saya (tampilkan, edit, perbarui, hapus):
Ini tentu saja dapat ditingkatkan, tetapi setidaknya, saya memiliki pandangan yang berbeda untuk not_found dan internal_error tanpa mengesampingkan fungsi inti Rails.
sumber
|| not_found
bagian, panggil sajafind!
(perhatikan bang) dan itu akan membuang ActiveRecord :: RecordNotFound ketika sumber daya tidak dapat diambil. Juga, tambahkan ActiveRecord :: RecordNotFound ke array dalam kondisi if.StandardError
dan tidakException
, untuk berjaga-jaga. Sebenarnya saya akan meninggalkan halaman statis 500 standar dan tidak menggunakan kustomrender_500
sama sekali, artinya saya akan secara eksplisitrescue_from
ini akan membantu Anda ...
Pengontrol Aplikasi
Pengontrol kesalahan
views / errors / error_404.html.haml
sumber
cukup tambahkan ini ke halaman yang ingin Anda render ke halaman kesalahan 404 dan Anda selesai.
sumber
Saya ingin melemparkan 'normal' 404 untuk setiap pengguna yang masuk yang bukan admin, jadi saya akhirnya menulis sesuatu seperti ini di Rails 5:
sumber
sumber
Untuk menguji penanganan kesalahan, Anda dapat melakukan sesuatu seperti ini:
sumber
Jika Anda ingin menangani 404 yang berbeda dengan cara yang berbeda, pertimbangkan untuk menangkapnya di pengontrol Anda. Ini akan memungkinkan Anda untuk melakukan hal-hal seperti melacak jumlah 404 yang dihasilkan oleh kelompok pengguna yang berbeda, memiliki dukungan berinteraksi dengan pengguna untuk mencari tahu apa yang salah / bagian mana dari pengalaman pengguna yang mungkin perlu diubah, lakukan pengujian A / B, dll.
Saya di sini telah menempatkan logika dasar dalam ApplicationController, tetapi juga dapat ditempatkan di pengontrol yang lebih spesifik, untuk memiliki logika khusus hanya untuk satu pengontrol.
Alasan saya menggunakan if dengan ENV ['RESCUE_404'], adalah agar saya dapat menguji peningkatan AR :: RecordNotFound secara terpisah. Dalam tes, saya dapat mengatur ENV var ini menjadi false, dan rescue_from saya tidak akan menyala. Dengan cara ini saya dapat menguji peningkatan terpisah dari logika 404 bersyarat.
sumber