web-dev-qa-db-ja.com

サインアップするために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

ご了承ください:

  • Userモデルにはまだ:registerableがあります
  • devise/registrationsはメールとパスワードの更新を処理します
  • 他のユーザー属性(パーミッションなど)の更新は、別のコントローラーによって処理されます

実際の答え:

デフォルトのDeviseパスのルートを削除します。すなわち:

devise_for :users, path_names: {
  sign_up: ''
}
144
Nathan Long

私もこれをやろうとしましたが、 devise google groupのスレッド は本当にきれいな解決策を探すことを思いとどまらせました。

JoséValim(Deviseメンテナー)を引用します。

簡単なオプションはありません。パッチを提供するか、:skip =>:registerableを使用して、必要なルートのみを追加できます。

元の質問は:

Railsから特定のルート(削除ルート)を削除する良い方法はありますか?

52
Benoit Garret

あなたのモデルでこれを行うことができます

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

次のように変更します。

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

シンボル:registerableが削除されたことに注意してください

それだけです、他に何も必要ありません。登録ページへのすべてのルートとリンクも魔法のように削除されます。

88
stephenmurdoch

devise_invitable パスのcreateおよびnewを削除しようとする同様の問題がありました:

前:

 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

注2devise_invitableに適用していますが、任意のdevise * able機能で動作します

重要な注意:devise_scopeがonuserではなくusers?それは正しいです、これに注意してください!この問題を引き起こす多くの痛みを引き起こす可能性があります:

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]
30
equivalent8

別の投稿 がこれに似ており、@ chrisnicolaが出した回答を共有したいと思いました。投稿では、本番中にユーザーのサインアップのみをブロックしようとしていました。

登録コントローラーを変更することもできます。次のようなものを使用できます。

In "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

これにより、deviseのコントローラーがオーバーライドされ、代わりに上記のメソッドが使用されます。誰かが何らかの理由でsign_upページにたどり着いた場合に備えて、フラッシュメッセージを追加しました。また、任意のパスへのリダイレクトを変更できる必要があります。

また "config/routes.rb"でこれを追加できます:

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

このようにすると、標準のデバイスを使用してプロファイルを編集できます。必要に応じて、プロファイル編集オプションを上書きすることもできます。

  def update
  end

"app/controllers/registrations_controller.rb"

20
Daniel

「devise_for」の前に配置することで、「devise_scope」をオーバーライドできます。

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

devise_for :users

これが最善の方法であるかどうかはわかりませんが、サインインページにリダイレクトするだけなので、現在の私のソリューションです。

12
Midnight

これは古い質問ですが、最近同じ問題を解決し、次の方法よりもはるかにエレガントなソリューションを思い付きました。

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デフォルトのdeviseモジュールでの出力:

                  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
11
max

Routes.rbでこれを行う

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/devise/shared/_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 %>
4
Syed

@maxの answer が気に入りましたが、使用しようとするとdevise_mappingがnilであるためエラーになりました。

私は彼の解決策を問題に対処しているように少し修正しました。 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が必要です。

4
dvanoni

これは、ルートをいじったり、アプリケーションコントローラーメソッドを追加したりしなくてもうまく機能することがわかりました。私のアプローチは、deviseメソッドをオーバーライドすることです。これを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 -%>
3
lacostenycoder

私の場合、他の人のために。
with 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
2
Micka

ここに私が行ったわずかに異なるルートがあります。これにより、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
1
bmaddy

ルートを変更すると、それに伴う他の問題が山ほどあります。私が見つけた最も簡単な方法は、以下を実行することです。

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
0
Weston Ganger

私は同じ問題を抱えていたので、登録ページからユーザーをリダイレクトすることは少し悪い習慣であることがわかりました。したがって、私の解決策は基本的に: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 %>

したがって、このフォームは、次のようなパスワードを更新する新しいポストエンドポイントに送信します。

  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を使用して、パスワードが更新されたかどうかをユーザーに伝えることができます。

0
Sarp Kaya