質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
Devise

Deviseとは、Ruby-on-Railsの認証機能を追加するプラグインです。

Ruby

Rubyはプログラミング言語のひとつで、オープンソース、オブジェクト指向のプログラミング開発に対応しています。

Ruby on Rails

Ruby on Railsは、オープンソースのWebアプリケーションフレームワークです。「同じことを繰り返さない」というRailsの基本理念のもと、他のフレームワークより少ないコードで簡単に開発できるよう設計されています。

Q&A

1回答

3383閲覧

devise gemでログインとサインアップに同一のフォームを作りたい

Taka624

総合スコア40

Devise

Deviseとは、Ruby-on-Railsの認証機能を追加するプラグインです。

Ruby

Rubyはプログラミング言語のひとつで、オープンソース、オブジェクト指向のプログラミング開発に対応しています。

Ruby on Rails

Ruby on Railsは、オープンソースのWebアプリケーションフレームワークです。「同じことを繰り返さない」というRailsの基本理念のもと、他のフレームワークより少ないコードで簡単に開発できるよう設計されています。

0グッド

0クリップ

投稿2016/04/19 11:33

ユーザ管理にdeviseを使用しています。
現在、ログインのためのフォームと、サインアップのためのフォームは別々のものになっています。
しかし、UX向上のため、同じ単一のフォームでログイン/サインアップどちらともできるようにしたいのですが、やり方がわかりません。

現在フォームのリクエスト先は、ログインフォームが

<%= form_for(:user, :url => session_path(:user)) do |f| %> <%= f.text_field :email, placeholder: "メールアドレスを入力" %> <%= f.password_field :password, placeholder: "パスワードを入力" %> <%= f.submit 'ログイン' %> <% end %>

で、サインアップフォームが

<%= form_for(resource, as: resource_name, url: registration_path(resource_name)) do |f| %> <%= devise_error_messages! %> <%= f.email_field :email, placeholder: "メールアドレスを入力" %> <%= f.password_field :password, placeholder: "パスワードを入力(4文字以上)" %> <%= f.submit "サインアップ" %> <% end %>

になっています。
これを、同一のフォームで両方の処理が可能にする方法はありますでしょうか。

どうぞよろしくお願いします。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

想定は同じ画面に二つのフォームがある状況でしょうか。それとも,同じフォームファイルを共有して,それぞれのフォームを表示する方法を知りたいのでしょうか。前者は二つのフォームを同じフォームにまとめるだけで実現可能です。後者はフォームのコードをまとめると返って煩わしくなると思いますし可読性の面からお勧めしません。非表示のフォームにhidden属性を付けて,link clickなどでhiddenとshowの切替という方法などはできると思います。
自由度がそこそこある実装なので,これらの情報で解決方法が見えなけれ実装の方針をもう少し詳しく教えていただければと思います。

追記

返信していただいた内容の実装であればdeviseのRegistrationsControllerのcreateアクションをカスタマイズすればできると思います。

簡単にはsuperの前にfindメソッドでUserの存在判定を行い,存在すればsign_inメソッドを実行して,リダイレクトし,存在しなければsuperメソッド(継承元クラスの同じ名前のメソッドを呼び出す)を呼ぶだけで実装できると思います。

投稿2016/04/19 12:33

編集2016/04/19 13:15
退会済みユーザー

退会済みユーザー

総合スコア0

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

Taka624

2016/04/19 12:50 編集

ありがとうございます。 理想としては、 もし入力されたメールアドレスとパスワードがすでに存在するものであればログインとしてフォーム送信をし、存在しなければサインアップとしてフォーム送信をしたいと考えております。
退会済みユーザー

退会済みユーザー

2016/04/19 13:07

なるほどですね。 そういった実装を試したことがないのでコードを提示はできませんがdeviseのregistrationコントローラーのcreateアクションをオーバーライドして,paramsのユーザが存在したらsign_in,しなかったらuser createを継続するという方針で実装できる気がします。情報を追記しておきます。
Taka624

2016/04/20 06:07

追記ありがとうございます。 いろいろトライしているのですが、 「findメソッドでUserの存在判定を行い」 という部分ができておりません。どのように書くことができそうでしょうか。 たとえば、 def create @user = User.find(email: params[:email]) if @user.present? sign_in(resource_name, resource) else super end end フォームから送られてくるパラメータをどのようにどのように表現できて、どのように既存のレコードと照らし合わせるのか、理解ができておりません。 もしできましたら具体的な例を提示していただけると助かりますが、どういったことをまず学習すべきなどといったアドバイスもいただけたら嬉しいです。お忙しいようでしたら簡単なヒントだけでもお願いします。
退会済みユーザー

