Извините, что сложил это на вас, но это действительно сломано.
Давайте начнем с контроллера / маршрута. Идиоматический c способ сделать это по вложенному маршруту - GET /countries/:country_id/cities
. Вы также не должны вносить это в свою модель Profile / ProfilesController.
Вы можете объявить маршрут с помощью:
get '/countries/:country_id/cities', to: 'countries/cities#index'
или с помощью resources
с блоком:
resources :countries, only: [] do
resources :cities, only: [:index], module: :countries
end
И контроллер вот так:
module Countries
class CitiesController < ApplicationController
# GET /countries/:country_id/cities
def index
@cities = Profile::CITY_LIST[params[:city_id].to_i]
end
end
end
Не уверен, что я действительно могу понять, почему вы хотите использовать константу в модели, которая вообще не должна отвечать за это, а не на самом деле создание моделей "Страна" и "Город".
Самая большая проблема с вашим JavaScript заключается в том, что он абсолютно неидемпотентен. Все это работает на window.addEventListener("load")
, так что оно работает при начальной загрузке страницы, а затем полностью выходит из строя, когда Turbolinks заменяет содержимое страницы на AJAX, так как эти обработчики событий были присоединены непосредственно к самим элементам.
Чтобы написать JavaScript, который работает с Turbolinks, вы должны думать иначе. Создайте идемпотентные обработчики, которые улавливают событие, когда оно всплывает в DOM.
# app/javascript/packs/country_cities.js
import Rails from '@rails/ujs';
document.addEventListener('change', (event) => {
let input = event.target;
if (input.matches('#profile_country')) {
Rails.ajax({
url: `/cities/${input.value}/country`,
type: 'get',
dataType : 'script'
});
}
});
Если вы хотите использовать шаблон js.erb
, вам также необходимо переписать ваше представление так, чтобы оно трансформировало страницу:
// app/views/countries/cities.js.erb
document.getElementById("#profile_city").innerHTML = "<%= j options_for_select(@cities) %>";
Но вы также можете просто использовать JSON и создать элементы опции на клиенте, если хотите избежать ответственности сервера за преобразования на стороне клиента.