如何删除设计注册的设计路线?

Nat*_*ong 145 routing devise ruby-on-rails-3

我在Rails 3应用程序中使用Devise,但在这种情况下,用户必须由现有用户创建,该用户确定他/她将拥有哪些权限.

因此,我想要:

  • 删除路线的用户注册.
  • 为了还允许用户编辑自己的个人资料(变更电子邮件地址和密码),双方已经签署了

我怎样才能做到这一点?

目前,我通过以下方式有效地删除了这条路线devise_for :users:

match 'users/sign_up' => redirect('/404.html')
Run Code Online (Sandbox Code Playgroud)

这有效,但我想有更好的方法,对吧?

更新

正如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
Run Code Online (Sandbox Code Playgroud)

注意:

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

实际答案:

删除默认Devise路径的路由; 即:

devise_for :users, path_names: {
  sign_up: ''
}
Run Code Online (Sandbox Code Playgroud)

ste*_*och 89

你可以在你的模型中做到这一点

# typical devise setup in User.rb
devise :database_authenticatable, :registerable, :recoverable, :rememberable, :trackable, :validatable
Run Code Online (Sandbox Code Playgroud)

将其更改为:

devise :database_authenticatable, :recoverable, :rememberable, :trackable, :validatable
Run Code Online (Sandbox Code Playgroud)

请注意该符号:registerable已被删除

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

  • 使用管理部分(为允许编辑任意记录而构建)为用户提供编辑自己的配置文件的方法是我在很长一段时间内听到的最糟糕的想法.请没人这样做 (28认同)
  • 不幸的是,这也删除了我需要的`edit_user_registration`的路由.正如我所说,"他们仍然可以编辑他们的个人资料." (21认同)

Ben*_*ret 54

我试图做到这一点,但设计谷歌小组的一个线程阻止我寻找一个非常干净的解决方案.

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

没有直接的选择.您可以提供补丁或使用:skip =>:registerable并仅添加所需的路由.

最初的问题是:

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

  • 非常正确.事实上,我提出了一个补丁,他礼貌地拒绝了:"今天,你可以跳过整个控制器.它在使用方面不是最优的,但是手动设置整个控制器的路线是相当直接的.我相信排除路线按名称只会使路由生成代码更复杂(比现在更复杂),因为我们将无法使用Rails助手(如资源,资源和朋友)".https://github.com/plataformatec/devise/issues/1246#issuecomment-1736879 (4认同)
  • 我不知道这个答案最初写的时候是否是这种情况,但José引用的代码是错误的.在Devise 3.4.1中,它是`:skip =>:registrations`不是`:skip =>:registerable`. (2认同)

equ*_*nt8 30

我有类似的问题试图删除createnew的devise_invitable路径:

之前:

 devise_for :users
Run Code Online (Sandbox Code Playgroud)

耙路线

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
Run Code Online (Sandbox Code Playgroud)

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
Run Code Online (Sandbox Code Playgroud)

耙路线

accept_user_invitation GET    /users/invitation/accept(.:format)                 devise/invitations#edit
                       PUT    /users/invitation(.:format)                        devise/invitations#update
Run Code Online (Sandbox Code Playgroud)

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

注意2我在devise_invitable上应用它,但它适用于任何设计*功能

重要提示:看看devise_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]
Run Code Online (Sandbox Code Playgroud)


Dan*_*iel 20

我找到了另一篇与此类似的帖子,想分享@chrisnicola给出的答案.在帖子中,他们试图仅在生产期间阻止用户注册.

您还可以修改注册控制器.你可以使用这样的东西:

"app/controllers/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
Run Code Online (Sandbox Code Playgroud)

这将覆盖设备的控制器并使用上述方法.他们添加了flash消息,因为某人以某种方式进入了sign_up页面.您还应该能够将重定向更改为您喜欢的任何路径.

也可以在"config/routes.rb"中添加:

devise_for :users, :controllers => { :registrations => "registrations" }
Run Code Online (Sandbox Code Playgroud)

像这样离开将允许您使用标准设计编辑您的个人资料.如果您愿意,您仍然可以通过包含覆盖编辑配置文件选项

  def update
  end
Run Code Online (Sandbox Code Playgroud)

"app/controllers/registrations_controller.rb"中


小智 12

您可以通过将"devise_scope"放在"devise_for"之前来覆盖它.

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

devise_for :users
Run Code Online (Sandbox Code Playgroud)

不确定这是否是最佳方式,但目前是我的解决方案,因为它只是重定向回到登录页面.


max*_*max 11

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

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
Run Code Online (Sandbox Code Playgroud)

并且它给出了命名路由的默认名称(例如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
Run Code Online (Sandbox Code Playgroud)

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
Run Code Online (Sandbox Code Playgroud)


dva*_*oni 5

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

我将他的解决方案稍微修改为似乎解决了该问题的解决方案。它需要将调用包装到resourceinside devise_scope

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
Run Code Online (Sandbox Code Playgroud)

请注意,devise_scope期望单数:userresource期望复数:users