はじめに
本記事はプログラミング初心者が、railsの学習を進めながら、躓いた部分、解決した箇所、またそれらの解決方法を備忘録も兼ねてまとめているものです。
最初はprogate。そのあと、「現場で使える RubyonRails5 速習実践ガイド」(通称)「現場Rails」を参考に進めていきました。
そのため、記事の内容には誤りがある可能性があることをご理解ください。
誤りがあればお手数ですが、ご指摘いただければと思います。よろしくお願いします。
環境
Ruby 3.1.2
Rails 7.0.3.1
- if @user.errors.present?
ul#error_explanation
- @user.errors.full_messages.each do |message|
li = message
dl
= form_with model: @user, url: '/users', local: true do |f|
.form-group
f.label 名前
= f.text_field :name, class: 'form-control', id: 'user_name', placeholder: '山田 太郎'
.form-group
f.label 性別
br
= f.radio_button :sex, :男性
= f.label :sex, '男性', {value: :'男性', style: "display: inline-block;"}
= f.radio_button :sex, :女性
= f.label :sex, '女性', {value: :'女性', style: "display: inline-block;"}
.form-group
= f.label :age
/ = f.text_field :age, class: 'form-control', id: 'user_age'
.form-controlls
= f.select :age, options_for_select(1..40), options = { include_blank: true }
|歳
.form-group
= f.label :hemo
= f.text_field :hemo, class: 'form-control', id: 'user_hemo', placeholder: '15.0'
|g/dl
.form-group
= f.label :feti
= f.text_field :feti, class: 'form-control', id: 'user_feti', placeholder: '105.0'
|ng/mL
.form-group
= f.label :sterone
= f.text_field :sterone, class: 'form-control', id: 'user_sterone', placeholder: '550'
|ng/mL
.form-group
#check
= check_box_tag (:user)
f.label 個人情報の取り扱いについて同意します。
iframe src="https://kiyaku.jp/hinagata/privacy.html"
/ =f.submit '判定を開始する', class: 'btn btn-primary'
input(type="submit" id='link3' value="判定を開始する" disabled)
class User < ApplicationRecord
validates :name, presence: true
validates :sex, presence: true
validates :hemo, presence: true
validates :feti, presence: true
validates :sterone, presence: true
---中略---
end
class UsersController < ApplicationController
def show
@user = User.find(params[:id])
end
def new
@user = User.new
end
def create
@user = User.new(user_params)
if @user.save
redirect_to @user, notice: "判定が正常に実行されました。"
else
render :new, status: :unprocessable_entity
end
end
private
def user_params
params.require(:user).permit(:name, :sex, :age, :hemo, :feti, :sterone)
end
end
問題のエラー
webサイトなどによくある、個人情報などの取り扱いについて、同意する際、チェックマークなんかいれますよね。
以下の画像のようなイメージです。
チェックマークが入ったら、「判定を開始する」ボタンが出てくるようにしたかったです。(してます。)
しかしながら、バリデーションを追加して、「判定を開始する」ボタンを押したら、以下のようなエラーになりました。
どうやら:urserには、:nameや:ageなどの入力された値が入ってくるはずなのに、'1'という数値が入ってきてしまっている。というようなエラーなようです。
解決方法
メンターの方にアドバイスをもらいました。
①モデルで、データベースに保存しない属性を指定できるattribute
で定義する。
agreement
はデータベースには保存されない、同意をしたかチェックするために使用する
attribute :agreement, :boolean, default: false
②agreement
に対して、バリデーションをつける
# 新規作成時には同意を必須して、かつtrueしか許可しない
validates :agreement, presence: true, acceptance: true, on: [:create]
③ストロングパラメータにagreement
を追加
class UsersController < ApplicationController
private
def user_params
params.require(:user).permit(:name, :sex, :age, :hemo, :feti, :sterone, :agreement)
end
end
④viewのコードも汚かったので、同時に直していただきました。
(f.labelの部分に=がついていなかったり、idの部分がおかしかったので、整理しました。わかりにくくてすみません💦)
(最終的なコード)
- if @user.errors.present?
ul#error_explanation
- @user.errors.full_messages.each do |message|
li = message
dl
= form_with model: @user, url: '/users', local: true do |f|
.form-group
= f.label :name
= f.text_field :name, class: 'form-control', id: 'user_name', placeholder: '山田 太郎'
.form-group
= f.label :sex
br
= f.radio_button :sex, :男性
= f.label :sex, '男性', {value: :'男性', style: "display: inline-block;"}
= f.radio_button :sex, :女性
= f.label :sex, '女性', {value: :'女性', style: "display: inline-block;"}
.form-group
= f.label :age
.form-controlls
= f.select :age, options_for_select(1..40), options = { include_blank: true }
|歳
.form-group
= f.label :hemo
= f.text_field :hemo, class: 'form-control', id: 'user_hemo', placeholder: '15.0'
|g/dl
.form-group
= f.label :feti
= f.text_field :feti, class: 'form-control', id: 'user_feti', placeholder: '105.0'
|ng/mL
.form-group
= f.label :sterone
= f.text_field :sterone, class: 'form-control', id: 'user_sterone', placeholder: '550'
|ng/mL
.form-group
= f.check_box :agreement, checked: false, id: 'check'
= f.label :agreement, '個人情報の取り扱いについて同意します。', for: 'check'
iframe src="https://kiyaku.jp/hinagata/privacy.html"
input(type="submit" id='link3' value="判定を開始する" disabled)
これで、バリデーションを加え、チェック機能を実装しても、できるようになりました。バリデーションもしっかり機能しています。
おわりに
今回のエラーの大きな原因は、同意するのボタンの部分の実装がうまくいっておらず、本来カラムが入るべきところを、定義していない:user
を入れてしまったことが原因です。slimの時のcheckboxの書き方をしかり覚えて、同じミスがないようにしたいです。また、modelにattribute
を定義することで、データに登録せずとも、同意したかどうかをチェックできるものがあったので、以後使えそうだなと思いました。かなり読みにくい記事だとは思いますが、だれかの役に立てれば幸いです。もし何かあれば、お気軽にコメントよろしくお願いします。