Rails 4设计登录为POPUP窗口 [英] Rails 4 Devise Login as a POPUP window

查看:205
本文介绍了Rails 4设计登录为POPUP窗口的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

Hi Iam使用devise进行身份验证用户



我已经按照各种教程在弹出窗口中获取登录信息,但是我没有成功可以任何一个告诉如何做细节。我已经尝试过各种教程,但没有任何工作,所有的东西都是重定向到登录页面。



我是一个新手在rails请帮助这个。



我无法登录同一页



这里是我的new.html.erb

  <%= form_for(:user,:html => {:id =>'login_form'},:url => user_session_path,:remote =>:true,:format =>:json) F | %GT; 

<%= f.email_field:email,:autofocus => true,:placeholder => email,:id => 'login_email'%>
<%= f.password_field:password,:placeholder => password,:id => 'login_password'%>

<%if devise_mapping.rememberable? - %GT;
< div><%= f.check_box:remember_me%> <%= f.label:remember_me%>< / div>
<%end - %>

< div><%= image_submit_tag('modals / account / login_submit.png')%>< / div>
<%end%>

这是我的标题页

 <%if user_signed_in? %GT; 
< p>欢迎<%= current_user.email%>< / p>
<%= link_to退出,destroy_user_session_path,:method => :删除%>
<%else%>
< p>您尚未登录。< / p>
<%= link_to登录,new_user_session_path,:remote => :true%>

<%end%>


解决方案

首先,你想要一个 popup或pop-over



弹出窗口是新的Windows,让人想起90年代的广告,而弹出窗口(有时称为模态)是UI中的集成元素,基本上是所有Web 2.0网站都使用弹出窗口提高可用性,而弹出式窗口会降低体验:)






Pop-Overs



我们已经实现了功能您寻求(点击此开发网站顶部的登录)



有一些事情你必须得到正确的工作 - 我会在这里详细说明:






路线

 #config / ro utes.rb 
devise_for:users,:path => '',:controllers => {:sessions => 'sessions',:registrations => 'registrations'},:path_names => {:sign_in => 'login',:password => '忘记',:确认=> 'confirm',:unlock => 'unblock',:registration => 'register',:sign_up => 'new',:sign_out => 'logout'}

第一步是让路由排序



尽管Devise具有良好路由文档,但您需要自定义路由以包含自定义的 session / 注册控制器,以及您想要的任何自定义路径



路线最重要的部分是(您需要自定义控制器!):

 :controllers => {:sessions => 'sessions',:registrations => 'registration'} 






控制器



接下来,您需要在会话注册中添加ajax响应功能控制器。即使Devise每次安装都添加了这些控制器,它们仍然保持隐藏,如果要添加功能,则必须扩展它们。



这是我们的会话&注册控制器(此代码的LOTS可以删除,但现在适用于我们):



会话

 #app / controllers / sessions_controller.rb 
class SessionsController< DeviseController
prepend_before_filter:require_no_authentication,:only => [:new,:create]
prepend_before_filter:allow_params_authentication !,:only => :创建
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?

#我们实际上需要硬编码为Rails默认响应者不
#支持返回空请求响应
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 =>方法,:only => [:password]}
end

def auth_options
{:scope => resource_name,:recall => #{controller_path} #new}
end
end

注册

 #app / controllers / registrations_controller.rb 
class RegistrationsController< DeviseController
prepend_before_filter:require_no_authentication,:only => [:new,:create,,cancel]
prepend_before_filter:authenticate_scope !,:only => $($)


$ b before_filter:configure_permitted_pa​​rameters

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)

如果resource.save
如果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}如果is_navigational_format?
expire_session_data_after_sign_in!
respond_with resource,:location => after_inactive_sign_up_path_for(资源)
end
else
clean_up_passwords资源

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
#我们需要使用资源的副本,因为我们不想更改
#当前用户到位。
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)

如果update_resource(resource,account_update_params)
如果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资源
respond_with资源
end
end

