2010-01-26 48 views
160

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.Cách chuyển hướng đến trang trước trong Ruby On Rails?

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 bấm lưu trên trang đó, nó gọi phương thức dự án điều khiển/cập nhật. Sau khi tôi cập nhật mã, tôi muốn chuyển hướng đến đường dẫn mà tôi đã truy cập trước khi tôi 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 phân loại.

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

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

Mọi ý tưởng về cách tôi có thể làm việc này. Nó có vẻ như là một vấn đề có thể dễ dàng giải quyết, nhưng tôi mới làm quen với RoR.

Trả lời

289

Trong chỉnh sửa hành động của bạn, lưu trữ các url yêu cầu trong băm phiên, trong đó 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 một thành công tiết kiệm:

redirect_to session.delete(:return_to) 
+0

Điều này đã làm điều này. Cảm ơn! – easement

+65

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 thiết nữa. – stigi

+15

không có nhiều tab mở nhầm lẫn logic này? – jones

33

Đây là cách chúng tôi chỉ 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 lưu trữ yêu cầu GET cuối cùng trong thông số phiên :return_to phiên, do đó, tất cả các biểu mẫu, ngay cả khi nhiều thời gian đã đăng sẽ hoạt động với :return_to.

+3

'request.request_uri' không còn khả dụng, vì vậy tôi đề nghị sử dụng' request.fullpath' thay vì – anka

+0

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

+2

yup đó là khá tốt. Tôi sẽ chỉ đề nghị nói chung không sử dụng 'và' và' hoặc' trong câu lệnh 'if'. Sử dụng '&&' và '||' để thay thế. Chi tiết [tại đây] (http://devblog.avdi.org/2010/08/02/using-and-and-or-in-ruby/). – Achilles

46

Tôi thích phương pháp của Jaime với một ngoại lệ, nó làm việc tốt hơn cho tôi để tái lưu trữ các referer 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 luôn được chuyển hướng về URL đầu tiên bạn lưu trữ trong phiên với phương thức Jaime. Ví dụ, giả sử tôi có đối tượng là 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 sửa Orang bằng cách sử dụng cùng một mã, session[:return_to] sẽ không được đặt bởi 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 về hành động chỉnh sửa của Apple # trước đó.

+0

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

88

Tại sao redirect_to(:back) không hoạt động cho bạn, tại sao lại không hoạt động?

redirect_to(:back) hoạt động như một sự quyến rũ đối với tôi. Nó chỉ là một cắt ngắn cho redirect_to(request.env['HTTP_REFERER'])

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

Xin lưu ý rằng redirect_to(:back) đang được tán thành trong Rails 5.Bạn có thể sử dụng

redirect_back(fallback_location: 'something') thay thế (xem http://blog.bigbinary.com/2016/02/29/rails-5-improves-redirect_to_back-with-redirect-back.html)

+11

'redirect_to: back' không hoạt động tốt cho tôi, giả sử bạn truy cập'/posts/new', điều này được đặt làm tham chiế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ị một lần nữa, tức là '/ posts/new'. Tuy nhiên nó hoạt động tốt cho các mục đích khác. – Kris

+0

Đó là, OP muốn chuyển hướng lại hai lần. Tôi cá là anh ta chỉ có thể 'redirect_to projects_path'. –

+0

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

18

request.referer được thiết lập bởi Rack và được thiết lập như sau:

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

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

+0

Không chắc chắn tệp nào bạn đang xem nhưng ở nguồn giá, đây là cách 'referer' được định nghĩa là [28 Mar 2011] (https://github.com/rack/rack/blob/828e2ab0396c5bbf4b5ccd76e6392a475633a81f/lib/rack /request.rb#L222-L224) và đó là cách nó được định nghĩa là [hôm nay] (https://github.com/rack/rack/blob/bbae0ce30ddeb9f8a2a208d08e479ee5a85a1a02/lib/rack/request.rb#L289-L291). Đó là, '|| '/' 'không phải là một phần của định nghĩa. –

11

Trong ray 5, theo các hướng dẫn trong Rails Hướng dẫn, 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 trình duyệt bảo đảm đặt. Đó là lý do tại sao bạn nên cung cấp một 'fallback_location'.

+0

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

+0

@Chambeur, đúng vậy. Tôi đã sửa lại nó! – pSkarl

+0

@pSkarl Làm thế nào tôi có thể truyền một đối tượng 'notice' với câu lệnh' redirect_back' để báo cho người dùng biết đã xảy ra sự cố với thông điệp flash? –

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 gốc của MBO (được viết bằng đườ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 
Các vấn đề liên quan