0
0

More than 3 years have passed since last update.

Rails hidden_field について調べる(確認画面を作成して挙動確認)

Posted at

こちらもなんとなくで意味を理解している、具体的な使い方のイメージができていない
の理由からしらべて記事を書くことにしました

「hidden_field」とは

form_forやform_withの中で使用する
目に見えない値を送るイメージ

どうやら、「hidden_field_tag」ヘルパーもあるみたいだが
これらの違いはまた別の日に記事にする

とりあえず、手を動かして使ってみる、準備編

ユーザーが投稿する画面を作って
投稿するまえに投稿の内容の確認画面を作成してみる

UserとPostのそれぞれのコントローラーとモデルを
作成してみる

~/environment/rails/sample_app
❯ rails g controller users 

~/environment/rails/sample_app
❯ rails g model User

~/environment/rails/sample_app
❯ rails g controller posts index new create

~/environment/rails/sample_app
❯ rails g model Post

~/environment/rails/sample_app
❯ rails db:migrate

アソシエーション

app/model/user.rb
class User < ApplicationRecord
  has_many :posts
end
app/model/post.rb
class User < ApplicationRecord
  has_many :user
end

初期データを入れる

以前、自分が書いた記事をみつつ
UserとPostの初期データを入れる
以前書いた初期データを入れる記事

db/seeds.rb
test_user = User.create!(
  name: 'test',
  email: 'test@mail.com',
  password: 'password'
)

Post.create!(
  title: 'test title',
  contents: '投稿のテストです',
  user_id: test_user.id
)

Post.create!(
  title: 'test title2',
  contents: '投稿のテスト、2回めです',
  user_id: test_user.id
)

下記のコマンドで実行

rails db:seed

一覧画面を作成

コントローラーの記載
何度もユーザーの取得を宣言するのは、面倒なので
privateメソッドで記述しておく

app/controller/posts_controller.rb
class PostsController < ApplicationController
  before_action :set_user

  def index
    @posts = Post.where(user_id: @user.id)
  end

  private

  def set_user
    @user = User.find(1)
  end
end

viewの作成

app/views/posts/index.html.erb
<h1>投稿一覧画面</h1>

<% @posts.each do |post| %>
  <p><%= post.title %></p>
  <p><%= post.contents %></p>
<% end %>

ルーティング定義

config/routes.rb
Rails.application.routes.draw do
  get 'posts/index'
end

投稿作成画面を作成

こちらもコントローラーの記載から

app/controller/posts_controller.rb
class PostsController < ApplicationController
  before_action :set_user

  def index
    @posts = Post.where(user_id: @user.id)
  end

  def new
    @posts = Post.new
  end

  def create
    @posts = Post.create(
      title: params[:post][:title],
      contents: params[:post][:contents],
      user_id: @user.id
    )

    if @posts.save
      redirect_to posts_index_path
    else
      render :new
    end
  end

  private

  def set_user
    @user = User.find(1)
  end
end

params[:title]」として取得しようとしてつまずいた
パラメータの確認
params[:モデル名][:渡したname属性]で取得する

viewの作成

app/views/posts/new.html.erb
<h1>投稿新規作成画面</h1>

<%= form_with(model: @posts, url: posts_create_path, local: true) do |f| %>
  <div id="container">
    <%= f.text_field :title %>
    <%= f.text_area :contents %>

    <%= f.submit %>
  </div>
<% end %>

ルーティング定義

config/routes.rb
Rails.application.routes.draw do
  get 'posts/index'
  # 追加
  get 'posts/new'
  post 'posts/create'
end

これでまずは普通のユーザーが投稿して
一覧画面までできた

いよいよ確認画面を作成する

Postコントローラーに確認画面用の「confirmアクション」を追加する

app/controller/posts_controller.rb
class PostsController < ApplicationController
  before_action :set_user
  # 追加
  before_action :posts_params

  def index
    @posts = Post.where(user_id: @user.id)
  end

  def new
    @posts = Post.new
  end

  # 確認画面用のアクション 追加
  def confirm
    @posts = Post.new(
      title: params[:post][:title],
      contents: params[:post][:contents]
    )

    # エラーが発生した場合true、エラーが無い場合falseを返す
    if @posts.valid?
      render :confirm
    else
      render :new
    end
  end

  # 削除
  def create
    @posts = Post.create(
      title: params[:post][:title],
      contents: params[:post][:contents],
      user_id: @user.id
    )

    if @posts.save
      redirect_to posts_index_path
    else
      render :new
    end
  end

  private

  def set_user
    @user = User.find(1)
  end

  # ストロングパラメーター追加
  def posts_params
    params.require(:post).permit(:title, :contents)
  end
