Hi Iam using devise for my authentication of the user
嗨,我使用设计我的用户身份验证
I have followed the various tutorials for getting the login in a popup window but Iam not successful can any one kindly tell how do it in details. I have tried various tutorials but nothing is working every thing is redirecting again in to a login page.
我已经按照各种教程在弹出窗口中获取登录但是我没有成功,任何人都可以告诉我们如何详细说明。我已经尝试了各种教程,但没有任何工作,每一件事都重定向到登录页面。
I am a newbie in rails Please kindly help to this.
我是铁路的新手请帮忙。
I am unable to get the login on the same page
我无法在同一页面上登录
Here Is my new.html.erb
这是我的new.html.erb
<%= form_for(:user, :html => {:id => 'login_form'}, :url => user_session_path, :remote => :true, :format => :json) do |f| %>
<%= f.email_field :email, :autofocus => true, :placeholder => "email", :id => 'login_email' %>
<%= f.password_field :password, :placeholder => "password", :id => 'login_password' %>
<% if devise_mapping.rememberable? -%>
<div><%= f.check_box :remember_me %> <%= f.label :remember_me %></div>
<% end -%>
<div><%= image_submit_tag('modals/account/login_submit.png') %></div>
<% end %>
This is my headers page
这是我的标题页面
<% if user_signed_in? %>
<p>Welcome <%= current_user.email %></p>
<%= link_to "Sign out", destroy_user_session_path, :method => :delete %>
<% else %>
<p>You are not signed in.</p>
<%= link_to "Sign in", new_user_session_path, :remote => :true %>
<% end %>
1 个解决方案
#1
21
Firstly, do you want a pop-up or a pop-over?
首先,你想要弹出窗口还是弹出窗口?
Pop-ups are new Windows, and are reminiscent of 90's ads, whereas pop-overs (sometimes called modals) are integrated elements in the UI, and are basically just a div on a darkened background
弹出窗口是新的Windows,让人想起90年代的广告,而弹出式窗口(有时称为模态)是UI中的集成元素,基本上只是黑暗背景上的div
All Web 2.0 sites use pop-overs to enhance usability, whereas pop-ups detract from the experience :)
所有Web 2.0站点都使用弹出窗口来增强可用性,而弹出窗口则会减损体验:)
Pop-Overs
We have implemented the functionality you seek (click "login" at the top of this development site)
我们已经实现了您所寻求的功能(点击此开发站点顶部的“登录”)
There are several things you have to get right to make this work - I'll detail them for you here:
你需要做好几件事才能完成这项工作 - 我会在这里为你详细说明:
Routes
#config/routes.rb
devise_for :users, :path => '', :controllers => {:sessions => 'sessions', :registrations => 'registrations'}, :path_names => { :sign_in => 'login', :password => 'forgot', :confirmation => 'confirm', :unlock => 'unblock', :registration => 'register', :sign_up => 'new', :sign_out => 'logout'}
First step is to get your routes sorted
第一步是对您的路线进行排序
Although Devise has good routing documentation, you'll need to customize your routes to include customized session
/ registration
controllers, as well as any custom paths you want
虽然Devise有很好的路由文档,但您需要自定义路由以包含自定义会话/注册控制器,以及您想要的任何自定义路径
The most important part of the routes is (you need custom controllers!):
路线中最重要的部分是(你需要自定义控制器!):
:controllers => {:sessions => 'sessions', :registrations => 'registrations'}
Controllers
Next, you need to add ajax response functionality to your sessions
and registrations
controllers. Even though Devise adds these controllers with every install, they remain hidden, and if you want to add functionality, you'll have to extend them
接下来,您需要向会话和注册控制器添加ajax响应功能。即使Devise在每次安装时添加了这些控制器,它们仍然是隐藏的,如果你想添加功能,你必须扩展它们
Here are our sessions & registrations controllers (LOTS of this code can be removed, but it works for us right now):
这是我们的会话和注册控制器(可以删除此代码的许多内容,但它现在适用于我们):
Session
#app/controllers/sessions_controller.rb
class SessionsController < DeviseController
prepend_before_filter :require_no_authentication, :only => [ :new, :create ]
prepend_before_filter :allow_params_authentication!, :only => :create
prepend_before_filter { request.env["devise.skip_timeout"] = true }
prepend_view_path 'app/views/devise'
# GET /resource/sign_in
def new
self.resource = resource_class.new(sign_in_params)
clean_up_passwords(resource)
respond_with(resource, serialize_options(resource))
end
# POST /resource/sign_in
def create
self.resource = warden.authenticate!(auth_options)
set_flash_message(:notice, :signed_in) if is_navigational_format?
sign_in(resource_name, resource)
respond_to do |format|
format.json { render :json => {}, :status => :ok }
format.html { respond_with resource, :location => after_sign_in_path_for(resource) }
end
end
# DELETE /resource/sign_out
def destroy
redirect_path = after_sign_out_path_for(resource_name)
signed_out = (Devise.sign_out_all_scopes ? sign_out : sign_out(resource_name))
set_flash_message :notice, :signed_out if signed_out && is_navigational_format?
# We actually need to hardcode this as Rails default responder doesn't
# support returning empty response on GET request
respond_to do |format|
format.all { head :no_content }
format.any(*navigational_formats) { redirect_to redirect_path }
end
end
protected
def sign_in_params
devise_parameter_sanitizer.sanitize(:sign_in)
end
def serialize_options(resource)
methods = resource_class.authentication_keys.dup
methods = methods.keys if methods.is_a?(Hash)
methods << :password if resource.respond_to?(:password)
{ :methods => methods, :only => [:password] }
end
def auth_options
{ :scope => resource_name, :recall => "#{controller_path}#new" }
end
end
Registration
#app/controllers/registrations_controller.rb
class RegistrationsController < DeviseController
prepend_before_filter :require_no_authentication, :only => [ :new, :create, :cancel ]
prepend_before_filter :authenticate_scope!, :only => [:edit, :update, :destroy]
before_filter :configure_permitted_parameters
prepend_view_path 'app/views/devise'
# GET /resource/sign_up
def new
build_resource({})
respond_with self.resource
end
# POST /resource
def create
build_resource(sign_up_params)
if resource.save
if resource.active_for_authentication?
set_flash_message :notice, :signed_up if is_navigational_format?
sign_up(resource_name, resource)
respond_with resource, :location => after_sign_up_path_for(resource)
else
set_flash_message :notice, :"signed_up_but_#{resource.inactive_message}" if is_navigational_format?
expire_session_data_after_sign_in!
respond_with resource, :location => after_inactive_sign_up_path_for(resource)
end
else
clean_up_passwords resource
respond_to do |format|
format.json { render :json => resource.errors, :status => :unprocessable_entity }
format.html { respond_with resource }
end
end
end
# GET /resource/edit
def edit
render :edit
end
# PUT /resource
# We need to use a copy of the resource because we don't want to change
# the current user in place.
def update
self.resource = resource_class.to_adapter.get!(send(:"current_#{resource_name}").to_key)
prev_unconfirmed_email = resource.unconfirmed_email if resource.respond_to?(:unconfirmed_email)
if update_resource(resource, account_update_params)
if is_navigational_format?
flash_key = update_needs_confirmation?(resource, prev_unconfirmed_email) ?
:update_needs_confirmation : :updated
set_flash_message :notice, flash_key
end
sign_in resource_name, resource, :bypass => true
respond_with resource, :location => after_update_path_for(resource)
else
clean_up_passwords resource
respond_with resource
end
end
# DELETE /resource
def destroy
resource.destroy
Devise.sign_out_all_scopes ? sign_out : sign_out(resource_name)
set_flash_message :notice, :destroyed if is_navigational_format?
respond_with_navigational(resource){ redirect_to after_sign_out_path_for(resource_name) }
end
# GET /resource/cancel
# Forces the session data which is usually expired after sign
# in to be expired now. This is useful if the user wants to
# cancel oauth signing in/up in the middle of the process,
# removing all OAuth session data.
def cancel
expire_session_data_after_sign_in!
redirect_to new_registration_path(resource_name)
end
protected
# Custom Fields
def configure_permitted_parameters
devise_parameter_sanitizer.for(:sign_up) do |u|
u.permit(:first_name, :last_name,
:email, :password, :password_confirmation)
end
end
def update_needs_confirmation?(resource, previous)
resource.respond_to?(:pending_reconfirmation?) &&
resource.pending_reconfirmation? &&
previous != resource.unconfirmed_email
end
# By default we want to require a password checks on update.
# You can overwrite this method in your own RegistrationsController.
def update_resource(resource, params)
resource.update_with_password(params)
end
# Build a devise resource passing in the session. Useful to move
# temporary session data to the newly created user.
def build_resource(hash=nil)
self.resource = resource_class.new_with_session(hash || {}, session)
end
# Signs in a user on sign up. You can overwrite this method in your own
# RegistrationsController.
def sign_up(resource_name, resource)
sign_in(resource_name, resource)
end
# The path used after sign up. You need to overwrite this method
# in your own RegistrationsController.
def after_sign_up_path_for(resource)
after_sign_in_path_for(resource)
end
# The path used after sign up for inactive accounts. You need to overwrite
# this method in your own RegistrationsController.
def after_inactive_sign_up_path_for(resource)
respond_to?(:root_path) ? root_path : "/"
end
# The default url to be used after updating a resource. You need to overwrite
# this method in your own RegistrationsController.
def after_update_path_for(resource)
signed_in_root_path(resource)
end
# Authenticates the current scope and gets the current resource from the session.
def authenticate_scope!
send(:"authenticate_#{resource_name}!", :force => true)
self.resource = send(:"current_#{resource_name}")
end
def sign_up_params
devise_parameter_sanitizer.sanitize(:sign_up)
end
def account_update_params
devise_parameter_sanitizer.sanitize(:account_update)
end
end
Forms
Once you've added the backend functionality, you have to make your forms ajax-enabled. This is pretty simple:
一旦添加了后端功能,就必须使表单启用ajax。这很简单:
Login
#app/views/devise/sessions/new.html.erb
<%= form_for(devise_resource, :as => devise_resource_name, :html => {:id => 'login_form'}, :url => user_session_path, :remote => :true, :format => :json) do |f| %>
<%= f.email_field :email, :autofocus => true, :placeholder => "email", :id => 'login_email' %>
<%= f.password_field :password, :placeholder => "password", :id => 'login_password' %>
<% if devise_mapping.rememberable? -%>
<div><%= f.check_box :remember_me %> <%= f.label :remember_me %></div>
<% end -%>
<div><%= image_submit_tag('modals/account/login_submit.png') %></div>
<% end %>
Register
#app/views/devise/registrations/new.html.erb
<%= form_for(devise_resource, :as => devise_resource_name, :html => {:id => 'register_form'}, :url => user_registration_path, :remote => :true, :format => :json) do |f| %>
<div class="name_input_container">
<div class="name_input_cell">
<%= f.text_field :first_name, :autofocus => true, :class => 'first_name', :placeholder => 'first name' %>
<div class="error"><%= devise_resource.errors[:first_name].first if devise_resource.errors[:first_name].present? %></div>
</div>
<div class="name_input_cell_right">
<%= f.text_field :last_name, :class => 'last_name', :placeholder => 'last name' %>
<div class="error"><%= devise_resource.errors[:last_name].first if devise_resource.errors[:last_name].present? %></div>
</div>
</div>
<%= f.email_field :email, :placeholder => "email" %>
<div class="error"><%= devise_resource.errors[:email].first if devise_resource.errors[:email].present? %></div>
<%= f.password_field :password, :placeholder => "password", :title => "8+ characters" %>
<div class="error"><%= devise_resource.errors[:password].first if devise_resource.errors[:password].present? %></div>
<%= f.password_field :password_confirmation, :placeholder => "confirm password" %>
<div class="error"><%= devise_resource.errors[:password_confirmation].first if devise_resource.errors[:password_confirmation].present? %></div>
<div class="option_buttons">
<div class="already_registered">
<%= link_to 'already registered?', '#', :class => 'already_registered', :id => 'already_registered', :view => 'login' %>
</div>
<%= image_submit_tag('modals/account/register_submit.png', :class => 'go') %>
<div class="clear"></div>
</div>
<% end %>
Javascript
Finally, you just need to be able to handle the responses from Ajax:
最后,您只需要能够处理来自Ajax的响应:
Login
//app/assets/javscripts/application.js
$(document).on('submit', '#login_form', function(e) {
//do stuff here
}).on('ajax:success', '#login_form', function(e, data, status, xhr) {
//do stuff here
}).on('ajax:error', '#login_form', function(e, data, status, xhr) {
//do stuff here
});
Register
//app/assets/javascripts/application.js
$(document).on('submit', '#register_form', function(e){
//do stuff here
}).on('ajax:success', '#register_form', function(e, data, status, xhr) {
//do stuff here
}).on('ajax:error', '#register_form', function(e, data, status, xhr) {
//do stuff here
});
#1
21
Firstly, do you want a pop-up or a pop-over?
首先,你想要弹出窗口还是弹出窗口?
Pop-ups are new Windows, and are reminiscent of 90's ads, whereas pop-overs (sometimes called modals) are integrated elements in the UI, and are basically just a div on a darkened background
弹出窗口是新的Windows,让人想起90年代的广告,而弹出式窗口(有时称为模态)是UI中的集成元素,基本上只是黑暗背景上的div
All Web 2.0 sites use pop-overs to enhance usability, whereas pop-ups detract from the experience :)
所有Web 2.0站点都使用弹出窗口来增强可用性,而弹出窗口则会减损体验:)
Pop-Overs
We have implemented the functionality you seek (click "login" at the top of this development site)
我们已经实现了您所寻求的功能(点击此开发站点顶部的“登录”)
There are several things you have to get right to make this work - I'll detail them for you here:
你需要做好几件事才能完成这项工作 - 我会在这里为你详细说明:
Routes
#config/routes.rb
devise_for :users, :path => '', :controllers => {:sessions => 'sessions', :registrations => 'registrations'}, :path_names => { :sign_in => 'login', :password => 'forgot', :confirmation => 'confirm', :unlock => 'unblock', :registration => 'register', :sign_up => 'new', :sign_out => 'logout'}
First step is to get your routes sorted
第一步是对您的路线进行排序
Although Devise has good routing documentation, you'll need to customize your routes to include customized session
/ registration
controllers, as well as any custom paths you want
虽然Devise有很好的路由文档,但您需要自定义路由以包含自定义会话/注册控制器,以及您想要的任何自定义路径
The most important part of the routes is (you need custom controllers!):
路线中最重要的部分是(你需要自定义控制器!):
:controllers => {:sessions => 'sessions', :registrations => 'registrations'}
Controllers
Next, you need to add ajax response functionality to your sessions
and registrations
controllers. Even though Devise adds these controllers with every install, they remain hidden, and if you want to add functionality, you'll have to extend them
接下来,您需要向会话和注册控制器添加ajax响应功能。即使Devise在每次安装时添加了这些控制器,它们仍然是隐藏的,如果你想添加功能,你必须扩展它们
Here are our sessions & registrations controllers (LOTS of this code can be removed, but it works for us right now):
这是我们的会话和注册控制器(可以删除此代码的许多内容,但它现在适用于我们):
Session
#app/controllers/sessions_controller.rb
class SessionsController < DeviseController
prepend_before_filter :require_no_authentication, :only => [ :new, :create ]
prepend_before_filter :allow_params_authentication!, :only => :create
prepend_before_filter { request.env["devise.skip_timeout"] = true }
prepend_view_path 'app/views/devise'
# GET /resource/sign_in
def new
self.resource = resource_class.new(sign_in_params)
clean_up_passwords(resource)
respond_with(resource, serialize_options(resource))
end
# POST /resource/sign_in
def create
self.resource = warden.authenticate!(auth_options)
set_flash_message(:notice, :signed_in) if is_navigational_format?
sign_in(resource_name, resource)
respond_to do |format|
format.json { render :json => {}, :status => :ok }
format.html { respond_with resource, :location => after_sign_in_path_for(resource) }
end
end
# DELETE /resource/sign_out
def destroy
redirect_path = after_sign_out_path_for(resource_name)
signed_out = (Devise.sign_out_all_scopes ? sign_out : sign_out(resource_name))
set_flash_message :notice, :signed_out if signed_out && is_navigational_format?
# We actually need to hardcode this as Rails default responder doesn't
# support returning empty response on GET request
respond_to do |format|
format.all { head :no_content }
format.any(*navigational_formats) { redirect_to redirect_path }
end
end
protected
def sign_in_params
devise_parameter_sanitizer.sanitize(:sign_in)
end
def serialize_options(resource)
methods = resource_class.authentication_keys.dup
methods = methods.keys if methods.is_a?(Hash)
methods << :password if resource.respond_to?(:password)
{ :methods => methods, :only => [:password] }
end
def auth_options
{ :scope => resource_name, :recall => "#{controller_path}#new" }
end
end
Registration
#app/controllers/registrations_controller.rb
class RegistrationsController < DeviseController
prepend_before_filter :require_no_authentication, :only => [ :new, :create, :cancel ]
prepend_before_filter :authenticate_scope!, :only => [:edit, :update, :destroy]
before_filter :configure_permitted_parameters
prepend_view_path 'app/views/devise'
# GET /resource/sign_up
def new
build_resource({})
respond_with self.resource
end
# POST /resource
def create
build_resource(sign_up_params)
if resource.save
if resource.active_for_authentication?
set_flash_message :notice, :signed_up if is_navigational_format?
sign_up(resource_name, resource)
respond_with resource, :location => after_sign_up_path_for(resource)
else
set_flash_message :notice, :"signed_up_but_#{resource.inactive_message}" if is_navigational_format?
expire_session_data_after_sign_in!
respond_with resource, :location => after_inactive_sign_up_path_for(resource)
end
else
clean_up_passwords resource
respond_to do |format|
format.json { render :json => resource.errors, :status => :unprocessable_entity }
format.html { respond_with resource }
end
end
end
# GET /resource/edit
def edit
render :edit
end
# PUT /resource
# We need to use a copy of the resource because we don't want to change
# the current user in place.
def update
self.resource = resource_class.to_adapter.get!(send(:"current_#{resource_name}").to_key)
prev_unconfirmed_email = resource.unconfirmed_email if resource.respond_to?(:unconfirmed_email)
if update_resource(resource, account_update_params)
if is_navigational_format?
flash_key = update_needs_confirmation?(resource, prev_unconfirmed_email) ?
:update_needs_confirmation : :updated
set_flash_message :notice, flash_key
end
sign_in resource_name, resource, :bypass => true
respond_with resource, :location => after_update_path_for(resource)
else
clean_up_passwords resource
respond_with resource
end
end
# DELETE /resource
def destroy
resource.destroy
Devise.sign_out_all_scopes ? sign_out : sign_out(resource_name)
set_flash_message :notice, :destroyed if is_navigational_format?
respond_with_navigational(resource){ redirect_to after_sign_out_path_for(resource_name) }
end
# GET /resource/cancel
# Forces the session data which is usually expired after sign
# in to be expired now. This is useful if the user wants to
# cancel oauth signing in/up in the middle of the process,
# removing all OAuth session data.
def cancel
expire_session_data_after_sign_in!
redirect_to new_registration_path(resource_name)
end
protected
# Custom Fields
def configure_permitted_parameters
devise_parameter_sanitizer.for(:sign_up) do |u|
u.permit(:first_name, :last_name,
:email, :password, :password_confirmation)
end
end
def update_needs_confirmation?(resource, previous)
resource.respond_to?(:pending_reconfirmation?) &&
resource.pending_reconfirmation? &&
previous != resource.unconfirmed_email
end
# By default we want to require a password checks on update.
# You can overwrite this method in your own RegistrationsController.
def update_resource(resource, params)
resource.update_with_password(params)
end
# Build a devise resource passing in the session. Useful to move
# temporary session data to the newly created user.
def build_resource(hash=nil)
self.resource = resource_class.new_with_session(hash || {}, session)
end
# Signs in a user on sign up. You can overwrite this method in your own
# RegistrationsController.
def sign_up(resource_name, resource)
sign_in(resource_name, resource)
end
# The path used after sign up. You need to overwrite this method
# in your own RegistrationsController.
def after_sign_up_path_for(resource)
after_sign_in_path_for(resource)
end
# The path used after sign up for inactive accounts. You need to overwrite
# this method in your own RegistrationsController.
def after_inactive_sign_up_path_for(resource)
respond_to?(:root_path) ? root_path : "/"
end
# The default url to be used after updating a resource. You need to overwrite
# this method in your own RegistrationsController.
def after_update_path_for(resource)
signed_in_root_path(resource)
end
# Authenticates the current scope and gets the current resource from the session.
def authenticate_scope!
send(:"authenticate_#{resource_name}!", :force => true)
self.resource = send(:"current_#{resource_name}")
end
def sign_up_params
devise_parameter_sanitizer.sanitize(:sign_up)
end
def account_update_params
devise_parameter_sanitizer.sanitize(:account_update)
end
end
Forms
Once you've added the backend functionality, you have to make your forms ajax-enabled. This is pretty simple:
一旦添加了后端功能,就必须使表单启用ajax。这很简单:
Login
#app/views/devise/sessions/new.html.erb
<%= form_for(devise_resource, :as => devise_resource_name, :html => {:id => 'login_form'}, :url => user_session_path, :remote => :true, :format => :json) do |f| %>
<%= f.email_field :email, :autofocus => true, :placeholder => "email", :id => 'login_email' %>
<%= f.password_field :password, :placeholder => "password", :id => 'login_password' %>
<% if devise_mapping.rememberable? -%>
<div><%= f.check_box :remember_me %> <%= f.label :remember_me %></div>
<% end -%>
<div><%= image_submit_tag('modals/account/login_submit.png') %></div>
<% end %>
Register
#app/views/devise/registrations/new.html.erb
<%= form_for(devise_resource, :as => devise_resource_name, :html => {:id => 'register_form'}, :url => user_registration_path, :remote => :true, :format => :json) do |f| %>
<div class="name_input_container">
<div class="name_input_cell">
<%= f.text_field :first_name, :autofocus => true, :class => 'first_name', :placeholder => 'first name' %>
<div class="error"><%= devise_resource.errors[:first_name].first if devise_resource.errors[:first_name].present? %></div>
</div>
<div class="name_input_cell_right">
<%= f.text_field :last_name, :class => 'last_name', :placeholder => 'last name' %>
<div class="error"><%= devise_resource.errors[:last_name].first if devise_resource.errors[:last_name].present? %></div>
</div>
</div>
<%= f.email_field :email, :placeholder => "email" %>
<div class="error"><%= devise_resource.errors[:email].first if devise_resource.errors[:email].present? %></div>
<%= f.password_field :password, :placeholder => "password", :title => "8+ characters" %>
<div class="error"><%= devise_resource.errors[:password].first if devise_resource.errors[:password].present? %></div>
<%= f.password_field :password_confirmation, :placeholder => "confirm password" %>
<div class="error"><%= devise_resource.errors[:password_confirmation].first if devise_resource.errors[:password_confirmation].present? %></div>
<div class="option_buttons">
<div class="already_registered">
<%= link_to 'already registered?', '#', :class => 'already_registered', :id => 'already_registered', :view => 'login' %>
</div>
<%= image_submit_tag('modals/account/register_submit.png', :class => 'go') %>
<div class="clear"></div>
</div>
<% end %>
Javascript
Finally, you just need to be able to handle the responses from Ajax:
最后,您只需要能够处理来自Ajax的响应:
Login
//app/assets/javscripts/application.js
$(document).on('submit', '#login_form', function(e) {
//do stuff here
}).on('ajax:success', '#login_form', function(e, data, status, xhr) {
//do stuff here
}).on('ajax:error', '#login_form', function(e, data, status, xhr) {
//do stuff here
});
Register
//app/assets/javascripts/application.js
$(document).on('submit', '#register_form', function(e){
//do stuff here
}).on('ajax:success', '#register_form', function(e, data, status, xhr) {
//do stuff here
}).on('ajax:error', '#register_form', function(e, data, status, xhr) {
//do stuff here
});