退会済みユーザー

2016/04/20 12:50 編集

ほぼその方針で、おっけーです。 何が送られて来てるかわからない場合はbinding.pryで中身がどうなってるのかみると良いでしょう。 githubでdeviseの該当のコントローラーの処理を見るといいでしょう。 ただsuperメソッドにはparamsを引数に入れたほうがいいかもしれません。
Taka624

2016/04/21 11:40

今createメソッドが、 def create if User.where(email: params[:email]).present? binding.pry sign_in(resource_name, resource) else 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 respond_with resource end end こういう状態になっているのですが、 存在するemailでフォーム送信しても binding.pryで止まらず、 結局新規登録画面に戻ってしまい、 ログを見ると、 Processing by Users::RegistrationsController#create as HTML Parameters: {"authenticity_token"=>"WyRbexD6rKYPPcpDpQQu5y3XYhzo7h6mDTZIVs4BxZltFtXggmiSc0huvgVG70PH5UIdEnq+KXYjbuXOj2gVZg==", "user"=>{"email"=>"c@gmail.com", "password"=>"[FILTERED]"}, "commit"=>"\xE3\x81\xAF\xE3\x81\x98\xE3\x82\x81\xE3\x82\x8B"} User Load (0.4ms) SELECT `users`.* FROM `users` WHERE `users`.`email` IS NULL (0.9ms) BEGIN User Exists (2.9ms) SELECT 1 AS one FROM `users` WHERE `users`.`email` = BINARY 'c@gmail.com' LIMIT 1 (0.2ms) ROLLBACK こうなっていて、すでに存在するためcreateはできないという感じの処理になってしまいます。登録画面に戻ってきます。 superをあえて使わずに、createメソッドまるごとコピーしているのは、今後の実装でもこの部分をカスタマイズしようと思っているからです。 いろいろ試しているのですが、例えば上記のコードですとどこに問題がありそうか、ご指摘お願いできませんでしょうか。
退会済みユーザー

退会済みユーザー

2016/04/21 12:39 編集

わかりました。 params[:user][:email]でアドレスを呼んでください。
Taka624

2016/04/22 02:43

ありがとうございます。 以下のように書き換えて実行してみたところ、 if User.where(params[:user][:email]).present? 以下のエラーが出ました。 Mysql2::Error: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '@gmail.com)' at line 1: SELECT `users`.* FROM `users` WHERE (c@gmail.com) のように出ました。使用しているmysqlのバージョンは5.6.27なのですが、 このバージョンでは if User.where(params[:user][:email]).present? こちらの書き方が使えない文法でしたでしょうか?
退会済みユーザー

退会済みユーザー

2016/04/22 11:20

email:が抜けてます。 それでも動かなければidでfindでしてください。
Taka624

2016/04/22 12:44

それで行けました!!!!! 本当に有難うございます! それによって、ユーザが存在する場合の分岐の方に進むことができました! しかし、ここで、 NoMethodError in Users::RegistrationsController#create undefined method `to_key' for :user:Symbol def create if User.where(email: params[:user][:email]).present? sign_in(resource_name, resource) else build_resource(sign_up_params) こういうエラーがでてしまいます。一体何のエラーなのでしょうか。 sign_in(resource_name, resource) の行がハイライトされているので、この部分がおかしいのかもしれません。 引数の渡し方はこれだとおかしいでしょうか? フォームは <%= form_for(resource, as: resource_name, url: registration_path(resource_name)) do |f| %> こうなっています。 sign_in(resource_name, resource) こちらの部分は、deviseのソースコード(https://github.com/plataformatec/devise/blob/master/app/controllers/devise/registrations_controller.rb)の106行目を参考にしているのですがうまく行かず、 代わりに56行目部分の sign_in resource_name, resource, bypass: true これを使ってみたのですが、この行にて同じエラーが出ました。 原因がわかりませんでしょうか。 何度も何度も本当に有難うございます。
退会済みユーザー

退会済みユーザー

2016/04/22 13:34

あーなるほど:userがないときはそれ以下のキーも参照できないのでparams.key? :userをいれてください。
Taka624

2016/04/22 16:21 編集

ありがとうございます! すみません、 params.key? をどこに入れたらよいのでしょうか? 今止まっているのは、ユーザが存在する場合の、(サインアップでなく)ログインをする処理で止まっていると思います。すでにサインアップを過去にしてある存在するユーザのemailとパスワードでフォーム送信している状況です。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

まだベストアンサーが選ばれていません

会員登録して回答してみよう

アカウントをお持ちの方は

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問