Làm cách nào để chuyển hướng đến trang trước trong Ruby On Rails?


186

Tôi có một trang liệt kê tất cả các dự án có tiêu đề và phân trang có thể sắp xếp.

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

Tôi chọn chỉnh sửa một trong những dự án

path:
projects/436/edit

Khi tôi nhấp vào lưu trên trang đó, nó sẽ gọi phương thức cập nhật / điều khiển dự án. Sau khi tôi cập nhật mã, tôi muốn chuyển hướng đến đường dẫn mà tôi đã đi trước khi nhấp vào chỉnh sửa một dự án cụ thể. Nói cách khác, tôi muốn ở cùng một trang với cùng cách sắp xếp.

Tôi đã thấy link_to (: back) và nghĩ rằng: back có thể hoạt động trong redirect_to (: back), nhưng điều đó là không nên.

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

Bất kỳ ý tưởng về làm thế nào tôi có thể làm cho điều này để làm việc. Có vẻ như một vấn đề sẽ dễ dàng được giải quyết, nhưng tôi chưa quen với RoR.

Câu trả lời:


323

Trong hành động chỉnh sửa của bạn, lưu trữ url yêu cầu trong hàm băm phiên, có sẵn trên nhiều yêu cầu:

session[:return_to] ||= request.referer

Sau đó chuyển hướng đến nó trong hành động cập nhật của bạn, sau khi lưu thành công:

redirect_to session.delete(:return_to)

68
Tôi muốn đề xuất redirect_to session.delete(:return_to)trong hành động cập nhật. Điều này làm sạch giá trị từ phiên, vì nó không còn cần thiết nữa.
stigi

19
không có một vài tab mở nhầm lẫn logic này?
jones

12
Có phải bạn redirect_to request.refererkhông?
Elle Mundy

1
@DanMundy Không, để nó hoạt động thì nên request.referer.referer, nếu điều đó có thể. @Jaime Bellmyer Tại sao ||=?
x-yuri

@jones có. Cũng có sự nhầm lẫn nếu bạn chuyển sang chỉnh sửa mô hình khác. Tôi cũng quan tâm đến lý do tại sao || =
Mauro

99

Tại sao nó redirect_to(:back)không làm việc cho bạn, tại sao nó không đi?

redirect_to(:back)làm việc như một cơ duyên đối với tôi Nó chỉ là một đoạn ngắn cho redirect_to(request.env['HTTP_REFERER'])

http://apidock.com/rails/ActionControll/Base/redirect_to (trước Rails 3) hoặc http://apidock.com/rails/ActionControll/Redirecting/redirect_to (Rails 3)

Xin lưu ý rằng redirect_to(:back)không được chấp nhận trong Rails 5. Bạn có thể sử dụng

