renderで指定したファイルがレンダリングする際にエラーになってしまう
renderで指定したファイルがレンダリングする際にエラーになってしまう現象
renderで指定したファイルがレンダリングする際にエラーになってしまうことがあり、ハマったのでこちらにまとめます。
以下のようなコードを記述していました。
[app/controllers/cooking_informations_controller.rb] def search_time ① @fishes = Fish.all @cookings = Cooking.all end def search_calculate_cooking_time ② @fishes = Fish.all @cookings = Cooking.all search_time_format = CookingSearchTimeForm.new(fish_kind: params[:fish_kind], cooking_name: params[:cooking_name]) if search_time_format.save ④ @fish_kind = params[:fish_kind] @cooking_name = params[:cooking_name] @handle_pattern = search_time_format.handle_search @cooking_information = search_time_format.cooking_information_search else flash.now[:notice] = "検索フォームを全て入力してくだい" render :search_time end end def calculate_cooking_time ③ calculate_cooking_time_format = CalculateCookingTimeForm.new(let_foodstuff_capacity: params[:let_foodstuff_capacity], cookware_capacity: params[:cookware_capacity], count: params[:count]) if calculate_cooking_time_format.save render template: "static_pages/top" else flash.now[:notice] = "計算フォームを全て入力してください" render :search_time end end
[app/forms/cooking_time_form.rb] include ActiveModel::Model include ActiveModel::Attributes attribute :fish_kind, :string attribute :cooking_name, :string validates :fish_kind, presence: true validates :cooking_name, presence: true def save invalid? ? false : true end def handle_search cooking_id = Cooking.find_by(name: cooking_name).id fish_id = Fish.find_by(kind: fish_kind).id handle_id = CookingInformation.find_by(cooking_id: cooking_id, fish_id: fish_id).handle_id Handle.find(handle_id).pattern end def cooking_information_search cooking_id = Cooking.find_by(name: cooking_name).id fish_id = Fish.find_by(kind: fish_kind).id CookingInformation.find_by(cooking_id: cooking_id, fish_id: fish_id) end
[app/forms/calculate_cooking_time_form.rb] include ActiveModel::Model include ActiveModel::Attributes attribute :let_foodstuff_capacity, :integer attribute :cookware_capacity, :integer attribute :count, :integer validates :let_foodstuff_capacity, presence: true validates :cookware_capacity, presence: true validates :count, presence: true def save invalid? ? false : true end
[app/views/cooking_informations/search_time.html.slim] .search-wrapper .container .row.justify-content-md-center .col-md-auto.mt-5 = render partial: 'search_time_form'
[app/views/cooking_informations/search_caluculate_cooking_time.html.slim] .search-wrapper .container .row.justify-content-md-center .col-md-auto.mt-5 = render partial: 'search_time_form' ⑤ .row.justify-content-md-center .col .mt-5.fs-3.cooking-list .cooking-information-title ' 料理名: = @cooking_name | ( = @fish_kind | )<br> ' 捌き方: = @handle_pattern .cooking-information-overview.mt-4 .d-inline-block = image_tag cooking_image_path(@cooking_information), size: '400x300', class: 'rounded-circle' .d-inline-block.float-end = form_with url: calculate_cooking_time_cooking_informations_path, local: true do |f| .form-group = f.label :count, '調理する魚の数:' = f.number_field :count, min: 1, placeholder: '料理する魚の数(必須)', class: 'calculate-fish-count-form text-center' .form-group = f.label :let_foodstuff_capacity, '食材を寝かせられるキャパシティ:' = f.number_field :let_foodstuff_capacity, min: 1, step: 0.5, placeholder: '匹数(必須)', class: 'calculate-cooking-capacity-form text-center' .form-group = f.label :cookware_capacity, '調理機材のキャパシティ:' = f.number_field :cookware_capacity, min: 1, step: 0.5, placeholder: '匹数(必須)', class: 'calculate-cooking-capacity-form text-center' = f.submit '合計の料理時間は?', class: 'btn btn-primary calculate-cooking-time-button' .d-flex.justify-content-center.mt-5#js-result-calculate-cooking-time ' 料理時間の合計: | ?<br> ' 捌く時間の合計: | ?<br> ' 調理時間の合計: | ? .cooking-information-details.mt-4 .d-inline-block | 捌き方の動画 .mt-3 iframe width="400" height="300" src="#{FishHandleInformation.find_by(fish_id: @cooking_information.fish_id, handle_id: @cooking_information.handle_id).handle_url}" .d-inline-block.float-end | 料理のレシピサイト<br> .mt-5 = link_to '調理レシピ', "#{@cooking_information.cooking_url}"
[app/views/cooking_informations/_search_time_form.html.slim] = form_with url: search_calculate_cooking_time_cooking_informations_path, local: true do |f| .form-group = f.collection_select :fish_kind, @fishes, :kind, :kind, { include_blank: '魚の種類(必須)' }, {class: 'search_select_form'} = f.collection_select :cooking_name, @cookings, :name, :name, { include_blank: '料理の種類(必須)' }, {class: 'search_select_form'} = button_tag type: 'submit', class: 'btn btn-primary search_button' do i.fas.fa-search
最初に①のアクションにより以下のような画面がレンダリングされる。
上記の画像の魚の種類と料理の種類を入力して検索すると、②のアクションにより以下のような画面がレンダリングされる。
上記の画像の(調理する魚の数)と(食材を寝かせられるキャパシティ)と(調理機材のキャパシティ)を入力して検索すると、③のアクションの下記より、
render template: "static_pages/top"
下記のような画面がレンダリングされる。
(調理する魚の数)と(食材を寝かせられるキャパシティ)と(調理機材のキャパシティ)のいずれかを入力しない場合は、④のバリデーションに引っかかり、以下の処理がされる。
flash.now[:notice] = "計算フォームを全て入力してください" render :search_calculate_cooking_time
renderで[search_calculate_cooking_time]アクションを指定しているので、以下の画面がレンダリングされるのを期待していたが、
実際は、以下のようなエラーになってしまう。
これは、HTTPプロトコルはステートレスによる通信による為である。
流れは以下のようになります。
上記の画面から(調理する魚の数)と(食材を寝かせられるキャパシティ)と(調理機材のキャパシティ)を入力してHTTPリクエストを送る。
↓
サーバー側では、レンダリングにより③のアクションが動く。
↓
バリデーションに引っかからない場合は、以下が処理される。
render template: "static_pages/top"
アプリケーションのトップページがレンダリングされる。
↓
バリデーションに引っかかる場合は、以下が処理される。
render :search_calculate_cooking_time
上記記述により、[app/views/cooking_informations/search_caluculate_cooking_time.html.slim]をレンダリングするファイルに指定する。
↓
[app/views/cooking_informations/search_caluculate_cooking_time.html.slim]の⑤の部分(以下参照)により、
= render partial: 'search_time_form'
[app/views/cooking_informations/_search_time_form.html.slim]がレンダリングするファイルに指定されているが、
このファイルの中には、
= form_with url: search_calculate_cooking_time_cooking_informations_path, local: true do |f| .form-group = f.collection_select :fish_kind, @fishes, :kind, :kind, { include_blank: '魚の種類(必須)' }, {class: 'search_select_form'} = f.collection_select :cooking_name, @cookings, :name, :name, { include_blank: '料理の種類(必須)' }, {class: 'search_select_form'} = button_tag type: 'submit', class: 'btn btn-primary search_button' do i.fas.fa-search
上記のように[@fishes]や[@cookings]などの配列が記載されているが、(調理する魚の数)と(食材を寝かせられるキャパシティ)と(調理機材のキャパシティ)を入力する際にHTTPリクエストを送るさいは、以下のアクションを通るため、
def calculate_cooking_time calculate_cooking_time_format = CalculateCookingTimeForm.new(let_foodstuff_capacity: params[:let_foodstuff_capacity], cookware_capacity: params[:cookware_capacity], count: params[:count]) if calculate_cooking_time_format.save render template: "static_pages/top" else flash.now[:notice] = "計算フォームを全て入力してください" render :search_calculate_cooking_time end end
[@fishes]や[@cookings]を取得していないので、エラーになる。
バリデーションに引っかからない際に、以下のレンダリングがエラーにならないのはトップページのビューファイルにインスタンス変数が記載されていない為である。
render template: "static_pages/top"
参考記事
collection_selectにインスタンス変数を渡すと、undefined method `map' for nil:NilClass が発生するエラー - Qiita