如何删除要注册的 Devise 路由?

我在 Rails 3应用程序中使用 Devise,但在这种情况下,用户必须由现有用户创建,用户决定他/她将拥有什么权限。

因此,我要:

  • 删除用户注册的路由
  • 仍然允许用户编辑他们的配置文件(更改电子邮件地址和密码) 之后他们已经注册

我怎么能这么做?

目前,我通过在 devise_for :users之前放置以下内容,有效地消除了这条路线:

match 'users/sign_up' => redirect('/404.html')

行得通,但我想还有更好的办法,对吧?

更新

正如 Benoit Garret 所说,在我的情况下,最好的解决方案是跳过大规模创建注册路线,只创建我实际想要的路线。

为此,我首先运行 rake routes,然后使用输出重新创建我想要的输出。最终的结果是:

devise_for :users, :skip => [:registrations]
as :user do
get 'users/edit' => 'devise/registrations#edit', :as => 'edit_user_registration'
put 'users' => 'devise/registrations#update', :as => 'user_registration'
end

请注意:

  • 我还有 :registerable在我的 User模型
  • devise/registrations处理更新电子邮件和密码
  • 更新其他用户属性-权限等-由不同的控制器处理

实际的答案是:

删除默认设计路径的路由; 即:

devise_for :users, path_names: {
sign_up: ''
}
60253 次浏览

你可以在你的模型中这样做

# typical devise setup in User.rb
devise :database_authenticatable, :registerable, :recoverable, :rememberable, :trackable, :validatable

改成:

devise :database_authenticatable, :recoverable, :rememberable, :trackable, :validatable

注意到符号 :registerable已被删除

就是这样,没有其他需要。所有的路由和注册页面的链接也被神奇地删除了。

我也试图这样做,但 谷歌设计小组的线索劝阻我寻找一个真正干净的解决方案。

我引用 José Valim (设计维护者)的话:

没有直接的选择,您可以提供一个补丁 或者使用: Skip = > : 可注册并且只添加您想要的路由。

最初的问题是:

有没有什么好的方法可以删除一个特定的路由(删除路由) 从 Rails 来的?

您可以修改 devise gem 本身:

gem which devise

让我们假设路径是: /usr/local/lib/ruby/gems/1.9.1/gems/devise-1.4.2/lib/devise

那就去

编辑该目录中的 routes.rb。有一个叫做 def devise_registration(mapping, controllers)的方法,你可以修改它来去除新的动作。您还可以完全删除 devise_registration的映射

我有过类似的问题,试图删除 创造新的不受欢迎的设计路径:

以前:

 devise_for :users

耙道

accept_user_invitation GET    /users/invitation/accept(.:format)           devise/invitations#edit
user_invitation POST   /users/invitation(.:format)                  devise/invitations#create
new_user_invitation GET    /users/invitation/new(.:format)              devise/invitations#new
PUT    /users/invitation(.:format)                  devise/invitations#update

之后

devise_for :users , :skip => 'invitation'
devise_scope :user do
get "/users/invitation/accept", :to => "devise/invitations#edit",   :as => 'accept_user_invitation'
put "/users/invitation",        :to => "devise/invitations#update", :as => nil
end

耙道

accept_user_invitation GET    /users/invitation/accept(.:format)                 devise/invitations#edit
PUT    /users/invitation(.:format)                        devise/invitations#update

注1设计范围 https://github.com/plataformatec/devise#configuring-routes

注2我正在把它应用在 design _ invitable 上,但它可以与任何可设计的特性一起工作

重要提示: 看到 design _ scope 是在 使用者而不是 用户上吗?没错,小心这个!给你这个问题会带来很多痛苦:

Started GET "/users/invitation/accept?invitation_token=xxxxxxx" for 127.0.0.1
Processing by Devise::InvitationsController#edit as HTML
Parameters: {"invitation_token"=>"6Fy5CgFHtjWfjsCyr3hG"}
[Devise] Could not find devise mapping for path "/users/invitation/accept?  invitation_token=6Fy5CgFHtjWfjsCyr3hG".
This may happen for two reasons:


