本文介绍了Rails 4如何在错误时覆盖设计响应路径的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我已经为此苦苦挣扎了一段时间。我有一个Rails4 / Devise 3.1应用程序,系统中有两个用户:

I've been struggling for a while with this one. I have a Rails4/Devise 3.1 app with two users in the system:


  1. 毕业

  2. 雇主

和一个devise用户,可以通过多态:profile 关联。我有毕业生通过 / graduate / sign_up 路径注册,而雇主通过 / employer / sign_up 路径注册,两者均通过相同的 /views/devise/registrations/new.html.erb 视图(因为它们的注册形式几乎相同-电子邮件和密码)。一切正常,除非出现验证错误,否则 RegistrationsController#create.respond_with资源始终将两种用户类型都重定向到 / users path,我需要将它们重定向回它们最初来自的位置,例如 /研究生/报名 /雇主/报名。我尝试用 redirect_to respond_替换为,但最终导致资源对象丢失,并带有相关的错误消息。

and one devise User who can be either a Graduate or Employer via a polymorphic :profile association. I have Graduates sign up via /graduate/sign_up path and employers via /employer/sign_up path both of which route to the same /views/devise/registrations/new.html.erb view (since their signup form is pretty much the same - email and password). Everything works fine, except when there is a validation error, RegistrationsController#create.respond_with resource always redirects both user types to /users path and I need to redirect them back to where they originally came from, e.g. /graduate/sign_up or /employer/sign_up respectively. I've tried replacing respond_with with redirect_to, but I end up loosing the resource object with associated error messages. Any idea guys on how this can be done?

这些是我的模型吗?

class User < ActiveRecord::Base
  devise :database_authenticatable, :registerable,
         :recoverable, :rememberable, :trackable, :validatable

  belongs_to :profile, polymorphic: true
end

class Graduate < ActiveRecord::Base
  has_one :user, as: :profile 
end

class Employer < ActiveRecord::Base
  has_one :user, as: :profile
end

注册控制器:

class RegistrationsController < Devise::RegistrationsController

  def create
    build_resource sign_up_params

    user_type = params[:user][:user_type]
    # This gets set to either 'Graduate' or 'Employer'
    child_class_name = user_type.downcase.camelize
    resource.profile = child_class_name.constantize.new

    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_with resource
    end
  end
end

注册视图(对于毕业生和雇主均相同):

Registration view (same for both, graduates and employers):

<h2>Sign up</h2>

<%= form_for(resource, as: resource_name, url: registration_path(resource_name)) do |f| %>
  <%= devise_error_messages! %>

  <div><%= f.label :email %><br />
  <%= f.email_field :email, :autofocus => true %></div>

  <div><%= f.label :password %><br />
  <%= f.password_field :password %></div>

  <div><%= f.label :password_confirmation %><br />
  <%= f.password_field :password_confirmation %></div>
  <%= hidden_field resource_name, :user_type, value: params[:user][:user_type] %>

  <div><%= f.submit "Sign up" %></div>
<% end %>

<%= render "devise/shared/links" %>

这些是我的路线:

 devise_for :users, :controllers => { :registrations => 'registrations' }

 devise_scope :user do
    match 'graduate/sign_up', to: 'registrations#new', user: { user_type: 'graduate' }, via: [:get]
    match 'employer/sign_up', to: 'registrations#new', user: { user_type: 'employer' }, via: [:get]
  end

  root to: 'home#index'

耙路的输出;

$ rake routes
                  Prefix Verb     URI Pattern                    Controller#Action
        new_user_session GET      /users/sign_in(.:format)       devise/sessions#new
            user_session POST     /users/sign_in(.:format)       devise/sessions#create
    destroy_user_session DELETE   /users/sign_out(.:format)      devise/sessions#destroy
           user_password POST     /users/password(.:format)      devise/passwords#create
       new_user_password GET      /users/password/new(.:format)  devise/passwords#new
      edit_user_password GET      /users/password/edit(.:format) devise/passwords#edit
                         PATCH    /users/password(.:format)      devise/passwords#update
                         PUT      /users/password(.:format)      devise/passwords#update
cancel_user_registration GET      /users/cancel(.:format)        registrations#cancel
       user_registration POST     /users(.:format)               registrations#create
   new_user_registration GET      /users/sign_up(.:format)       registrations#new
  edit_user_registration GET      /users/edit(.:format)          registrations#edit
                         PATCH    /users(.:format)               registrations#update
                         PUT      /users(.:format)               registrations#update
                         DELETE   /users(.:format)               registrations#destroy
        graduate_sign_up GET /graduate/sign_up(.:format)    registrations#new {:user=>{:user_type=>"graduate"}}
        employer_sign_up GET /employer/sign_up(.:format)    registrations#new {:user=>{:user_type=>"employer"}}
                    root GET      /   


推荐答案

,如果您已有一个名为#index的现有模板,则忽略:location 参数。我仍然不明白为什么当资源有错误时,Devise为什么会重定向到#index或#show。

Apparently, the :location parameter is ignored if you have an existing template called, well, in this case, #index. I still don't understand why Devise redirects to #index or #show when the resource has errors on it.

我将更新此答案,以了解更多信息。

I'll update this answer as I find out more.

这篇关于Rails 4如何在错误时覆盖设计响应路径的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

10-23 20:51