Melakukan redirect_to dengan benar: kembali ke Ruby on Rails ketika pengarah tidak tersedia

91

Saya mengalami masalah dengan redirect_to :back. Ya, itu perujuk.

Saya sering mendapatkan pengecualian

(ActionController :: RedirectBackError) "Tidak ada HTTP_REFERER yang disetel dalam permintaan untuk tindakan ini, jadi redirect_to: back tidak berhasil dipanggil. Jika ini adalah tes, pastikan untuk menetapkan request.env [\" HTTP_REFERER \ "]."

Saya menyadari bahwa ini adalah akibat dari tidak adanya perujuk. Adakah cara yang, misalnya, seseorang dapat menyetel variabel sesi pada setiap akses dengan halaman terakhir yang dikunjungi, dan, jika HTTP_REFERER tidak tersedia, gunakan variabel sesi ini untuk dialihkan?

pengguna67050
sumber
Saya memiliki kesalahan yang sama dalam tindakan pembaruan, yang aneh karena perujuk tidak boleh kosong (karena permintaan akan berasal dari formulir), tetapi beberapa pengguna baru saja berhasil melakukan ini yang saya tidak tahu caranya.
lulalala

Jawaban:

144

Hal ini tidak mungkin bahwa Anda lakukan memiliki sesi dan tidak memiliki referer.

Situasi di mana perujuk tidak disetel tidak biasa dan saya biasanya menyelamatkan harapan itu:

def some_method
  redirect_to :back
rescue ActionController::RedirectBackError
  redirect_to root_path
end

Jika Anda sering melakukan ini (yang menurut saya ide yang buruk), Anda dapat membungkusnya dengan metode lain seperti yang disarankan Maran.

BTW Saya pikir itu ide yang buruk karena ini membuat alur pengguna menjadi ambigu. Hanya dalam kasus login ini masuk akal.

PEMBARUAN : Seperti yang ditunjukkan beberapa orang, ini tidak lagi berfungsi dengan Rails 5. Sebagai gantinya, gunakan redirect_back, metode ini juga mendukung fallback. Kode tersebut kemudian menjadi:

def some_method
  redirect_back fallback_location: root_path
end
membahayakan
sumber
4
Saya menduga bahwa saya akan mengubah ini untuk menggunakan rescue_from sebagai gantinya.
Bob Aman
1
@BobAman IMO kita dapat menggunakan rescue_fromjika pengontrol memiliki beberaparedirect_to :back
Theo B
tidak berfungsi dengan rel 5, ActionController :: RedirectBackError tidak ditentukan ... solusi apa?
Matrix
Gunakan ini sebagai gantinya:redirect_to (request.referrer || root_url)
Abhi
38

Inilah metode redirect_to_back kecil saya:

  def redirect_to_back(default = root_url)
    if request.env["HTTP_REFERER"].present? and request.env["HTTP_REFERER"] != request.env["REQUEST_URI"]
      redirect_to :back
    else
      redirect_to default
    end
  end

Anda dapat mengirimkan url opsional untuk pergi ke tempat lain jika http_refferrer kosong.

Mirko
sumber
37
def store_location
  session[:return_to] = request.request_uri
end

def redirect_back_or_default(default)
  redirect_to(session[:return_to] || default)
  session[:return_to] = nil
end

Coba itu! (Berkat plugin Authlogic )

Maran
sumber
22
Ini adalah solusi yang bagus, tetapi saya akan mengimbau siapa pun yang menggunakannya untuk mengingat bahwa ini dapat "merusak" dengan cara yang sangat membingungkan pengguna jika dia menggunakan banyak tab untuk menjelajahi aplikasi Anda.
Mitch Lindgren
3
+1 Untuk menjawab pertanyaan dan tidak mengkritik metode desain.
Abe Petrillo
31

Fitur inti

redirect_backadalah fitur inti dari Rails 5+, ini tersedia di ActionController::Redirectingmodul yang sudah disertakan ApplicationController::Base.

PERINGATAN DEPRECATION: redirect_to :backtidak digunakan lagi dan akan dihapus dari Rails 5.1. Silakan gunakan redirect_back(fallback_location: fallback_location)where fallback_locationmewakili lokasi yang akan digunakan jika permintaan tidak memiliki informasi rujukan HTTP.

EDIT: sumber

Cyril Duchon-Doris
sumber
Tautkan ke sumber, silakan
Chris Bloom
1
@ Chrisbloom7 Ini adalah pesan peringatan yang saya dapatkan saat menjalankan Rails 5.0.0beta3 dengan redirect_to :back.
Cyril Duchon-Doris
21

Mungkin sudah terlambat tetapi saya ingin membagikan metode saya yang juga mempertahankan opsi:

  def redirect_back_or_default(default = root_path, *options)
    tag_options = {}
    options.first.each { |k,v| tag_options[k] = v } unless options.empty?
    redirect_to (request.referer.present? ? :back : default), tag_options
  end

Anda bisa menggunakannya seperti:

redirect_back_or_default(some_path, :notice => 'Hello from redirect', :status => 301)
troex
sumber
14

diperbarui: Rails 5 menambahkan metode redirect_back ( https://github.com/rails/rails/pull/22506/ ), lebih baik gunakan saja:

redirect_back fallback_location: answer_path(answer), flash: { error: I18n.t('m.errors')}

Untuk rel yang lebih rendah dari 5.0 masih bisa menggunakan cara lama dibawah ini:

mirip dengan jawaban @ troex, tambahkan ini ke pengontrol aplikasi Anda

def redirect_back_or_default(default = root_path, options = {})
  redirect_to (request.referer.present? ? :back : default), options
end

lalu gunakan di pengontrol Anda

redirect_back_or_default answer_path(answer), flash: { error: I18n.t('m.errors')}
longkt90
sumber
0

Baru-baru ini, saya mengalami masalah yang sama di mana saya harus mengalihkan :backatau ke halaman tertentu. Setelah pergi ke banyak solusi, saya akhirnya menemukan ini yang sederhana dan sepertinya menyelesaikan masalah:


if request.env["HTTP_REFERER"].present?
    redirect_to :back
else
    redirect_to 'specific/page'
end

Jika Anda ingin menggunakan sessiondetail, lakukan di bagian lain kode.

Rahul Goyal
sumber