首页 > 解决方案 > 使用 Devise 时注册失败如何保持在同一页面上?(注册表格显示在根页面上)

问题描述

我是这个社区的新用户作为登录用户,但在没有登录的情况下已经被你们保存了几次。非常感谢。

我对 Ruby-on-Rails 也比较陌生。

我一直在窃听两天,打算禁用由设计创建的重定向...

基本上,我有一个 home_page ,其中显示了一个自定义注册表单,使用 form_for 并设计如下:

<div class="signup">
    <div>
      <h2>Create a new account</h2>
      <p>It's quick and easy.</p>
    </div>

    <%= form_for(resource, as: resource, url: registration_path(resource)) do |f| %>
      <%#= f.error_notification %>

      <div class="form-styling">
        <div>
          <%= f.text_field :first_name,
                          required: true,
                          autofocus: true,
                          placeholder: "First Name",
                          label: false,
                          autocomplete: "off" %>

          <%= f.text_field :family_name,
                          required: true,
                          placeholder: "Family Name",
                          label: false,
                          autocomplete: "off" %>
        </div>
        <div>
          <%= f.text_field :username,
                          required: true,
                          placeholder: "Username",
                          label: false,
                          autocomplete: "off" %>
          <%= f.email_field :email,
                           required: true,
                           placeholder: "Email",
                           label: false,
                           autocomplete: "off" %>
        </div>
        <div>
          <%= f.password_field :password,
                              required: true,
                              hint: ("#{@minimum_password_length} characters minimum" if @minimum_password_length),
                              placeholder: "Password",
                              label: false,
                              autocomplete: "new-password" %>
          <%= f.password_field :password_confirmation,
                              required: true,
                              placeholder: "Password Confirmation",
                              label: false,
                              autocomplete: "new-password" %>
        </div>
        <div>
          <%= f.text_field :address,
                          required: true,
                          placeholder: "Neighbourhood",
                          label: false,
                          autocomplete: "off" %>
        </div>
        <div class="bottom-signup">
          <div class="sign-up-btn">
            <%= f.submit "Sign up" %>
          </div>
          <%- if devise_mapping.omniauthable? %>
            <%- resource_class.omniauth_providers.each do |provider| %>
              <%= link_to "Sign up with #{OmniAuth::Utils.camelize(provider)}", omniauth_authorize_path(resource_name, provider) %>
            <% end %>
          <% end %>
        </div>
      </div>

    <% end %>
  </div>

此表单可以按需要完美运行,但如果 Devise 所需的参数之一为 false(例如:password_confirmation != password),它会将我重定向到:http://localhost:3000/users 而不是 http://localhost:3000/我希望显示表单的位置。

这是由于设计框架,我理解,但我似乎无法设法找到解决它的方法..

我试过这样改变设计注册控制器

class Users::RegistrationsController < Devise::RegistrationsController
  # before_action :configure_sign_up_params, only: [:create]
  # before_action :configure_account_update_params, only: [:update]

  # GET /resource/sign_up
  # def new
  #   super
  # end

  # POST /resource
  def create
    build_resource(sign_up_params)
    if resource.save
      redirect_to products_path
    else
      redirect_to root_path
    end
    yield resource if block_given?
    if resource.persisted?
      if resource.active_for_authentication?
        set_flash_message! :notice, :signed_up
        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}"
        expire_data_after_sign_in!
        respond_with resource, location: after_inactive_sign_up_path_for(resource)
       end
     else
      clean_up_passwords resource
      set_minimum_password_length
      respond_with redirect_to: root_path(resource),
                   notice: resource.errors['current_password'][0]
     end
  end

  # GET /resource/edit
  # def edit
  #   super
  # end

  # PUT /resource
  # def update
  #   super
  # end

  # DELETE /resource
  # def destroy
  #   super
  # 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
  #   super
  # end

  # protected

  # If you have extra params to permit, append them to the sanitizer.
  # def configure_sign_up_params
  #   devise_parameter_sanitizer.permit(:sign_up, keys: [:attribute])
  # end

  # If you have extra params to permit, append them to the sanitizer.
  # def configure_account_update_params
  #   devise_parameter_sanitizer.permit(:account_update, keys: [:attribute])
  # end

  # The path used after sign up.
  # def after_sign_up_path_for(resource)
  #   super(resource)
  # end

  # The path used after sign up for inactive accounts.
  # def after_inactive_sign_up_path_for(resource)
  #   super(resource)
  # end
