Techioz Blog

セッションコントローラーに何らかの問題がある

概要

セッションコントローラー.rb

class SessionsController < ApplicationController

    def new
        @user = User.new
    end

    def create
        @user = User.find_by(email: user_params[:email])
        if @user && @user.password == user_params[:password]
            cookies[:user_id] = @user.id
            redirect_to blogs_path
        else
            flash.now[:notice] = "invalid email or password"
            render :new
        end
    end

    private
        def user_params
            params.require(:user).permit(:email,:password)
        end
end

新しい.html.erb

<p id="notice"><%= notice %></p>
<h1> Sign in  </h1>

<%= form_with(url: sessions_path, method: :post) do |form| %>
  <div>
    <%= form.label :email %>
    <%= form.text_field :email %>
  </div>

  <div>
    <%= form.label :password %>
    <%= form.password_field :password %>
  </div>

  <%= form.submit "Submit" %>
<% end %>

私は Rails を使用しており、フォームの送信を処理する作成アクションを備えた SessionsController を作成しました。ただし、フォームが正しく処理されていないようで、その理由がわかりません。これで送信をクリックすると、以前の方法でフォームがレンダリングされるだけです

誰かがこの問題のトラブルシューティングを手伝ってくれ、修正方法についてのガイダンスを提供してもらえますか?フォームの送信が適切に機能するよう支援していただければ幸いです。

解決策

# add user model v
form_with(model: @user, url: sessions_path, method: :post)

この方法で生成される入力名の属性は、user[email] と user[password] になります。 params.require(:user) を必要としているため、params にはユーザー キーが必要です: {user: {email: “myemail”, password: “123”}}。

また、Turbo を使用している場合にエラー応答を表示するには、これが必要になります (Rails 7 ではデフォルトで使用されています)。

render :new, status: :unprocessable_entity

アップデート

フォームを作成するときに最も重要な部分は、フォーム ビルダーによってどのような名前属性が生成されるかです。

<%= form_with url: "/sign_in", method: :post do |f| %>
  <%= f.text_field :email %>
  <%#=> <input type="text" name="email"> %>
<% end %> #                      ^^^^^

<%= form_with model: @user, url: "/sign_in", method: :post do |f| %>
  <%= f.text_field :email %>
  <%#=> <input type="text" name="user[email]"> %>
<% end %> #                      ^^^^^^^^^^^

form_with がどのように機能するかを知っておく必要があるだけです。 https://translate.google.com/translate?hl=ja&sl=en&tl=ja&u=https://api.rubyonrails.org/classes/ActionView/Helpers/FormHelper.html#method-i-form_with

フォームを送信すると、SessionsController#create に移動します。送信されたフォーム パラメーターは Rails によって解析され、params ヘルパーで利用できます。URL エンコードされたパラメーターの場合、次のようになります。

#                                   name=value
>> Rack::Utils.parse_nested_query("email=asdf")
=> {"email"=>"asdf"}
>> Rack::Utils.parse_nested_query("user[email]=asdf")
=> {"user"=>{"email"=>"asdf"}}

デフォルトでは、params は ActionController::Parameters オブジェクトを返します。ユーザーモデルにパラメーターを与えるためには、パラメーターを許可する必要があります。これは許可されません: User.create(params) は、email=myemail&superadmin=true を送信できる可能性があり、現在は私が担当しているためです。

コントローラーでは、最初に次の呼び出しが行われます。 user_params[:email] => params.require(:user).permit(:email,:password)

>> parameters = Rack::Utils.parse_nested_query("email=myemail")
>> params     = ActionController::Parameters.new(parameters)
#  ^ this is what you have
#  v this is what happens (you have to look at server logs)
>> params.require(:user)
/home/alex/.rbenv/versions/3.2.2/lib/ruby/gems/3.2.0/gems/actionpack-7.0.4.3/lib/action_controller/metal/strong_parameters.rb:500:in `require':
param is missing or the value is empty: user (ActionController::ParameterMissing)

モデルを追加する場合: @user:

>> parameters = Rack::Utils.parse_nested_query("user%5Bemail%5D=myemail")
>> params     = ActionController::Parameters.new(parameters)
>> params.require(:user)
=> #<ActionController::Parameters {"email"=>"myemail"} permitted: false>
>> params.require(:user).permit(:email)
=> #<ActionController::Parameters {"email"=>"myemail"} permitted: true>
#                                                                 ^
# everything else should work from this point

User.find(params[:id]) のように、個々の属性を取得するときは、params を許可する必要がないことに注意してください。

これをどうやって判断したのでしょうか?フォームを見てください。モデルがありません: @user は、上記の ^ をすべて意味します。それはよくある問題です。ただし、ログを確認するだけで、パラメータやブラウザに表示されないエラーを確認できます。