form_withの非同期通信
form_withの非同期通信
form_withの処理でハマってしまったことがあったので、こちらにまとめます。
以下のようなコードを記述していました。
[app/controllers/cooking_informations_controller.rb] def search_time @fishes = Fish.all @cookings = Cooking.all search_time_format = CookingSearchTimeForm.new(fish_kind: params[:fish_kind], cooking_name: params[:cooking_name], count: params[:count]) @fish = Fish.find_by(kind: params[:fish_kind]) end
[app/views/cooking_informations/search_time.html.slim] .search-wrapper .container .row.justify-content-md-center .col-md-auto.mt-5 = form_with url: search_time_cooking_informations_path 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'} = f.number_field :count, min: 1, placeholder: '料理する魚の数(必須)', class: 'search_form text-center' = button_tag type: 'submit', class: 'btn btn-primary search_button' do i.fas.fa-search .row.justify-content-md-center .col - if @fish.present? = @fish.kind - else | テスト
上記のように記述していて、魚の種類を選ばずに検索をするとブラウザに以下のように表示される。
ログは、以下のようになっている。
Started POST "/cooking_informations/search_time" for ::1 at 2021-12-24 00:23:52 +0900 Processing by CookingInformationsController#search_time as JS ① Parameters: {"authenticity_token"=>"tD4Ldg9RT6FXji1IyvjpdOYyIzeo2SOTe0YRvYkP4UWbsnr0OY//FpWzamJBl6j7ZDDait9hI6uvxYE1i+nDng==", "fish_kind"=>"", "cooking_name"=>"", "count"=>"", "button"=>""} Fish Load (0.4ms) SELECT `fishes`.* FROM `fishes` WHERE `fishes`.`kind` = '' LIMIT 1 ↳ app/controllers/cooking_informations_controller.rb:13:in `search_time' Rendering cooking_informations/search_time.html.slim within layouts/application Fish Load (0.4ms) SELECT `fishes`.* FROM `fishes` ↳ app/views/cooking_informations/search_time.html.slim:7 Cooking Load (0.3ms) SELECT `cookings`.* FROM `cookings` ↳ app/views/cooking_informations/search_time.html.slim:8 Rendered cooking_informations/search_time.html.slim within layouts/application (Duration: 5.5ms | Allocations: 4009) [Webpacker] Everything's up-to-date. Nothing to do Rendered shared/_header.html.slim (Duration: 0.3ms | Allocations: 158) Completed 200 OK in 37ms (Views: 33.4ms | ActiveRecord: 1.1ms | Allocations: 13916)
ログの①を確認すると[JS]となっており、JavaScript形式で取得している。
魚の種類を選んで検索をするとブラウザに以下のように表示される。
ログは、以下のようになっている。
Started POST "/cooking_informations/search_time" for ::1 at 2021-12-24 00:33:53 +0900 Processing by CookingInformationsController#search_time as JS ① Parameters: {"authenticity_token"=>"tD4Ldg9RT6FXji1IyvjpdOYyIzeo2SOTe0YRvYkP4UWbsnr0OY//FpWzamJBl6j7ZDDait9hI6uvxYE1i+nDng==", "fish_kind"=>"アジ", "cooking_name"=>"", "count"=>"", "button"=>""} ② Fish Load (0.5ms) SELECT `fishes`.* FROM `fishes` WHERE `fishes`.`kind` = 'アジ' LIMIT 1 ↳ app/controllers/cooking_informations_controller.rb:13:in `search_time' Rendering cooking_informations/search_time.html.slim within layouts/application Fish Load (0.6ms) SELECT `fishes`.* FROM `fishes` ↳ app/views/cooking_informations/search_time.html.slim:7 Cooking Load (0.4ms) SELECT `cookings`.* FROM `cookings` ↳ app/views/cooking_informations/search_time.html.slim:8 Rendered cooking_informations/search_time.html.slim within layouts/application (Duration: 8.0ms | Allocations: 4012) [Webpacker] Everything's up-to-date. Nothing to do Rendered shared/_header.html.slim (Duration: 0.4ms | Allocations: 158) Completed 200 OK in 36ms (Views: 31.0ms | ActiveRecord: 1.5ms | Allocations: 13935)
ログの①を確認すると[JS]となっており、JavaScript形式で取得している。
また、②より[アジ]がパラメーターで渡っている。
コントローラで以下のように記述があるので、@fishに値が入り、
@fish = Fish.find_by(kind: params[:fish_kind])
viewファイルの条件分岐により、
- if @fish.present? = @fish.kind - else | テスト
ブラウザには、魚の種類が表示されるはずだがブラウザには[テスト]と表示される。。。。
開発者ツールの[Network]の[Preview]と[Response]を確認すると以下のようになる。
開発者ツールの[Elements]を確認すると、以下のように[テスト]となっている。
原因は、ログの①よりJavaScript形式で取得しているが、そもそもHTML形式しか用意していない為。
開発者ツールの[Network]の[Preview]と[Response]では、想定通りのものが表示されているのに、開発者ツールの[Elements]やブラウザには、想定外のものが表示されるのは、この為である。
今回このようになってしまったのは、[form_with]に[local: true]の記述を忘れて非同期通信になってしまった為。
以下のように[local: true]を記述すると、
[app/views/cooking_informations/search_time.html.slim] .search-wrapper .container .row.justify-content-md-center .col-md-auto.mt-5 = form_with url: search_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'} = f.number_field :count, min: 1, placeholder: '料理する魚の数(必須)', class: 'search_form text-center' = button_tag type: 'submit', class: 'btn btn-primary search_button' do i.fas.fa-search .row.justify-content-md-center .col - if @fish.present? = @fish.kind - else | テスト
魚の種類を選択して検索するとブラウザに想定通りのものが表示される。
ログも以下のように、[HTML]形式で取得している。
Started POST "/cooking_informations/search_time" for ::1 at 2021-12-24 00:56:13 +0900 Processing by CookingInformationsController#search_time as HTML Parameters: {"authenticity_token"=>"2VztlBEwgxv2rzN1ukmXjWnIP8X3HTIkgJ0lLnr9Wxr20JwWJ+4zrDSSdF8xJtYC68rGeIClMhxUHrWmeBt5wQ==", "fish_kind"=>"アジ", "cooking_name"=>"", "count"=>"", "button"=>""} Fish Load (0.3ms) SELECT `fishes`.* FROM `fishes` WHERE `fishes`.`kind` = 'アジ' LIMIT 1 ↳ app/controllers/cooking_informations_controller.rb:13:in `search_time' Rendering cooking_informations/search_time.html.slim within layouts/application Fish Load (0.5ms) SELECT `fishes`.* FROM `fishes` ↳ app/views/cooking_informations/search_time.html.slim:7 Cooking Load (0.3ms) SELECT `cookings`.* FROM `cookings` ↳ app/views/cooking_informations/search_time.html.slim:8 Rendered cooking_informations/search_time.html.slim within layouts/application (Duration: 6.8ms | Allocations: 4004) [Webpacker] Everything's up-to-date. Nothing to do Rendered shared/_header.html.slim (Duration: 0.2ms | Allocations: 158) Completed 200 OK in 25ms (Views: 21.6ms | ActiveRecord: 1.2ms | Allocations: 13911)