end

「valid?」「invalid?」メソッド

こちらにも違いがあるみたい

valid?
バリデーションが実行された結果
エラーが無い場合trueを返し,エラーが発生した場合falseを返す

invalid?」はその逆

ルーティングの定義から

config/routes.rb
Rails.application.routes.draw do
  get 'posts/index'
  get 'posts/new'
  # 削除
  post 'posts/create'
  # 追加
  post 'posts/confirm'
end

view作成

~/environment/rails/sample_app
❯ touch app/views/posts/confirm.html.erb

viewを修正していく
でも、まずは確認画面へ行くかテストしたいので

app/views/posts/confirm.html.erb
  <h1>成功</h1>

だけ記入
フォームを送信した際に、URLが
localhost:3000/posts/confirmになっていて
画面に「成功」の画面がでていればOK

さらに細かく実装していく

アクションを追加する

app/controller/posts_controller.rb
class PostsController < ApplicationController
  # ~割愛~

  # 確認画面用のアクション
  def confirm
    @posts = Post.new(
      title: params[:post][:title],
      contents: params[:post][:contents]
    )

    # エラーが発生した場合true、エラーが無い場合falseを返す
    # 後置ifで記述
    render :confirm if @posts.valid?
  end


  # ~割愛~
end

viewを作成していく

app/views/posts/confirm.html.erb
<h1>確認画面</h1>

<%= form_with(model: @posts, url: posts_complete_path, local: true) do |f| %>
  <div id="container">
    # ここで登場、「hidden_field」
    <%= f.hidden_field :title %>
    <%= @posts.title%>

    <%= f.hidden_field :contents %>
    <%= @posts.contents%>

    # パラメーターに対して名前をつけることができる、name属性
    <%= f.submit '戻る', name: 'back' %>
    <%= f.submit '送信する' %>
  </div>
<% end %>

フォームの送信先に少し手こずる
・form_withは、デフォルトで「POST」で送信する
・コントローラーでcreateを使用してオブジェクトを作成するとnewとsaveを
行ってくれる
→そのため、フォームが「PATCH」で送信される
→「PATCH」はすでにオブジェクトがある場合に送信される

完了画面用のアクションを追加する

app/controller/posts_controller.rb
class PostsController < ApplicationController
  # ~割愛~

  # 確認画面用のアクション
  def confirm
    @posts = Post.new(
      title: params[:post][:title],
      contents: params[:post][:contents]
    )

    # エラーが発生した場合true、エラーが無い場合falseを返す
    # 後置ifで記述
    render :confirm if @posts.valid?
  end

  # 完了画面用のアクション
  def complete
    @posts = Post.new(
      title: params[:post][:title],
      contents: params[:post][:contents],
      user_id: @user.id
    )

    # パラメーターに[:back]がついている(戻るボタン)をクリック
    # もしくは、オブジェクトが保存されなかったら「new」の画面を戻す
    render :new if params[:back] || !@posts.save
  end

  # ~割愛~
end

これで、投稿→確認→完了の画面遷移までができる
投稿の簡易アプリが完成

戻るボタンを押した際に使用される「hidden_field」

作成したview

app/views/posts/confirm.html.erb
<h1>確認画面</h1>

<%= form_with(model: @posts, url: posts_complete_path, local: true) do |f| %>
  <div id="container">
    # ここで登場、「hidden_field」
    <%= f.hidden_field :title %>
    <%= @posts.title%>

作成されているHTML

<input type="text" name="post[title]" id="post_title">

内容を入力して、戻るボタンを押す
<input type="text" value="テスト タイトル" name="post[title]" id="post_title">

value」の中に入力した値がはいっている
ユーザが直接フォームから入力させないまま、値を受け渡したい時に使用する

参考記事

https://railsguides.jp/action_view_overview.html
https://railsdoc.com/page/hidden_field
https://qiita.com/___xxx_/items/7c9b194230c7ce2b02ca
https://remonote.jp/rails-confirm-form
https://web-begginer-log.com/rails-confirm/

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