やりたい事・困っている事
親カテゴリを選択すると、子カテゴリのフォームの中身が動的に変わり、子カテゴリが選択されると、孫カテゴリも動的に変わるセレクトボックスをつくりたいです。
以下を参考にしました。
Ajaxでセレクトボックスの中身が動的に変わるRailsアプリの作り方(Qiita)
【Rails】Ajaxでセレクトボックスの中身が動的に変わる実装(3段構成)
具体的にはユーザーが記事(post)を投稿する際に
Prefecture(都道府県)→City(市区町村)→Area(エリア)
のカテゴリを動的に選択できるようにしたいです。
親・子の要素が動的に動いている状態だったのですが、孫要素を動かす為に修正したところ、
現在はエラーが出てしまいどのように修正すればいいのか分からなくなってしまいました。
ActionController::UrlGenerationError in CitiesController#index
No route matches {:action=>"index", :controller=>"areas", :prefecture_id=>#<City id: 33, name: "青森", prefecture_id: 17, created_at: "2019-11-02 09:42:41", updated_at: "2019-11-02 09:42:41">}, missing required keys: [:city_id]
【path: prefecture_city_areas_path(city)】
お分かりになる方がいらっしゃればご教授願います。
宜しくお願い致します。
##(追記)試してみたこと・新たな問題
上記のエラーを解決する為に city.idを追記
Controller
ruby
1class CitiesController < ApplicationController 2 def index 3 prefecture = Prefecture.find(params[:prefecture_id]) 4 cities = prefecture.cities.map do |city| 5 { 6 id: city.id, 7 name: city.name, 8 ~~path: prefecture_city_areas_path(city)~~ 9 path: prefecture_city_areas_path(city.id, city) 10 } 11 end 12 render json: cities 13 end 14end
エラーは解消され、親要素から子要素は順調に動いているのですが、
孫要素に反応がありません。
console.log($(this).find('option:selected').data().grandchildrenPath);
undefined となってしまいます。
どなたかお分かりになる方いらっしゃいましたらお力添えをお願いいたします。
##コード
view
ruby
1 <div> 2 <% prefecture_options = Prefecture.order(:id).map { |c| [c.name, c.id, data: { children_path: prefecture_cities_path(c) }] } %> 3 <%= f.select :prefecture_id, prefecture_options, { include_blank: true }, class: 'select-parent' %> 4 </div> 5 <div> 6 <% cities = @post.prefecture.try(:cities) || [] %> 7 <% city_options = cities.map { |c| [c.name, c.id, data: { path: prefecture_city_areas_path(c) }] } %> 8 <%= f.select :city_id, city_options, { include_blank: true }, class: 'select-children' %> 9 </div> 10 <div> 11 <% areas = @post.city.try(:areas) || [] %> 12 <% area_options = areas.map { |c| [c.name, c.id] } %> 13 <%= f.select :area_id, area_options, { include_blank: true }, class: 'select-grandchildren' %> 14 </div>
coffeescript
1$(document).on 'turbolinks:load', -> 2 replaceSelectOptions = ($select, results) -> 3 $select.html $('<option>') 4 $.each results, -> 5 option = $('<option>').val(this.id).text(this.name) 6 if this.path 7 option.data('path', this.path) 8 $select.append(option) 9 10#親から子 11 replaceChildrenOptions = -> 12 childrenPath = $(@).find('option:selected').data().childrenPath 13 $selectChildren = $(@).closest('form').find('.select-children') 14 if childrenPath? 15 $.ajax 16 url: childrenPath 17 dataType: "json" 18 success: (results) -> 19 replaceSelectOptions($selectChildren, results) 20 error: (XMLHttpRequest, textStatus, errorThrown) -> 21 console.error("Error occurred in replaceChildrenOptions") 22 console.log("XMLHttpRequest: #{XMLHttpRequest.status}") 23 console.log("textStatus: #{textStatus}") 24 console.log("errorThrown: #{errorThrown}") 25 else 26 replaceSelectOptions($selectChildren, []) 27 28#子から孫 29 replaceGrandChildrenOptions = -> 30 grandchildrenPath = $(@).find('option:selected').data().Path 31 $selectGrandChildren = $(@).closest('form').find('.select-grandchildren') 32 console.log($(@).find('option:selected').data().grandchildrenPath) 33 34 if grandchildrenPath? 35 $.ajax 36 url: grandchildrenPath 37 dataType: "json" 38 success: (results) -> 39 replaceSelectOptions($selectGrandChildren, results) 40 error: (XMLHttpRequest, textStatus, errorThrown) -> 41 console.error("Error occurred in replaceChildrenOptions") 42 console.log("XMLHttpRequest: #{XMLHttpRequest.status}") 43 console.log("textStatus: #{textStatus}") 44 console.log("errorThrown: #{errorThrown}") 45 else 46 replaceSelectOptions($selectGrandChildren, []) 47 48 $('.select-parent').on 49 'change': replaceChildrenOptions 50 51 $('.select-children').on 52 'change': replaceGrandChildrenOptionsコードの表示(ブロック)
Controller
ruby
1class CitiesController < ApplicationController 2 def index 3 prefecture = Prefecture.find(params[:prefecture_id]) 4 cities = prefecture.cities.map do |city| 5 { 6 id: city.id, 7 name: city.name, 8 path: prefecture_city_areas_path(city) 9 } 10 end 11 render json: cities 12 end 13end
ruby
1class AreasController < ApplicationController 2 def index 3 city = City.find(params[:city_id]) 4 render json: city.areas.select(:id, :name) 5 end 6end
Model
ruby
1class Post < ApplicationRecord 2 belongs_to :prefecture, optional: true 3 belongs_to :city, optional: true 4 belongs_to :area, optional: true 5end
ruby
1class Prefecture < ApplicationRecord 2 has_many :cities, ->{ order(:id) }, dependent: :destroy 3end
ruby
1class City < ApplicationRecord 2 belongs_to :prefecture, optional: true 3 has_many :areas, ->{ order(:id) }, dependent: :destroy 4end
ruby
1class Area < ApplicationRecord 2 belongs_to :city, optional: true 3end
Routing
ruby
1Rails.application.routes.draw do 2resources :posts, only: [:index, :show, :new, :create, :edit, :update, :destroy] do 3collection do 4 get '/:id/city' => 'posts#city', as: "city" 5 end 6 end 7 resources :prefectures, only: [] do 8 resources :cities, only: :index do 9 resources :areas, only: :index 10 end 11 end 12end
あなたの回答
tips
プレビュー