2010-01-17 25 views
8

Một điều bạn có thể làm trên rap lyric explanation site của tôi là "like" giải thích (khi bạn đang đăng nhập):Nhắc người dùng đăng nhập sau khi ông mất một hành động nào đó

http://dl.getdropbox.com/u/2792776/screenshots/2010-01-17_1645.png

Tôi muốn hiển thị liên kết "Thích" với người dùng không đăng nhập và sau đó, khi người dùng không đăng nhập nhấp vào "Thích", hãy hiển thị cho anh ta một hộp đèn có biểu mẫu "Đăng nhập hoặc Đăng ký" (như Digg/Reddit)

http://dl.getdropbox.com/u/2792776/screenshots/2010-01-17_1650.png

Cách tốt nhất để hoàn thành t là gì của anh ấy?

Hiện nay tôi đang sử dụng phương pháp này:

  1. Nhấp vào "Like" bài viết để /annotations/:id/vote (cơ thể POST cho biết người dùng đang thích hoặc "đánh dấu không thích").
  2. Hành động điều khiển vote Chú có require_userbefore_filter trông như thế này:

    def require_user 
        unless current_user 
        store_desired_location 
        flash[:notice] = "You'll need to login or register to do that" 
        redirect_to login_path # map.login '/login', :controller => 'user_sessions', :action => 'new' 
        return false 
        end 
    end 
    
  3. user_sessions#new trông như thế này:

    def new 
        @user_session = UserSession.new 
        respond_to do |format| 
        format.html {} 
        format.js { 
         render :layout => false 
        } 
        end 
    end 
    

Vấn đề là chuyển hướng không dường như hoạt động chính xác trên javascript:

http://dl.getdropbox.com/u/2792776/screenshots/2010-01-17_1700.png

Làm cách nào để chuyển hướng này chính xác?

Ngoài ra, đây có phải là cách tiếp cận chung phù hợp không? Một suy nghĩ khác mà tôi có là đính kèm một trình xử lý khác vào liên kết "Thích" trong javascript khi không có người dùng đã đăng nhập (nhưng tôi không nghĩ phương pháp này có hiệu quả với các hành động khác mà tôi muốn xử lý theo cùng một cách)

Trả lời

3

Có một vài vấn đề cần khắc phục ở đây.

  1. Trình duyệt nói chung không cho phép chuyển hướng đến yêu cầu POST.

  2. redirect_to không giữ nguyên định dạng mà không có đầu vào bổ sung.

  3. 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à:

  1. Yêu cầu chú thích # phiếu (POST)
  2. lọc required_user không
  3. làm cho phiên làm việc mới
  4. gửi thông tin đăng nhập và độc đáo POST dữ liệu trở lại chú thích # vote (POST)
  5. 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.
  6. 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:

  1. Tạo một phần mới được mô hình hóa sau phần vote_form_replica.
  2. Thêm câu lệnh hiển thị tương ứng vào mẫu phiên mới.
  3. Áp dụng bộ lọc cho hành động của bạn.
+0

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 –

+0

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

+0

Ồ, cũng - không nên 'render: action => 'user_sessions/new'' là' render: template =>' user_sessions/new'' (trong 'require_user')? –

0

Tôi sẽ tiếp cận điều này theo cách bạn mô tả ở cuối câu hỏi của mình. Trước khi hiển thị trang ban đầu, hãy kiểm tra xem người dùng có đăng nhập hay không. Nếu có, liên kết "Thích" nên sử dụng hành vi bình thường của họ. Nếu không, hãy liên kết sự kiện nhấp để hiển thị bảng đăng ký/đăng nhập. Không có gì về điều này mà không thể được tái sử dụng. Trên thực tế, chúng tôi sử dụng phương pháp chính xác này trong công việc của mình. Bất kỳ hành động nào của người dùng yêu cầu xác thực hoặc tuân theo hành vi thông thường của nó hoặc bật lên bảng điều khiển đăng nhập chung tùy thuộc vào trạng thái đăng nhập tại thời điểm tải trang.

+0

"Nếu không, hãy liên kết sự kiện nhấp để hiển thị bảng đăng ký/đăng nhập" - Tôi chỉ không muốn thực hiện việc này cho mọi hành động yêu cầu người dùng đăng nhập (đồng thời, khi người dùng DOES đăng nhập, làm cách nào để đảm bảo rằng bất kỳ hành động nào mà anh ta yêu cầu ban đầu đã diễn ra?) –

Các vấn đề liên quan