Bagaimana cara mengarahkan ulang ke halaman sebelumnya di Ruby On Rails?

186

Saya memiliki halaman yang mencantumkan semua proyek yang memiliki header dan pagination yang dapat diurutkan.

path:
/projects?order=asc&page=3&sort=code

Saya memilih untuk mengedit salah satu proyek

path:
projects/436/edit

Ketika saya mengklik simpan di halaman itu, ia memanggil metode pengontrol / pembaruan proyek. Setelah saya memperbarui kode saya ingin mengarahkan ulang ke jalur yang saya gunakan sebelum saya mengklik edit proyek tertentu. Dengan kata lain, saya ingin berada di halaman yang sama dengan pengurutan yang sama.

Saya melihat link_to (: kembali) dan berpikir: kembali dapat bekerja di redirect_to (: kembali), tapi itu tidak jalan.

puts YAML::dump(:back) 
yields the following:
:back 

Ada ide tentang bagaimana saya bisa membuatnya bekerja. Sepertinya masalah yang akan mudah dipecahkan, tapi saya baru mengenal RoR.

keenakan
sumber

Jawaban:

323

Dalam tindakan edit Anda, simpan url permintaan dalam hash sesi, yang tersedia di beberapa permintaan:

session[:return_to] ||= request.referer

Kemudian arahkan kembali ke tindakan pembaruan Anda, setelah berhasil menyimpan:

redirect_to session.delete(:return_to)
Jaime Bellmyer
sumber
68
Saya sarankan redirect_to session.delete(:return_to)dalam tindakan pembaruan. Ini membersihkan nilai dari sesi, karena tidak diperlukan lagi.
stigi
19
tidak memiliki beberapa tab terbuka membingungkan logika ini?
Jones
12
Tidak bisa Anda hanya redirect_to request.referer?
Elle Mundy
1
@DanMundy Tidak, agar bisa berfungsi seharusnya request.referer.referer, jika itu mungkin. @Jaime Bellmyer Kenapa ||=?
x-yuri
@Jones ya. Ada juga kebingungan jika Anda beralih ke edit model lain. Saya juga tertarik pada mengapa || =
Mauro
99

Mengapa redirect_to(:back)tidak bekerja untuk Anda, mengapa itu tidak jalan?

redirect_to(:back)bekerja seperti pesona bagi saya. Itu hanya jalan pintas redirect_to(request.env['HTTP_REFERER'])

http://apidock.com/rails/ActionController/Base/redirect_to (pre Rails 3) atau http://apidock.com/rails/ActionController/Redirecting/redirect_to (Rails 3)

Harap dicatat bahwa redirect_to(:back)sedang tidak digunakan lagi dalam Rails 5. Anda dapat menggunakan

