createアクションでのみ作動するカスタムバリデーションを実装しようと思ったのですがcocoonを使っているためパラメータが複雑でよくわからなくなってしまいました。
ログで確認したパラメータはこうなっております
"band"=>{"name"=>"Beatles", "relationships_attributes"=>{"0"=>{"user_id"=>"2", "part"=>"Gt1", "_destroy"=>"false"}, "1598231822108"=>{"user_id"=>"0", "part"=>"Vo1", "_destroy"=>"false"}}}
ここからuser_id == current_user に一致する配列が一つでもあればtrue,そうでなければfalseというコードはどう書けばいいでしょうか
def band_params params.require(:band).permit( :name, relationships_attributes: [ :id, :part, :band_id, :user_id, :_destroy ] )
試したこと
最初の構想ではこういうバリデーションを作ろうとしていました
class BandCreateValidator < ActiveModel::Validator def validate(record) record.each do |r| end end
回答を参考にして
サーバーログで確認したパラメータ
"band"=>{"name"=>"Beatles", "relationships_attributes"=>{"0"=>{"user_id"=>"2", "part"=>"Gt1", "_destroy"=>"false"}, "1598231822108"=>{"user_id"=>"0", "part"=>"Vo1", "_destroy"=>"false"}}}
と実際のパラメータ
<ActionController::Parameters {"name"=>"Beatles", "relationships_attributes"=><ActionController::Parameters {"0"=><ActionController::Parameters {"part"=>"Gt1", "user_id"=>"2", "_destroy"=>"false"} permitted: true>, "1598279704474"=><ActionController::Parameters {"part"=>"Vo1", "user_id"=>"0", "_destroy"=>"false"} permitted: true>} permitted: true>} permitted: true>
が違ったためrelations.any?{|k,v| v["user_id"].to_i == current_user.id}では
エラー undefined method `any?' for #ActionController::Parameters:0x00007fb8b09e55c8
が起きてしまいました。
そこでセキュリティ的に問題はありますがto_unsafe_hを付けてみました
bands_controller.rb . . . def create @band = Band.new(band_params) if validate_on_create(band_params) if @band.save redirect_to @band flash[:notice] = 'バンドの登録に成功しました' else flash[:alert] = 'バンドの登録に失敗しました(save)' redirect_to new_band_path end else flash[:alert] = 'バンドの登録に失敗しました(validate)' redirect_to new_band_path end end . . private def validate_on_create(relations) relations.to_unsafe_h.any?{|k,v| v["user_id"].to_i == current_user.id} end
このように記述したところなんとか動いたのですが、本来通るはずであるuser_id == current_userでも'バンドの登録に失敗しました(validate)'と表示され通りません(ページの描写は出来ている)
そこで validate_on_craeteメソッドから意図的に to_unsafe_h を外してエラーを起こしbetter_errorでデバッグしてみました
コンソール >> relations => <ActionController::Parameters {"name"=>"Beatles", "relationships_attributes"=><ActionController::Parameters {"0"=><ActionController::Parameters {"part"=>"Gt1", "user_id"=>"2", "_destroy"=>"false"} permitted: true>, "1598279704474"=><ActionController::Parameters {"part"=>"Vo1", "user_id"=>"0", "_destroy"=>"false"} permitted: true>} permitted: true>} permitted: true> >> relations.any? !! #<NoMethodError: undefined method `any?' for #<ActionController::Parameters:0x00007fb8b09e55c8>> >> relations.to_unsafe_h => {"name"=>"Beatles", "relationships_attributes"=>{"0"=>{"part"=>"Gt1", "user_id"=>"2", "_destroy"=>"false"}, "1598279704474"=>{"part"=>"Vo1", "user_id"=>"0", "_destroy"=>"false"}}} >> relations.to_unsafe_h.any? => true >> relations.to_unsafe_h.any?{|k,v| v["user_id"].to_i == 2} => false ##コンソールではcurrent_user.idが使えないため代わりに同じ値の2を使用しています
一体なぜここがFalseになるのでしょうか?
回答1件
あなたの回答
tips
プレビュー
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2020/08/24 14:55
2020/08/24 21:12
2020/08/25 02:37