環境
- macOS 10.15.6
- Ruby 2.5.7
- Rails 5.2.3
参考にしたURL
https://pikawaka.com/rails/enum
https://qiita.com/clbcl226/items/3e832603060282ddb4fd
https://qiita.com/ATORA1992/items/fc6217412c5bc004ac6c
https://qiita.com/y-suna/items/1f5f34c6289fd88199a5
https://qiita.com/ozackiee/items/17b91e26fad58e147f2e
実現したいこと
- 投稿時の:expense カラムのセレクトボックスの選択肢をenum で登録した値(type1, type2, type3)で表示したい
html
1# 実現したいセレクトボックスの形 2<select> 3 <option value="1">type1</option> 4 <option value="2">type2</option> 5 <option value="3">type3</option> 6</select>
- DB に保存する値はセレクトボックスのvalue の値(1, 2, 3)をInteger 型で保存したい
ruby
1# 実現したいDB 保存の形 2{ 3 :name => "name", 4 :expense => 1 # enum で登録したvalue値のインデックス番号のInteger 型 5}
問題
- DB 保存時に
'1' is not a valid expense
エラーで保存ができません(はじめの数字はenum で定義したvalue値に対応するインデックス番号)
状態
ruby
1# schema.rb 2 create_table "destinations", force: :cascade do |t| 3 t.string "name" 4 t.integer "expense", default: 0 5 end
ruby
1# controller 2 def create 3 @destination = current_user.destinations.build(destination_params) 4 if @destination.save 5 flash[:success] = "Destination added!" 6 redirect_to destination_path(@destination) 7 else 8 render 'destinations/new' 9 end 10 end 11 12 private 13 14 def destination_params 15 params.require(:destination).permit(:name, :expense) 16 end
ruby
1# model 2class Destination < ApplicationRecord 3 4 enum expense: { 5 "---": 0, 6 type1: 1, 7 type2: 2, 8 type3: 3, 9 } 10end
ruby
1# view 2<%= form_with model: @destination |f| %> 3 <%= f.label :expense %> 4 <%= f.select :expense, options_for_select(Destination.expenses), {} %> 5 <%= f.submit%> 6<% end %>
html
1# 出力されたHTML 2<select name="destination[expense]"> 3 <option value="0">---</option> 4 <option value="1">type1</option> 5 <option value="2">type2</option> 6 <option value="3">type3</option> 7</select>
原因の予想
'1' is not a valid expense
で引数に関するエラーという事なのでbinding.pry で確認したところInteger 型で保存するカラムにString 型で値が送られる事によるエラーでないかと予想しました
ruby
1# expense の型を調べる 2[1] pry > destination_params[:expense] 3"3" 4[2] pry > destination_params[:expense].class 5String < Object
試した事
下記を参考にstrong_parameters で保存される値を強制的にInteger 型に変換する方法を試しました
https://qiita.com/y-suna/items/1f5f34c6289fd88199a5
ruby
1# controller 2# strong_parameters で:expense をInteger 型に変換 3# 修正前 4 def destination_params 5 params.require(:destination).permit(:name, :expense) 6 end 7 8# 修正後 9 def destination_params 10 params.require(:destination).permit(:name).merge(expense: params[:destination][:expense].to_i) 11 end
pry
1# :expense がInteger 型になっているか確認 2[1] pry > destination_params[:expense] 3Unpermitted parameter: :expense 43 5[2] pry > destination_params[:expense].class 6Unpermitted parameter: :expense 7Integer < Numeric
試した事で起こった新たな問題
- セレクトボックスのvalue値(1, 2, 3)を保存したいのですが、保存される値がセレクトボックスの選択肢の値(type1, type2, type3)になってしまいます
- schema.rb で:expense の型をInteger 型に指定しているはずなのにDB に保存できてしまう
pry
1# :expense に保存されている値を確認 2[1] pry > destination = Destination.first 3{ 4 :name => "name", 5:expense => "type1", # ここにセレクトボックスのvalue値(1, 2, 3)を保存したい 6} 7[2] pry > destination.expense 8"type1" 9[3] pry > destination.expense.class 10String < Object
pry
1# コントローラj@destination に送られる:expense の値を確認 2[1] pry > @destination.expense 3"type1" 4[2] pry > @destination.expense.class 5String < Object
試した事で分からないこと
- enum で定義した(名前定義: 対応する数値) にどのタイミングで変換されて保存されるのか?
- なぜschema.rb で指定した型以外でもDB に保存できるのか?
教えて頂きたいこと
長々と書いてしまったのでまとめます。
- enum で定義した値でセレクトボックスを表示したい
- セレクトボックス選択で保存される値はenum で定義した値のインデックス番号をInteger 型で保存したい
この2点を実現したいです。よろしくお願いします。
あなたの回答
tips
プレビュー