end

这是我的ApplicationController

class ApplicationController < ActionController::Base
  before_action :authenticate_user!
  before_action :configure_permitted_parameters, if: :devise_controller?
  protect_from_forgery with: :exception
  include Pundit

  # Pundit: white-list approach.
  after_action :verify_authorized, except: :index, unless: :skip_pundit?
  after_action :verify_policy_scoped, only: :index, unless: :skip_pundit?

  # Uncomment when you *really understand* Pundit!
  # rescue_from Pundit::NotAuthorizedError, with: :user_not_authorized
  # def user_not_authorized
  #   flash[:alert] = "You are not authorized to perform this action."
  #   redirect_to(root_path)
  # end

  private

  def skip_pundit?
    devise_controller? || params[:controller] =~ /(^(rails_)?admin)|(^pages$)/
  end

  def configure_permitted_parameters
    # For additional fields in app/views/devise/registrations/new.html.erb
    devise_parameter_sanitizer.permit(:sign_up, keys: [:first_name, :family_name, :username, :address])

    # For additional in app/views/devise/registrations/edit.html.erb
    devise_parameter_sanitizer.permit(:account_update, keys: [:username])
  end

  def after_sign_in_path_for(resource)
    return products_path
  end

  def after_sign_up_path_for(resource)
    return products_path
  end
end

这些是我的路线

devise_scope :user do
    get "/sign_in" => "pages#home" # custom path to login/sign_in
    get "/sign_up" => "pages#home", as: "new_user_registration" # custom path to sign_up/registration
  end

  devise_for :users, controllers: {
    sessions: 'users/sessions',
    registrations: 'users/registrations'
  }

  root to: 'pages#home'

我对这件事要疯了,但我真的很想了解Devise ..

需要帮助请叫我。

提前致谢!

标签: ruby-on-railsrubydevise

解决方案


又是我。

经过一番努力,我已经和我的一个朋友解决了这个问题。

这是一条可以禁用自动重定向到设计表单并启用设置您自己的路径并在注册失败后保留在 root_path 上的路径

1)将这些行添加到您的路线中,以覆盖对设计生成表单的直接回调并自定义您的用户旅程。

 devise_for :users, controllers: {
    registrations: 'users/registrations'
  }

通过这样做,您告诉 Rails 您正在更改用于注册的设计控制器的变量。

2) 在你的 controllers/users/registrations_controller.rb 创建一个新方法 create

def create
    build_resource(sign_up_params)
    resource.save
    yield resource if block_given?
    if resource.persisted?
      if resource.active_for_authentication?
        set_flash_message! :notice, :signed_up
        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}"
        expire_data_after_sign_in!
        respond_with resource, location: after_inactive_sign_up_path_for(resource)
      end
    else
      clean_up_passwords resource
      set_minimum_password_length
      render "pages/home"
    end
  end

我在这里所做的只是将最后一个包裹从:

else
      clean_up_passwords resource
      set_minimum_password_length
      respond_with resource, :location => after_sign_in_path_for(resource)
    end

else
      clean_up_passwords resource
      set_minimum_password_length
      render "pages/home"
    end

3)然后您必须在名为custom_failure.rb的lib 文件夹中创建一个新文件(lib 文件夹中的任何位置都可以正常工作)。在此文件中,添加以下行:

class CustomFailure < Devise::FailureApp
  def redirect_url
    '/'
  end

def route
  '/'
end

  # You need to override respond to eliminate recall
  def respond
    if http_auth?
      http_auth
    else
      redirect
    end
  end
end

在这里,您覆盖响应以消除召回。

4) 然后在config/initializers/devise.rb 中添加以下行:

config.warden do |manager|
    manager.failure_app = CustomFailure
  end

基本上,在这里您告诉设计查看您刚刚创建的 custom_failure.rb 文件以防发生故障。

5) 最后,在您的config/application.rb中将这些行添加到您的模块中:

config.autoload_paths << Rails.root.join('lib')

在这里,您告诉 Rails 自动加载您的“lib”文件夹和其中的所有文件(这一步似乎对所有用户都不是强制性的,但我的 rails 应用程序还没有自动加载“lib”文件)。


我希望这对你们中的一些人有所帮助。

享受您的代码。

最好的,伊斯特


推荐阅读