0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

rails_tutorial chapter7 part2 <忘備録>

Posted at

form_withは重要なパートですね。

まず下処理として、以下の記述

users_controller.rb



def new
@user = User.new
end

view側で以下を記述

app/views/users/new.html.erb
<h1>Sign up</h1>

<div class="row">
  <div class="col-md-6 col-md-offset-3">
    <%= form_with(model: @user, local: true) do |f| %>
      <%= f.label :name %>
      <%= f.text_field :name %>

      <%= f.label :email %>
      <%= f.email_field :email %>

      <%= f.label :password %>
      <%= f.password_field :password %>

      <%= f.label :password_confirmation, "Confirmation" %>
      <%= f.password_field :password_confirmation %>

      <%= f.submit "Create my account", class: "btn btn-primary" %>
    <% end %>
  </div>
</div>

これらを分解して理解していくと、
まず以下の部分ですが、
form_withはデフォルトで“remote” XHR requestを送るため、local: trueと設定することで同期通信とする。

以前、非同期通信の実装でデフォルトがremoteとなっていることを知らず、つまづいたので忘れないようメモ。

<%= form_with(model: @user, local: true) do |f| %>
  .
  .
  .
<% end %>

そして、f.formなどありますが、これらをhtmlでみてみると以下の通りです。

<form accept-charset="UTF-8" action="/users" class="new_user"
      id="new_user" method="post">
  <input name="authenticity_token" type="hidden"
         value="NNb6+J/j46LcrgYUC60wQ2titMuJQ5lLqyAbnbAUkdo=" />
  <label for="user_name">Name</label>
  <input id="user_name" name="user[name]" type="text" />

  <label for="user_email">Email</label>
  <input id="user_email" name="user[email]" type="email" />

  <label for="user_password">Password</label>
  <input id="user_password" name="user[password]"
         type="password" />

  <label for="user_password_confirmation">Confirmation</label>
  <input id="user_password_confirmation"
         name="user[password_confirmation]" type="password" />

  <input class="btn btn-primary" name="commit" type="submit"
         value="Create my account" />
</form>

例えば、以下のコードは

<%= f.label :name %>
<%= f.text_field :name %>

<%= f.label :email %>
<%= f.email_field :email %>

<%= f.label :password %>
<%= f.password_field :password %>
<label for="user_name">Name</label>
<input id="user_name" name="user[name]" type="text" />

<label for="user_email">Email</label>
<input id="user_email" name="user[email]" type="email" />

<label for="user_password">Password</label>
<input id="user_password" name="user[password]" type="password" />

例えば、この中の"user[email]"という値は、userハッシュの:emailキーの値(params[:email])と一致します。

@user = User.new(params[:user])
実際にはこのようなコードとほぼ同じである、ということです。

@user = User.new(name: "Foo Bar", email: "foo@invalid",
                 password: "foo", password_confirmation: "bar")

また、このような記述がありました。

次に重要な要素は、formタグ自身です。Railsはformタグを作成するときに@userオブジェクトを使います。すべてのRubyオブジェクトは自分のクラスを知っている(4.4.1)ので、Railsは@userのクラスがUserであることを認識します。また、@userは新しいユーザーなので、 Railsはpostメソッドを使ってフォームを構築すべきだと判断します。

要は、railsが自分のクラスや@userの中身を踏まえて、メソッドを決定してくれるとのことです。賢いですね。

つまり、@userがnewアクションでは空なので、updateアクションを実行してくれます。賢いですね。(2回目)

したがって、htmlの記述は以下の通りです。
action="/users"とポストメソッドでnewアクションが実行されるというわけですね。

<form action="/users" class="new_user" id="new_user" method="post">

そして、POSTリクエストはcreateアクションに送られます。ここで、createアクションでフォーム送信を受け取り、User.newを使って新しいユーザーオブジェクトを作成し、ユーザーを保存(または保存に失敗)します。

なので、newアクションとupdateアクションはセットで必要となります。

これで問題なさそうですが、実は問題があります。
それは以下の書き方にはセキュリティ上の問題があります。

@user = User.new(params[:id])

回避するためには、ストロングパラメーターが必要です。

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

flhashの表示

以下の説明が分かりやすい。

  def create
    @user = User.new(user_params)
    if @user.save
      flash[:success] = "Welcome to the Sample App!"
      redirect_to @user
    else
      render 'new'
    end
  end
application.html.erb
   <% flash.each do |message_type, message| %>
     <div class="alert alert-<%= message_type %>"><%= message %></div>
   <% end %>

適用するCSSクラスをメッセージの種類によって変更するようにしています。これにより、例えば:successキーのメッセージが表示される場合、適用されるCSSクラスは次のようになります。

alert-<%= message_type %>
alert-success

このとき、:successキーはシンボルでしたが、テンプレート内に反映させる際に埋め込みRubyが自動的に"success"という文字列に変換している点に注意してください。この性質を利用することで、キーの内容によって異なったCSSクラスを適用させることができ、メッセージの種類によってスタイルを動的に変更させることができます。例えば、8.1.4ではflash[:danger]を使ってログインに失敗したことを表すメッセージを表示します11 (実際、既にalert-dangerというCSSクラスを使って、リスト 7.21のエラーメッセージのスタイルをdivタグで指定しています)。Bootstrap CSSは、このようなflashのクラス用に4つのスタイルを持っています(success、info、warning、danger)。また、本書のサンプルアプリケーションでは、これらの全てのスタイルを場合に応じて使っていきます(例えば11.2ではinfoを、8.1.4ではdangerを使います)。

テンプレート内にflashのメッセージが差し込まれるので、次のようなコードは、

flash[:success] = "Welcome to the Sample App!"

最終的には次のようなHTMLになります。

<div class="alert alert-success">Welcome to the Sample App!</div>

第7章は、以下の2点を理解できたら大丈夫かなと思います。
・form_withを使って、newアクション、createアクションを実装する
・flashの使い方

gravatorも出てきましたが、ある程度知っていればよさそう。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?