ruby на рельсах, не может передать значения check_box_tag обратно в update_attributes
У меня есть довольно простое приложение на Rails, которое выполняет математические тесты. Пользователи могут создавать математические задачи с вопросом и ответом. Они также могут создавать экзамены с названием. Модели связаны с отношением has_many_and_belongs_to, потому что у каждого теста может быть много проблем, и каждая проблема может принадлежать множеству тестов. Эта связь, кажется, работает хорошо в том, что когда я удаляю проблемы или экзамены, списки связанных объектов обновляются. В настоящее время у меня есть то, что, когда вы создаете экзамен, представление дает вам список флажков, по одному для каждой проблемы в базе данных проблем. Пользователь нажимает флажки для задач, которые они хотят в своем экзамене, и какие бы флажки не были установлены, эти проблемы добавляются к экзамену. Я покажу код для обновления, так как это представление, которое я использовал для тестирования.
Вот мнение:
<h2>Available Problems:</h2>
<% Problem.all.each do |prob| %>
<%= f.fields_for "exam[problem_ids][]", prob do |builder| %>
<p>
<%= check_box_tag "exam[problem_ids][]", prob.id, @exam.problems.include?(prob) %>
<%= prob.question %> = <%= prob.answer %> | <%= link_to "Edit", edit_problem_path(prob) %>
</p>
<% end %>
<% end %>
Я должен был использовать check_box_tag
потому что если бы я попытался использовать builder.check_box
, это не сохранит, какие ящики уже были отмечены.
Мой контроллер:
def update
@exam = Exam.find(params[:id])
if @exam.update_attributes(params[:exam].permit(:title, :problem_ids))
redirect_to @exam
else
render 'edit'
end
end
В представлении я сохранил все результаты флажков в массиве problem_ids. Я знаю, что этот массив заполняется правильно, потому что, когда я добавляю следующий код, он работает.
@exam.problems = []
params[:exam][:problem_ids].each {
|prob_id|
@exam.problems << Problem.find(prob_id)
}
Очевидно, это очень хакерский способ сделать это, так как я каждый раз вручную строю список проблем, но я просто не могу понять, как получить результаты этих флажков для автоматического заполнения в update_attributes
метод. Есть идеи?
ОБНОВЛЕНИЕ: В соответствии с предложением Донована ниже, я применил следующий метод в моей модели экзамена:
def problem_ids=(some_problem_ids)
@exam.problems.clear
some_problem_ids.each {
|prob_id|
@exam.problems << Problem.find(prob_id)
}
end
Насколько я понимаю, это должен быть метод "сеттера" для problem_ids
, К сожалению, список проблем все еще не обновляется, когда я использую следующую строку в моем контроллере экзамена:
@exam.update_attributes(params[:exam].permit(:title, :problem_ids))
PS я должен поставить .permit(:title, :problem_ids)
немного или я получу ForbiddenAttributesError
,
2 ответа
Спасибо за вашу помощь, но я наконец-то понял это самостоятельно. Проблема заключалась в том, что, хотя я позволял problem_ids
чтобы передать в качестве параметра, я не говорил контроллеру, что это на самом деле массив. Итак, как только я изменил соответствующую строку на:
@exam.update_attributes(params[:exam].permit(:title, problem_ids: []))
это сработало отлично!
@exam.problems - это список объектов, но также должен быть problem_ids
Метод сеттера на экзамене из-за отношений, поэтому
@exam.update_attributes(params[:exam])
должен делать то, что вы хотите. Если по какой-то причине вам нужно только обновить problem_ids, это должно сработать:
@exam.update_attribute(:problem_ids, params[:exam][:problem_ids])
Примечание: я пропустил rails4 strong_parameters, чтобы сделать ответ универсальным для rails 3 или 4, убедитесь, что вы используете подходящие методы для вашей версии.