ทำการ redirect_to อย่างถูกต้อง: กลับไปที่ Ruby on Rails เมื่อผู้อ้างอิงไม่พร้อมใช้งาน


91

ฉันมีปัญหากับredirect_to :back. ใช่เป็นผู้อ้างอิง

ฉันมักจะได้รับข้อยกเว้น

(ActionController :: RedirectBackError) "ไม่ได้ตั้งค่า HTTP_REFERER ในคำขอให้ดำเนินการนี้ดังนั้นจึงไม่สามารถเรียกใช้ redirect_to: back ได้สำเร็จหากเป็นการทดสอบโปรดระบุ request.env [\" HTTP_REFERER \ "]"

ฉันตระหนักดีว่านี่เป็นผลมาจากการที่ไม่มีผู้อ้างอิง ตัวอย่างเช่นมีวิธีใดบ้างที่สามารถตั้งค่าตัวแปรเซสชันในการเข้าถึงแต่ละครั้งที่มีการเยี่ยมชมหน้าสุดท้ายและเมื่อ HTTP_REFERER ไม่พร้อมใช้งานให้ใช้ตัวแปรเซสชันนี้เพื่อเปลี่ยนเส้นทางไป


ฉันมีข้อผิดพลาดเดียวกันในการดำเนินการอัปเดตซึ่งเป็นเรื่องแปลกเนื่องจากผู้อ้างอิงต้องไม่ว่างเปล่า (เนื่องจากคำขอจะมาจากแบบฟอร์ม) แต่ผู้ใช้บางคนเพิ่งจัดการสิ่งนี้ซึ่งฉันไม่รู้ว่าทำอย่างไร
lulalala

คำตอบ:


144

ไม่น่าเป็นไปได้ที่คุณจะมีเซสชันและไม่มีผู้อ้างอิง

สถานการณ์ที่ผู้อ้างอิงไม่ได้ตั้งค่านั้นไม่ใช่เรื่องผิดปกติและฉันมักจะช่วยเหลือการเปิดเผยดังกล่าว:

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

หากคุณทำสิ่งนี้บ่อยๆ (ซึ่งฉันคิดว่าเป็นความคิดที่ไม่ดี) คุณสามารถห่อด้วยวิธีอื่นอย่างที่ Maran แนะนำ

BTW ฉันคิดว่านั่นเป็นความคิดที่ไม่ดีเพราะสิ่งนี้ทำให้ Userflow ไม่ชัดเจน เฉพาะในกรณีของการเข้าสู่ระบบเท่านั้นที่เหมาะสม

อัปเดต : ตามที่หลาย ๆ คนชี้ให้เห็นว่าสิ่งนี้ใช้ไม่ได้กับ Rails 5 อีกต่อไปให้ใช้redirect_backวิธีนี้ยังสนับสนุนทางเลือกอื่น จากนั้นรหัสจะกลายเป็น:

def some_method
  redirect_back fallback_location: root_path
end

4
ฉันสงสัยว่าฉันจะเปลี่ยนสิ่งนี้ไปใช้ rescue_from แทน
Bob Aman

1
@BobAman IMO เราสามารถใช้ได้rescue_fromหากคอนโทรลเลอร์มีหลายตัวredirect_to :back
Theo B

ไม่ทำงานกับราง 5, ActionController :: RedirectBackError ไม่ได้กำหนด ... วิธีแก้ปัญหาคืออะไร?
Matrix

ใช้สิ่งนี้แทน:redirect_to (request.referrer || root_url)
Abhi

38

นี่คือวิธี redirect_to_back เล็ก ๆ ของฉัน:

  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

คุณสามารถส่ง URL ที่เป็นทางเลือกเพื่อไปที่อื่นได้หาก http_refferrer ว่างเปล่า


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

ลองดูสิ! (ขอบคุณปลั๊กอินAuthlogic )


22
นี่เป็นวิธีแก้ปัญหาที่ดี แต่ฉันขอแนะนำให้ทุกคนที่ใช้แอปโปรดจำไว้ว่าแอปนี้อาจ "แตก" ในลักษณะที่ทำให้ผู้ใช้สับสนอย่างมากหากใช้หลายแท็บเพื่อเรียกดูแอปของคุณ
Mitch Lindgren

3
+1 สำหรับการตอบคำถามและไม่วิพากษ์วิจารณ์วิธีการออกแบบ
Abe Petrillo

31

คุณสมบัติหลัก

redirect_backเป็นคุณสมบัติหลักจาก Rails 5+ ซึ่งมีอยู่ในActionController::Redirectingโมดูลที่รวมอยู่ในApplicationController::Baseไฟล์.

คำเตือนการredirect_to :backเลิกใช้งาน: เลิกใช้งานแล้วและจะถูกลบออกจาก Rails 5.1 โปรดใช้redirect_back(fallback_location: fallback_location)ตำแหน่งที่fallback_locationแสดงตำแหน่งที่จะใช้หากคำขอไม่มีข้อมูลผู้อ้างอิง HTTP

แก้ไข: ที่มา


โปรดลิงก์ไปยังแหล่งที่มา
Chris Bloom

1
@ Chrisbloom7 redirect_to :backนี้เป็นข้อความแจ้งเตือนฉันมีในขณะที่ทำงานกับทางรถไฟ
Cyril Duchon-Doris

21

อาจจะสายไป แต่ฉันอยากจะแบ่งปันวิธีการของฉันซึ่งยังคงรักษาตัวเลือกไว้:

  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

คุณสามารถใช้มันเช่น:

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

14

อัปเดต: Rails 5 เพิ่มวิธี redirect_back ( https://github.com/rails/rails/pull/22506/ ) ดีกว่าเพียงแค่ใช้:

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

สำหรับรางที่ต่ำกว่า 5.0 ยังสามารถใช้วิธีเดิมด้านล่าง:

คล้ายกับคำตอบของ @ troex ให้เพิ่มสิ่งนี้ลงในตัวควบคุมแอปพลิเคชันของคุณ

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

จากนั้นใช้ในคอนโทรลเลอร์ของคุณ

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

0

เมื่อเร็ว ๆ นี้ฉันพบปัญหาเดียวกันกับที่ฉันต้องเปลี่ยนเส้นทาง:backหรือไปยังหน้าใดหน้าหนึ่ง หลังจากหาวิธีแก้ปัญหามากมายในที่สุดฉันก็พบสิ่งนี้ซึ่งง่ายและดูเหมือนจะแก้ปัญหาได้:


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

หากคุณต้องการใช้sessionรายละเอียดให้ทำในส่วนอื่นของโค้ด

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.