Có một vài vấn đề cần khắc phục ở đây.
Trình duyệt nói chung không cho phép chuyển hướng đến yêu cầu POST.
redirect_to không giữ nguyên định dạng mà không có đầu vào bổ sung.
Vị trí cửa hàng không lưu giữ dữ liệu biểu mẫu.
Tất cả những vấn đề này có thể được giải quyết bằng cách loại bỏ chuyển hướng.
Đây là cách tôi đã truyền trong quá khứ:
Thay vì chuyển hướng trong required_user, hãy kết xuất. Nếu bộ lọc trước chuyển hướng hoặc hiển thị hành động đang chờ xử lý bị hủy. (Không cần phải trả về false). Thật không may, tuyến đường này làm mờ đường biên của bộ điều khiển. Nhưng cho phép cho dự phòng html đơn giản, và cho vay tự của mình để DRYness.
Quan điểm cao cấp của dòng chảy tác phẩm mới sẽ là:
- Yêu cầu chú thích # phiếu (POST)
- lọc required_user không
- làm cho phiên làm việc mới
- gửi thông tin đăng nhập và độc đáo POST dữ liệu trở lại chú thích # vote (POST)
- bộ lọc mới trong phiếu bầu sẽ nắm bắt thông tin phiên và nhật ký. Tiền thu được như dự kiến. Nếu đăng nhập thất bại trở lại 3.
- chú thích # phiếu chuyển hướng/ám như nó nên
Bắt đầu bằng cách làm lại các require_user để render user_sessions # mẫu mới.
def require_user
unless current_user
flash[:notice] = "You'll need to login or register to do that"
@user_session ||= UserSession.new
respond_to do |format|
format.html {render :template => 'user_sessions/new'}
format.js {
render :template => 'user_sessions/new', :layout => false
}
end
end
end
Đảm bảo chúng tôi có thể trả lại lỗi xác thực cho biểu mẫu.
Bây giờ, chúng tôi phải tăng user_session # mẫu mới để có thể nhớ hành động. Ngoài ra, nếu bạn định sử dụng lightbox, đây phải là một phần được hiển thị bởi RJS có liên quan hoặc new.html.erb.
Đầu tiên chúng ta tạo ra một phần để tạo ra các trường ẩn bảo toàn dữ liệu POST mà có thể đã bị mất trong một chuyển hướng:
<% if params[:controller] == "annotations" %>
<% content_for :old_form do %>
<%= hidden_field_tag "annotation[song_id]", params[:annotation][:song_id] %>
<%= hidden_field_tag "annotation[vote]", params[:annotation][:vote] %>
<% end %>
<% end %>
Sau đó, và việc này là một phần trong việc đăng nhập một phần sẽ chiếm lightbox của bạn:
<%= render :partial => vote_form_replica %>
<% url = params[:controller] == "user_sessions ? user_sessions_url : {} %>
<% form_tag @user_session, :url => url do |f| %>
<%= yield :old_form %>
<%= f.label :user_name %>
<%= f.text_field :user_name %>
<%= f.label :password %>
<%= f.password_field :password %>
<%= submit_tag %>
<%end%>
Hàm băm rỗng cho url trong form_tag trông giống như lỗi, nhưng không phải. Nó đảm bảo rằng dữ liệu biểu mẫu được đăng lên url đã kết xuất biểu mẫu. Mà tại thời điểm này nên là chú thích /: id/vote
Bây giờ cho bộ lọc mới để đăng nhập. Về cơ bản nó sẽ được làm những gì bao giờ UserSessionsController # tạo ra mà không có render/chuyển hướng. Sau đây được sao chép từ plugin xác thực RESTful.
def authenticate
self.current_user = User.authenticate(params[:login], params[:password])
if logged_in?
if params[:remember_me] == "1"
current_user.remember_me unless current_user.remember_token?
cookies[:auth_token] = { :value => self.current_user.remember_token,
:expires => self.current_user.remember_token_expires_at }
end
end
end
Tất cả những gì còn lại là đảm bảo thứ tự bộ lọc là đúng.
before_filter :authenticate, :require_user, :only => :vote
N.B .: Bạn có lẽ sẽ không phải sử dụng phiên bản này của require_user mà không cần phiên bản này của xác thực nên nó làm cho tinh thần để kết hợp chúng thành một bộ lọc duy nhất.
Và đó là nó. Cách thức này đã được thiết lập cho phép mã DRY dễ dàng sử dụng lại dễ dàng. Bằng cách đặt các bộ lọc mới vào ApplicationController, chúng có sẵn trong bất kỳ bộ điều khiển nào.Từ thời điểm này, việc thêm chức năng này vào bất kỳ bộ điều khiển/hành động nào khác chỉ thực hiện 3 bước đơn giản:
- Tạo một phần mới được mô hình hóa sau phần vote_form_replica.
- Thêm câu lệnh hiển thị tương ứng vào mẫu phiên mới.
- Áp dụng bộ lọc cho hành động của bạn.
Tôi nghĩ bạn phải kết hợp ': authenticate' và': require_user' trước các bộ lọc. Như là, bạn không thể gọi ': require_user' một cách riêng biệt bởi vì người dùng sẽ không bao giờ có thể đăng nhập. Tuy nhiên, tôi nghĩ đây là cách tiếp cận đúng về toàn bộ - đặc biệt là mẹo' content_for' để "phát lại" của người dùng hành động mong muốn khi anh ta đăng nhập và ý tưởng chung về việc ghi nhật ký người dùng qua một 'before_filter' đều khá thông minh –
Cảm ơn bạn. content_for không thực sự cần thiết, tôi chỉ cảm thấy nó làm cho mã dễ đọc hơn. Nó hoạt động tốt hơn trong bạn partials, do đó, điều chỉnh này cho các bộ điều khiển khác/hành động đòi hỏi một phần mới và tương ứng render: tuyên bố một phần. Tôi đã cập nhật giải pháp để phản ánh điều đó. Kết hợp các bộ lọc xác thực và require_user vào một bộ lọc đơn giản hơn. Tôi cảm thấy lời giải thích của giải pháp này chỉ tốt hơn bằng cách phá vỡ nó thành các bước nguyên tử mà bạn có thể thực hiện để điều chỉnh mã hiện tại của mình cho lược đồ này. – EmFi
Ồ, cũng - không nên 'render: action => 'user_sessions/new'' là' render: template =>' user_sessions/new'' (trong 'require_user')? –