redirect_back(fallback_location: 'something')sebagai gantinya (lihat http://blog.bigbinary.com/2016/02/29/rails-5-improves-redirect_to_back-with-redirect-back.html )

Pascal
sumber
12
redirect_to :backtidak berfungsi dengan baik untuk saya, katakan Anda mengunjungi /posts/new, ini ditetapkan sebagai perujuk untuk permintaan berikutnya, jadi setelah formulir berhasil dikirim itu menunjukkan formulir lagi, yaitu /posts/new. Namun itu berfungsi dengan baik untuk tujuan lain.
Kris
Artinya, OP ingin mengalihkan kembali dua kali. Aku yakin dia bisa saja redirect_to projects_path.
x-yuri
Ya. redirect_back tidak berfungsi dengan baik di Rails 5
strizzwald
@strizzwald apa artinya "tidak bekerja dengan baik"? Ada detail?
Pascal
@ Pascalbetz, Apa yang saya maksudkan adalah bahwa jika HTTP_REFERERtidak diatur, Anda mungkin mendapatkan ActionController::RedirectBackError, Anda harus menyelamatkan dari pengecualian ini dalam kasus itu. Dari pemahaman saya, menggunakan redirect_backtidak memerlukan penanganan pengecualian karena Anda dipaksa untuk menyediakan fallback_location. Mungkin 'tidak berfungsi dengan baik' bukan cara yang tepat untuk mengatakannya.
strizzwald
45

Saya suka metode Jaime dengan satu pengecualian, itu bekerja lebih baik bagi saya untuk menyimpan kembali referensi setiap kali:

def edit
    session[:return_to] = request.referer
...

Alasannya adalah bahwa jika Anda mengedit beberapa objek, Anda akan selalu diarahkan kembali ke URL pertama yang Anda simpan dalam sesi dengan metode Jaime. Sebagai contoh, katakanlah saya memiliki objek Apple dan Orange. Saya mengedit Apple dan session[:return_to]siap untuk referensi tindakan itu. Ketika saya pergi untuk mengedit Jeruk menggunakan kode yang sama, session[:return_to]tidak akan ditetapkan karena sudah ditentukan. Jadi ketika saya memperbarui Orange, saya akan dikirim ke referer dari tindakan edit # Apple sebelumnya.

Tony
sumber
ya, tetapi bisakah Anda menyarankan apa yang harus dilakukan jika url yang sama tidak sengaja disimpan saat Anda berada di? Anda berada di apel dan Anda berasal dari apel. Dan Anda ingin lokasi sebelumnya
Uko
33

Ini adalah bagaimana kami melakukannya di aplikasi kami

def store_location
  session[:return_to] = request.fullpath if request.get? and controller_name != "user_sessions" and controller_name != "sessions"
end

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

Dengan cara ini Anda hanya menyimpan permintaan GET terakhir di :return_toparam sesi, jadi semua formulir, bahkan ketika beberapa waktu POST akan berfungsi :return_to.

MBO
sumber
3
request.request_uritidak lagi tersedia, jadi saya sarankan untuk menggunakan request.fullpathsebagai gantinya
anka
@anka Diperbarui. Terima kasih atas komentar
MBO
2
ya itu cukup bagus. Saya hanya menyarankan untuk umumnya tidak menggunakan anddan ordalam ifpernyataan. Gunakan &&dan ||sebagai gantinya. Detail di sini .
Achilles
19

Di rel 5, sesuai instruksi dalam Panduan Rails, Anda dapat menggunakan:

redirect_back(fallback_location: root_path)

Lokasi 'kembali' ditarik dari tajuk HTTP_REFERER yang tidak dijamin disetel oleh peramban. Itulah mengapa Anda harus menyediakan 'fallback_location'.

pSkarl
sumber
Fitur ini muncul di rails 5.
Chambeur
@ pSkarl Bagaimana saya bisa melewatkan noticeobjek dengan redirect_backpernyataan untuk memberi tahu pengguna ada yang salah dengan pesan flash?
alexventuraio
2
Yah, aku bisa memecahkan masalah ini dengan melakukan: redirect_back(fallback_location: root_path, notice: "Something went wrong!"). Semoga ini bisa membantu.
alexventuraio
18

request.referer diatur oleh Rack dan diatur sebagai berikut:

def referer
  @env['HTTP_REFERER'] || '/'
end

Lakukan saja redirect_to request.refererdan itu akan selalu mengarahkan ke halaman referensi yang sebenarnya, atau root_path ('/'). Ini penting ketika melewati tes yang gagal dalam kasus direct-nav ke halaman tertentu di mana controller melempar redirect_to: kembali

Steve Tipton
sumber
Tidak yakin file mana yang Anda lihat tetapi pada sumber rak, ini adalah bagaimana refererdidefinisikan pada 28 Mar 2011 , dan itulah yang didefinisikan pada hari ini . Artinya, || '/'bukan bagian dari definisi.
maček
1

Bagi mereka yang tertarik, ini adalah implementasi saya untuk memperluas jawaban asli MBO (ditulis pada rail 4.2.4, ruby ​​2.1.5).

class ApplicationController < ActionController::Base
  after_filter :set_return_to_location

  REDIRECT_CONTROLLER_BLACKLIST = %w(
    sessions
    user_sessions
    ...
    etc.
  )

  ...

  def set_return_to_location
    return unless request.get?
    return unless request.format.html?
    return unless %w(show index edit).include?(params[:action])
    return if REDIRECT_CONTROLLER_BLACKLIST.include?(controller_name)
    session[:return_to] = request.fullpath
  end

  def redirect_back_or_default(default_path = root_path)
    redirect_to(
      session[:return_to].present? && session[:return_to] != request.fullpath ?
        session[:return_to] : default_path
    )
  end
end
aschyiel
sumber