Railsで連動プルダウン

都道府県を選んだら市区町村が絞り込まれるとかよくあるやつ。

今回は会社登録時に都道府県と市区町村をプルダウンで選べるみたいな設定で考える。

都道府県、市区町村、会社のモデルとそれぞれのリレーションはこんな感じ。

# ms_pref.rb
class MsPref < ActiveRecord::Base
  has_many :ms_cities
end

# ms_city.rb
class MsCity < ActiveRecord::Base
  belongs_to :ms_pref
end

# company.rb
class Company < ActiveRecord::Base
  belongs_to :ms_pref
  belongs_to :ms_city
end

まずはviewで市区町村のプルダウンをpartial化する。

# _form.html.slim
= form_for @company do |f|

   (省略...)

  .field
    = f.label :ms_pref
    = f.collection_select :ms_pref, MsPref.all, :id, :name
  .field
    = f.label :ms_city
    #cities_select
      = render partial: 'cities', locals: {ms_pref_id: MsPref.first.id}

   (省略...)

#  _cities.html.slim
= collection_select :company, :ms_city, MsCity.where(ms_pref_id: ms_pref_id), :id, :name

都道府県の変更を検知するためのjquery(coffeescript)を書く。

# companies.js.coffee
$(document).on 'change', '#company_ms_pref', ->
  $.ajax(
    type: 'GET'
    url: '/companies/cities_select'
    data: {
      ms_pref_id: $(this).val()
    }
  ).done (data) ->
    $('#cities_select').html(data)

あとは、ajaxでの値うけとり先のroutesの設定とcontrollerでそのメソッド定義して処理すれば完成!

# routes.rb
resources :companies do
  collection do
    get :cities_select
  end
end

# companies_controller.rb
def cities_select
  if request.xhr?
    render partial: 'cities', locals: {ms_pref_id: params[:ms_pref_id]}
  end
end

Rails楽しいー♡