У меня есть две модели, Preset и Plot, которые связаны отношением has_and_belongs_to_many.
class Preset < ApplicationRecord
belongs_to :user
has_and_belongs_to_many :plots
accepts_nested_attributes_for :plots, allow_destroy: true
end
class Plot < ApplicationRecord
has_and_belongs_to_many :presets
belongs_to :theme, optional: true
end
Я использую вложенную форму для создания Presets и связанных с ними графиков. У меня есть несколько динамических c элементов (построенных на примерах из Railscast 196), которые создают разные элементы в зависимости от типа графика, который пользователь хочет создать.
= form_with(model: @preset, local: true) do |f|
= label_tag('preset[name]', "New preset name:")
= text_field_tag('preset[name]')
%br
= label_tag('preset[description]', "Description:")
= text_field_tag('preset[description]')
%br
= link_to_add_plot "Add Default Plot", f, :plots, "defaultplot"
%br
%br
= link_to_add_plot "Add Existing Custom Plot", f, :plots, "customplot"
%br
%br
= link_to_add_plot "New Custom Plot", f, :plots, "newcustomplot"
%br
%br
= submit_tag("Create Preset")
%br
%br
Эти элементы link_to_add_plot используют метод в application_helper.rb для создания уникального элемента (согласно railscast 196) и вставки его в форму. Я могу опубликовать код для этого, если необходимо, в редактировании, но я уверен, что проблема не в этом. Если пользователь решает добавить «Новый пользовательский график», текстовое поле отображается с частичным, что позволяет пользователю ввести имя нового графика. Это прекрасно работает; новый график создается в базе данных, и, как и ожидалось, в таблице компоновщиков PlotsPresets появляется ссылка. Ниже приведен фрагмент _newcustomplot:
.title
New Custom Plot
%br
%fieldset
= f.label(:name, "Name:")
%br
= f.text_field(:name)
%br
= f.hidden_field :_destroy
= link_to "Remove plot", remove_plot_path, class: "remove_plot", remote: true
.breaks
%br
Однако, партиалы «Добавить график по умолчанию» и «Добавить существующий пользовательский график» немного сложнее; они полагаются на элемент options_from_collection_for_select, который отображает существующие графики, которые они могут добавить в свои предустановки. Идея состоит в том, чтобы добавить их в коллекцию для предустановки, чтобы в таблице компоновщиков была новая ссылка (но новый график не создавался). Вот пример одного из частичных элементов, _defaultplot:
.title
Default Plot
%br
%fieldset
= f.label(:id, "Select default plot:")
%br
= f.select(:id, options_from_collection_for_select(Plot.where(is_default_plot: true), :id, :name))
%br
= f.hidden_field :_destroy
= link_to "Remove plot", remove_plot_path, class: "remove_plot", remote: true
.breaks
%br
Само окно выбора прекрасно отрисовывается, отображая все существующие / стандартные графики, которые должны быть доступны пользователю. Однако при отправке формы я сразу получаю сообщение об ошибке 404:
Запущен POST "/ presets" для 127.0.0.1 в 2020-05-01 15:56:42 + 0100
Обработка PresetsController # создать как HTML
Параметры: {"authenticity_token" => "", "preset" => {"name" => "Preset", "description" => "Test with default "," plots_attributes "=> {" 1588345001310 "=> {" id "=>" 2 "," _destroy "=>" false "}}}," commit "=>" Создать пресет "}
Пользовательская нагрузка (29,9 мс) ВЫБЕРИТЕ "users". * FROM "users" WHERE "users". "Id" = $ 1 ORDER BY "users". "Id" AS C LIMIT $ 2 [["id", 1 ], ["LIMIT", 1]]
Отображение ошибок / error_404. html .haml в макетах / приложении
Отображение ошибок / error_404. html .haml в макетах / приложении (Продолжительность: 0,1 мс | Распределения: 31)
Визуализированные макеты / _environment_notice. html .haml (Длительность: 0,0 мс | Распределения: 11) Завершено 404 Не найдено за 405 мс (Просмотров: 82,9 мс | ActiveRecord: 297,8мс | Распределения: 66151)
Наконец, вот я s код контроллера:
#POST /presets
def create
print("Create")
#get details to save to presets from current user and params
email = current_user.email
_preset_params = preset_params
@preset = current_user.presets.create(name: _preset_params[:name], description: _preset_params[:description], user_email: email)
@preset.save
if _preset_params[:plots_attributes] != nil
for plot in _preset_params[:plots_attributes]
plot_params = plot[1]
#if an ID has been submitted and that plot already exists, add it to the preset's association
if plot_params[:id] != nil && Plot.exists?(plot_id)
@preset.plots << Plot.find(plot_id)
#otherwise, create a new plot
elsif plot_params[:_destroy] == "false"
if current_user.is_admin == false
plot_params[:is_default_plot] = false
end
@preset.plots.create(name: plot_params[:name], is_default_plot: plot_params[:is_default_plot], user_email: email)
end
end
end
if @preset.save
redirect_to presets_path, notice: 'Preset was successfully created.'
return
else
render :new
return
end
end
Я понятия не имею, что за кулисами меняется элемент options_from_collection_for_select, но всякий раз, когда я добавляю один из этих элементов в форму, это вызывает ошибку 404 (даже если Я «удаляю» это и устанавливаю _destroy, чтобы быть правдой). Любое понимание того, что является причиной этого, будет с благодарностью.