1) You forgot to wrap your route inside the scope block. For example:


devise_scope :user do
match "/some/route" => "some_devise_controller"
end


2) You are testing a Devise controller bypassing the router.
If so, you can explicitly tell Devise which mapping to use:


@request.env["devise.mapping"] = Devise.mappings[:user]

按路线来

devise_for :users, :controllers => {:registrations => "registrations"}, :skip => [:registrations]
as :user do
get 'users/edit' => 'devise/registrations#edit', :as => 'edit_user_registration'
put 'users' => 'devise/registrations#update', :as => 'user_registration'
end


devise_scope :user do
get "/sign_in",  :to => "devise/sessions#new"
get "/sign_up",  :to => "devise/registrations#new"
end

你会得到一个错误,现在当你来签署页面,修复它。 在 app/views/design/share/_ links.erb 中执行此更改

<% if  request.path != "/sign_in" %>
<%- if devise_mapping.registerable? && controller_name != 'registrations' %>
<%= link_to "Sign up", new_registration_path(resource_name) %><br />
<% end -%>
<% end %>

您可以通过将其置于“ design _ for”之前来覆盖“ design _ scope”。

devise_scope :user do
get "/users/sign_up",  :to => "sites#index"
end


devise_for :users

不知道这是否是最好的方式,但它是我的解决方案,因为它只是重定向回到页面中的签名。

我发现 另一个帖子和这个很相似,想分享一下@chrisnicola 给出的答案。在帖子中,他们试图只在生产过程中阻止用户注册。

您还可以修改注册控制器:

“ app/controller/registrations _ controller. rb”

class RegistrationsController < Devise::RegistrationsController
def new
flash[:info] = 'Registrations are not open.'
redirect_to root_path
end


def create
flash[:info] = 'Registrations are not open.'
redirect_to root_path
end
end

这将覆盖设计的控制器和使用上述方法代替。他们添加了闪光信息,以防有人不知怎么进入了注册页面。您还应该能够将重定向更改为您喜欢的任何路径。

你也可以在 “ config/routesrb”中添加以下内容:

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

让它像这样将允许您使用标准设计编辑您的配置文件。如果您希望仍然可以通过包括

  def update
end

“ app/controller/registrations _ controller. rb”

我也遇到过同样的问题,我发现将用户从注册页面重定向是一个有点糟糕的做法。所以我的解决方案基本上就是根本不使用 :registrable

我所做的是创建一个类似的页面,像编辑用户详细信息,看起来像:

<%= form_tag(update_user_update_path, method: :post) do %>  
<br>
<%= label_tag(:currPassword, 'Current password:') %> <%= password_field_tag(:currPassword) %> <br>
<%= label_tag(:newPassword, 'New password:') %> <%= password_field_tag(:newPassword) %> <br>
<%= label_tag(:newPasswordConfirm, 'Confirm new password:') %> <%= password_field_tag(:newPasswordConfirm) %> <br>
<%= submit_tag('Update') %>
<% end %>

因此,这个表单提交到一个新的 post 端点,用于更新密码,如下所示:

  def update
currPass = params['currPassword']
newPass1 = params['newPassword']
newPass2 = params['newPasswordConfirm']
currentUserParams = Hash.new()
currentUserParams[:current_password] = currPass
currentUserParams[:password] = newPass1
currentUserParams[:password_confirmation] = newPass2
@result = current_user.update_with_password(currentUserParams)
end

稍后,您可以在视图中使用 @result来告诉用户是否更新了密码。

这是一个古老的问题——但我最近解决了同样的问题,并想出了一个比下面这个更优雅的解决方案:

devise_for :users, :skip => [:registrations]
as :user do
get 'users/edit' => 'devise/registrations#edit', :as => 'edit_user_registration'
put 'users' => 'devise/registrations#update', :as => 'user_registration'
end

并且它给出了命名路由的默认名称(如 cancel_user_registration) ,而不会过于冗长。

devise_for :users, skip: [:registrations]


