目的
- DBに格納されている数値に少数の値を足そうとして詰まりまくったところをまとめる
困った箇所
- viewファイルで表している入力formの少数の値が入力できない。
- こちらで解決した→HTML 少数入力時に「有効な値を入力してください」と出たときの話
- 入力してDBのカラムに保存しようとしてもカラムに反映されない。
save
でのエラーは出ない。 -
rails console
で当該カラムに少数を入力しsave
するとDBのカラムに反映されるが、formから少数を入力しても足し算されない、整数の足し算はできる。
「viewファイルで表している入力formの少数の値が入力できない」の解決方法
- 下記の方法で解決した。
「入力してDBのカラムに保存しようとしてもカラムに反映されない。save
でのエラーは出ない。」の原因と解決方法
調査と原因
- 数値を保存するカラム
stady_time
のデータ型は少数を扱うためにdecimal
にしている。 - 下記にカラム
stady_time
を作成したときのマイグレーションファイルを下記に記載する。
class AddStudyTimeHashTagToPosts < ActiveRecord::Migration[6.0]
def change
add_column :posts, :study_time, "decimal"
end
end
- 原因はカラム作成時にデータ型"decimal"を設定するときにオプションで格納する数値の全桁数と少数部分の桁数のを指定する必要があったようである。
解決方法
-
カラム
study_time
を削除して再度オプション付きで作成し直すか、現在存在するstudy_time
カラムのデー型を設定し直すかの二通りがある。 -
今回は個人プロダクトであるが、デプロイして使用されているサービスで重要なカラムを一旦削除することはありえないため、データ型を設定し直す方法をとる。
-
下記の修正を加える
修正前 修正後 修正可否 カラム名 study_time study_time 修正しない データ型 decimal decimal 修正しない データ型のオプション 指定なし 全桁数12桁 少数点以下桁数2桁 修正する -
下記にカラムのデータ型設定を修正する手順を記載する。
-
下記コマンドを実行してマイグレーションファイル(DBの仕様変更を命令するファイル)を作成する。
$ rails g migration change_study_time
-
db/migrate/
に存在するマイグレーションファイル20200112011439_change_study_time.rb
に下記の記載を行う(#
の行はコメントなので実際はなくても良い)class AddPasswordToUsers < ActiveRecord::Migration[6.0] def change #カラムの変更なのでchenge_column :テーブル名, :カラム名, :データ型, :オプション(数値の全桁数), :オプション(数値の小数点以下の桁数、第二位まで欲しいので2とした) change_column :posts, :study_time, :decimal, precision: 12, scale: 2 end end
-
下記コマンドを実行してマイグレート(DBにマイグレーションファイル通りの仕様変更を行う命令)を行う。
$ rails db:migrate
-
もしマイグレーションファイルの記載を間違えてマイグレートしてしまったら下記の方法でマイグレート前の状態に戻す。
-
下記方法でカラムの方が正常に設定されているか確認する。
-
今回の場合Postモデルのstudy_timeカラムなので下記のコマンドになる。
- rails consoleを起動し下記コマンドを実行する。
>Post.columns_hash['study_time'].type => :decimal
-
「rails console
で当該カラムに少数を入力しsave
するとDBのカラムに反映されるが、formから少数を入力しても足し算されない、整数の足し算はできる。」の原因と解決方法
調査と原因
-
rails consoleでの確認と切り分けにより足し算を行なっているコントローラファイルに問題があると感じた。
-
少数は表示できるのに足されないということはformから送られてきた値を数値に変換している箇所に間違いがあると予想した。
-
下記にpostコントローラの当該処理のメソッドを抜粋して記載する。
def update @post = Post.find_by(id: params[:id]) @post.study_time += params[:study_time].to_i @post.save redirect_to("/posts/#{@post.id}") end
-
params[:study_time]
にはフォームで入力した少数値が入っている。.to_i
で入力した文字列を数値に変更している。 -
整数を表現する場合は
.to_i
でも良いが、少数を扱い際は別の表現にしないといけない。
解決方法
-
コントローラでフォームで入力した値を数値をして扱う処理で整数に変換してしまっているので少数も含む数値に変換してあげる記載をする。
-
.to_i
を.to_f
とする。 -
下記に正しいコードを記載する。
def update @post = Post.find_by(id: params[:id]) @post.study_time += params[:study_time].to_f @post.save redirect_to("/posts/#{@post.id}") end