#DELETE / resource
def destroy
resource.destroy
Devise.sign_out_all_scopes? sign_out:sign_out(resource_name)
set_flash_message:notice,:destroy如果is_navigational_format?
respond_with_navigational(resource){redirect_to after_sign_out_path_for(resource_name)}
end

#GET / resource / cancel
#强制会话数据通常在符号
#现在要过期如果用户想要在进程中间
#cancel oauth签入/ up,
#删除所有OAuth会话数据,这是有用的。
def取消
expire_session_data_after_sign_in!
redirect_to new_registration_path(resource_name)
end

protected

#自定义字段
def configure_permitted_pa​​rameters
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.respond_to?(:pending_reconfirmation?)&&
resource.pending_reconfirmation? &安培;&安培;
以前!= resource.unconfirmed_email
end

#默认情况下,我们需要对更新进行密码检查。
#您可以在自己的RegistrationsController中覆盖此方法。
def update_resource(resource,params)
resource.update_with_password(params)
end

#构建在会话中传递的设计资源。用于将
#临时会话数据移动到新创建的用户。
def build_resource(hash = nil)
self.resource = resource_class.new_with_session(hash || {},session)
end

#注册。您可以在自己的
#RegistrationsController中覆盖此方法。
def sign_up(resource_name,resource)
sign_in(resource_name,resource)
end

#注册后使用的路径。您需要在您自己的注册控制器中覆盖此方法
#。
def after_sign_up_path_for(资源)
after_sign_in_path_for(资源)
end

#注册不活动帐户后使用的路径。您需要在您自己的RegistrationsController中覆盖
#这个方法。
def after_inactive_sign_up_path_for(资源)
respond_to?(:root_path)? root_path:/
end

#更新资源后要使用的默认网址。您需要在您自己的RegistrationsController中覆盖
#这个方法。
def after_update_path_for(资源)
signed_in_root_path(resource)
end

#验证当前范围,并从会话中获取当前资源。
def authenticate_scope!
发送(: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






strong>



添加后端功能后,您必须启用表单ajax。这很简单:



登录

 <%= form_for(devise_resource,:as => devise_resource_name,:html => {:id =>'login_form'} ,:url => user_session_path,:remote =>:true,:format =>:json)do | f | %GT; 

<%= f.email_field:email,:autofocus => true,:placeholder => email,:id => 'login_email'%>
<%= f.password_field:password,:placeholder => password,:id => 'login_password'%>

<%if devise_mapping.rememberable? - %GT;
< div><%= f.check_box:remember_me%> <%= f.label:remember_me%>< / div>
<%end - %>

< div><%= image_submit_tag('modals / account / login_submit.png')%>< / div>
<%end%>

注册

 #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 | %GT;

< div class =name_input_container>
< div class =name_input_cell>
<%= f.text_field:first_name,:autofocus => true,class => 'first_name',:placeholder => '名字'%>
< div class =error><%= devise_resource.errors [:first_name] .first if devise_resource.errors [:first_name] .present? %GT;< / 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? %GT;< / DIV>
< / div>
< / div>

<%= f.email_field:email,:placeholder => email%>
< div class =error><%= devise_resource.errors [:email] .first if devise_resource.errors [:email] .present? %GT;< / DIV>

<%= f.password_field:password,:placeholder => password,:title => 8+个字符%>
< div class =error><%= devise_resource.errors [:password] .first if devise_resource.errors [:password] .present? %GT;< / DIV>

<%= f.password_field:password_confirmation,:placeholder => 确认密码%>
< div class =error><%= devise_resource.errors [:password_confirmation] .first if devise_resource.errors [:password_confirmation] .present? %GT;< / DIV>

< div class =option_buttons>
< div class =already_registered>
<%= link_to已注册?,'#',: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 p>

最后,您只需要能够处理Ajax的响应:



登录

  // 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
});

注册

  // 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
});


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

<%= 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 %>

解决方案

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

All Web 2.0 sites use pop-overs to enhance usability, whereas pop-ups detract from the experience :)


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

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

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:

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:

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  
});

这篇关于Rails 4设计登录为POPUP窗口的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