# Recreates the Devise registrations routes
# They act on a singular user (the signed in user)
# Add the actions you want in 'only:'
resource :users,
only: [:edit, :update, :destroy],
controller: 'devise/registrations',
as: :user_registration do
get 'cancel'
end

带有默认设计模块的 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)        devise/registrations#cancel
edit_user_registration GET    /users/edit(.:format)          devise/registrations#edit
user_registration PATCH  /users(.:format)               devise/registrations#update
PUT    /users(.:format)               devise/registrations#update
DELETE /users(.:format)               devise/registrations#destroy

对于其他人来说,我的情况。
devise (3.5.2)
我成功地删除了注册的路由,但保留了用于编辑配置文件的路由,代码如下。

#routes.rb
devise_for :users, skip: [:registrations]
as :user do
get 'users/edit' => 'devise/registrations#edit', :as => 'edit_user_registration'
put '/users(.:format)' => 'devise/registrations#update', as: 'user_registration'
patch '/users(.:format)' => 'devise/registrations#update'
end

改变路线会带来很多其他的问题。我找到的最简单的方法是这样做。

ApplicationController < ActionController::Base
before_action :dont_allow_user_self_registration


private


def dont_allow_user_self_registration
if ['devise/registrations','devise_invitable/registrations'].include?(params[:controller]) && ['new','create'].include?(params[:action])
redirect_to root_path
end
end
end

我发现这种方法在不干扰路由或添加应用程序控制器方法的情况下工作得很好。我的方法是推翻设计方法。把这个加到 app/controllers/devise/registrations_controller.rb 为了简洁起见,我省略了其他方法。

class Devise::RegistrationsController < DeviseController
...
# GET /resource/sign_up
def new
redirect_to root_path
end
....
end

为了消除其他视图仍然可以访问此路径的错觉,您可能还需要从 app/views/devise/shared/_links.erb中删除此代码

<%- if devise_mapping.registerable? && controller_name != 'registrations' %>
<%= link_to "Sign up", new_registration_path(resource_name) %><br />
<% end -%>

下面是我使用的略有不同的路线,它使你不必覆盖 devise/shared/_links.html.erb视图。

app/models/user.rb:

devise :database_authenticatable, :recoverable, :rememberable, :trackable, :validatable

config/routes.rb:

devise_for :users
devise_scope :user do
put 'users' => 'devise/registrations#update', as: 'user_registration'
get 'users/edit' => 'devise/registrations#edit', as: 'edit_user_registration'
delete 'users' => 'devise/registrations#destroy', as: 'registration'
end

以前:

$ rake routes | grep devise
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)                     devise/registrations#cancel
user_registration POST   /users(.:format)                            devise/registrations#create
new_user_registration GET    /users/sign_up(.:format)                    devise/registrations#new
edit_user_registration GET    /users/edit(.:format)                       devise/registrations#edit
PATCH  /users(.:format)                            devise/registrations#update
PUT    /users(.:format)                            devise/registrations#update
DELETE /users(.:format)                            devise/registrations#destroy

之后:

$ rake routes | grep devise
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
user_registration PUT    /users(.:format)                            devise/registrations#update
edit_user_registration GET    /users/edit(.:format)                       devise/registrations#edit
registration DELETE /users(.:format)                            devise/registrations#destroy

我喜欢@max 的 回答,但是当我试图使用它时,由于 devise_mapping为零,我遇到了一个错误。

我稍微修改了他的解决方案,使之看起来能够解决这个问题。它需要在 devise_scope中包装对 resource的调用。

devise_for :users, skip: [:registrations]


devise_scope :user do
resource :users,
only: [:edit, :update, :destroy],
controller: 'devise/registrations',
as: :user_registration do
get 'cancel'
end
end

请注意,devise_scope期望单数 :user,而 resource期望复数 :users

我使用了下面的方法,而不是寻找一个困难的解决方案。

  1. 从页面(路径策划/注册/new.html. erb)中删除 sign _ up 表单,并将其替换为自定义信息。

  2. 将传入流量重定向到其他页面,如下面的 routes.rb

    get "/users/sign_up", to: redirect('/')


post "/users/sign_up", to: redirect('/')

一定要在 devise_for :users之前写