Tom*_*man 8 authentication ruby-on-rails
你可以在我的说唱歌词解释网站上做的一件事是"喜欢"解释(一旦你登录):
http://dl.getdropbox.com/u/2792776/screenshots/2010-01-17_1645.png
我想向未登录的用户显示"赞"链接,然后,当未登录的用户点击"赞"时,向他显示一个带有"登录或注册"表单的灯箱(如Digg)/Reddit)
http://dl.getdropbox.com/u/2792776/screenshots/2010-01-17_1650.png
实现这一目标的最佳方法是什么?
目前我正在使用这种方法:
/annotations/:id/vote(POST主体指示用户是喜欢还是"不喜欢").该vote注解控制器操作有一个require_user before_filter看起来像这样:
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
Run Code Online (Sandbox Code Playgroud)user_sessions#new 看起来像这样:
def new
@user_session = UserSession.new
respond_to do |format|
format.html {}
format.js {
render :layout => false
}
end
end
Run Code Online (Sandbox Code Playgroud)问题是重定向似乎无法在javascript上正常工作:
http://dl.getdropbox.com/u/2792776/screenshots/2010-01-17_1700.png
如何让它正确重定向?
此外,这是正确的一般方法吗?另一个想法是当没有登录用户时,在javascript中为"Like"链接附加一个不同的处理程序(但我认为这种方法不能很好地扩展到我想以相同方式处理的其他操作)
这里有一些问题需要克服。
浏览器通常不允许重定向到 POST 请求。
如果没有额外的输入,redirect_to 不会保留格式。
存储位置不保留表单数据。
所有这些问题都可以通过消除重定向来解决。
这是我过去的交接方式:
不是在 required_user 中重定向,而是渲染。如果 before 过滤器重定向或渲染,则挂起的操作将被取消。(也不需要返回 false)。不幸的是,这条路线模糊了控制器的边界。但允许简单的 html 回退,并使其自身变得干燥。
新工作流程的高级视图将是:
首先重新设计 require_user 以呈现 user_sessions#new 模板。
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
Run Code Online (Sandbox Code Playgroud)
这@user_session ||= UserSession.new确保我们可以将验证错误返回到表单。
现在我们必须增强您的 user_session#new 模板,以便它可以记住该操作。另外,如果您计划使用灯箱,这应该是由相关 RJS 或 new.html.erb 渲染的部分渲染。
首先,我们创建一个部分来创建隐藏字段,保留在重定向中丢失的 POST 数据:
<% 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 %>
Run Code Online (Sandbox Code Playgroud)
然后在登录部分中渲染该部分,该部分将占据您的灯箱:
<%= 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%>
Run Code Online (Sandbox Code Playgroud)
form_tag 中 url 的空哈希看起来像是一个错误,但事实并非如此。它确保将表单数据发布到呈现表单的 url。此时应该是annotations/:id/vote
现在让新过滤器登录。本质上它将执行 UserSessionsController#create 在没有渲染/重定向的情况下执行的操作。以下内容是从 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
Run Code Online (Sandbox Code Playgroud)
剩下的就是确保过滤器顺序正确。
before_filter :authenticate, :require_user, :only => :vote
Run Code Online (Sandbox Code Playgroud)
注意:如果没有此版本的验证,您可能不会使用此版本的 require_user,因此将它们组合到单个过滤器中是有意义的。
就是这样。这种设置方式允许强大的 DRY 且易于重用的代码。通过将新过滤器放入 ApplicationController,它们可以在任何控制器中使用。从现在开始,将此功能添加到任何其他控制器/操作只需 3 个简单步骤:
| 归档时间: |
|
| 查看次数: |
882 次 |
| 最近记录: |