redirect_back(fallback_location: 'something')thay vào đó (xem http://blog.bigbinary.com/2016/02/29/rails-5-improves-redirect_to_back-with-redirect-back.html )


12
redirect_to :backTôi cũng không làm việc tốt, giả sử bạn truy cập /posts/new, đây được đặt làm người giới thiệu cho yêu cầu tiếp theo, vì vậy sau khi biểu mẫu được gửi thành công, nó sẽ hiển thị lại biểu mẫu, tức là /posts/new. Tuy nhiên, nó hoạt động tốt cho các mục đích khác.
Kris

Đó là, OP muốn chuyển hướng trở lại hai lần. Tôi cá là anh ấy có thể redirect_to projects_path.
x-yuri

Vâng. redirect_back không hoạt động tốt trong Rails 5
strizzwald

@strizzwald "không hoạt động tốt" nghĩa là gì? Có chi tiết nào không?
Pascal

@pascalbetz, Ý tôi là nếu HTTP_REFERERkhông được đặt, bạn có thể nhận được ActionController::RedirectBackError, bạn sẽ phải giải cứu khỏi ngoại lệ này trong trường hợp đó. Theo hiểu biết của tôi, việc sử dụng redirect_backkhông yêu cầu xử lý ngoại lệ vì bạn buộc phải cung cấp fallback_location. Có lẽ "không hoạt động tốt" không phải là cách đúng đắn để đặt nó.
strizzwald

45

Tôi thích phương pháp của Jaime với một ngoại lệ, nó hoạt động tốt hơn đối với tôi để lưu trữ lại người giới thiệu mỗi lần:

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

Lý do là nếu bạn chỉnh sửa nhiều đối tượng, bạn sẽ luôn được chuyển hướng trở lại URL đầu tiên bạn lưu trữ trong phiên bằng phương thức của Jaime. Ví dụ: giả sử tôi có đối tượng Apple và Orange. Tôi chỉnh sửa Apple và session[:return_to]được đặt thành người giới thiệu hành động đó. Khi tôi đi chỉnh sửa Cam bằng cách sử dụng cùng một mã, session[:return_to]sẽ không được đặt vì nó đã được xác định. Vì vậy, khi tôi cập nhật Orange, tôi sẽ được gửi đến người giới thiệu hành động chỉnh sửa # trước của Apple.


có, nhưng bạn có thể đề xuất phải làm gì nếu vô tình cùng một url được lưu trữ như bạn đang ở không? Bạn đang ở táo và bạn đến từ táo. Và bạn muốn vị trí trước đó
Uko

33

Đây là cách chúng tôi làm điều đó trong ứng dụng của chúng tôi

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

Bằng cách này, bạn chỉ lưu trữ yêu cầu GET cuối cùng trong :return_tophiên param, vì vậy tất cả các biểu mẫu, ngay cả khi POST nhiều lần sẽ hoạt động với :return_to.


3
request.request_urikhông còn khả dụng nữa, vì vậy tôi đề nghị sử dụng request.fullpaththay thế
anka

@anka Cập nhật. Cảm ơn đã bình luận
MBO

2
yup đó là khá tốt. Tôi chỉ đề nghị nói chung là không sử dụng andortrong các ifbáo cáo. Sử dụng &&||thay vào đó. Chi tiết tại đây .
Achilles

19

Trong rails 5, theo hướng dẫn trong Rails Guide, bạn có thể sử dụng:

redirect_back(fallback_location: root_path)

Vị trí 'quay lại' được lấy từ tiêu đề HTTP_REFERER không được đảm bảo đặt bởi trình duyệt. Đó là lý do tại sao bạn nên cung cấp 'fallback_location'.


Tính năng này xuất hiện trong đường ray 5.
Chambeur

@pSkarl Làm cách nào tôi có thể truyền một noticeđối tượng bằng redirect_backcâu lệnh để báo cho người dùng biết có gì đó không ổn với tin nhắn flash?
alexventuraio

2
Vâng, tôi có thể giải quyết điều này bằng cách làm : redirect_back(fallback_location: root_path, notice: "Something went wrong!"). Hy vọng nó có thể giúp bằng cách nào đó.
alexventuraio

18

request.referer được đặt bởi Rack và được đặt như sau:

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

Chỉ cần làm một redirect_to request.referervà nó sẽ luôn luôn chuyển hướng đến trang giới thiệu thực sự, hoặc root_path ('/'). Điều này rất cần thiết khi vượt qua các bài kiểm tra thất bại trong các trường hợp điều hướng trực tiếp đến một trang cụ thể trong đó bộ điều khiển ném redirect_to: back


Không chắc chắn về tập tin mà bạn đang xem nhưng tại nguồn rack, đây là cách refererđược xác định kể từ ngày 28 tháng 3 năm 2011 và đó là cách nó được định nghĩa cho đến ngày hôm nay . Đó là, || '/'không phải là một phần của định nghĩa.
maček

1

Đối với những người quan tâm, đây là triển khai của tôi mở rộng câu trả lời ban đầu của MBO (được viết theo đường ray 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
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.