Rails: выбор радиокнопок для вложенных объектов - PullRequest
13 голосов
/ 23 февраля 2011

Я застрял с этой простой задачей выбора. У меня есть эти модели:

#  id         :integer(4)      not null, primary key
#  category   :string(255)
#  content    :text
class Question < ActiveRecord::Base
    has_many :choices, :dependent => :destroy
    accepts_nested_attributes_for :choices
end

#  id          :integer(4)      not null, primary key
#  content     :text
#  correct     :boolean(1)
#  question_id :integer(4) 
class Choice < ActiveRecord::Base
    belongs_to :question
end

Когда я создаю новый вопрос, я хочу указать во вложенной форме не только content из Question, но даже content из 3 Answer объектов, и выбрать с помощью переключателя, который Одним из них является correct ответ. В действии new контроллера у меня есть это:

def new
    @title = "New Question"
    @question = Question.new
    3.times { @question.choices.build }

    respond_to do |format|
        format.html # new.html.erb
        format.xml  { render :xml => @question }
    end
end

Это код формы:

<%= simple_form_for @question do |question_form| %>
    <%= question_form.error_notification %>

    <div class="inputs">
    <%= question_form.input :content, :label => 'Question' %>
    <%= question_form.input :category, :collection => get_categories, :include_blank => false %>

    <% @question.choices.each do |choice| %>
        <%= question_form.fields_for :choices, choice do |choice_fields| %>
            <%= choice_fields.input :content, :label => 'Choice' %>
            <%= choice_fields.radio_button :correct, true %>
            <%= choice_fields.label :correct, 'Correct Answer' %>
        <% end %>
    <% end %>
    </div>

    <div class="actions">
    <%= question_form.button :submit %>
    </div>
<% end %>

Проблема в том, что этот код выдает три переключателя с разными именами: вы можете выбрать более одного правильного ответа, и это не правильное поведение. Названия трех переключателей: question[choices_attributes][0][correct], question[choices_attributes][1][correct] и question[choices_attributes][2][correct].

Вопрос: как создать три переключателя с одинаковым именем, чтобы выбрать один и только один правильный ответ? Как я могу создать правильный массив params, чтобы сохранить их в действии create следующим образом:

def create
    @question = Question.new(params[:question])
    # render or redirect stuff....
end

Большое спасибо!

Ответы [ 4 ]

9 голосов
/ 04 сентября 2017

Вы можете использовать radio_button_tag и передать ему свой собственный атрибут имени.

Поскольку вы все еще находитесь в области действия choice_fields, у вас есть доступ к нескольким методам, которые могут раскрыть объект, с которым вы работаетеon, что поможет вам правильно назвать ваше radio_button_tag.

Следующий код даст вашему переключателю правильное имя, которое будет принято как вложенный атрибут:

<%= radio_button_tag "question[choices_attributes][#{choice_fields.index}][correct]", true, choice_fields.object.correct %>

choice_fields.index дает вам доступ к правильному индексу создаваемого ресурса, поэтому первая копия будет иметь имя question[choices_attributes][0][correct], вторая question[choices_attributes][1][correct] и т. Д.

choice_fields.object.correct даетВы получаете доступ к текущему значению, поэтому правильные переключатели будут заполнены для редактирования форм.

Обновление: Решение, приведенное выше, на самом деле неверно, оно дает каждому переключателю различные nameатрибут, чтобы они не работали вместе (вы можете выбрать несколько переключателей одновременно).

Решение, с которым я закончил, было в следующих строках:

<%= radio_button_tag "question[choices_attributes][correct_choice]", choice_fields.index, choice_fields.object.correct %>

Thisдает каждому переключателюТо же имя, что и у других, и значение, равное индексу правильного выбора.Хэш параметров в итоге выглядит следующим образом:

question: {choices_attributes: {
        "0": {//choice 0},
        "1": {//choice 1},
        etc...
    },
    correct_choice: //index of correct answer
}

Затем я обновил свой контроллер, чтобы вручную обновить правильный выбор следующим образом:

def create

    # Find the index of the correct choice in the params hash
    correct_index = params[:question][:correct_choice]

    # mark the question at the correct index as correct
    params[:question][:choiceses_attributes][correct_index][:correct] = true

    # Use the updated params hash to create a new Question/update an existing Question

    @question = Question.new(params[:question])
    # render or redirect stuff....
end
6 голосов
/ 12 сентября 2011

Вы можете передать опцию name методу radio_button:

<%= choice_fields.radio_button :correct, true, :name => "choices_attributes" %>

(Из документации по рельсам http://api.rubyonrails.org/classes/ActionView/Helpers/FormHelper.html: кнопка радио (имя_объекта, метод, tag_value, options = {}))

Надеюсь, это поможет.

1 голос
/ 23 февраля 2011

Это не ответ, но я бы порекомендовал вам попробовать Formtastic.Это позволяет иметь дело с вложенными моделями, такими как STUPID EASY: https://github.com/justinfrench/formtastic

0 голосов
/ 21 июля 2017

Это определенно работает на Rails 4 .Не проверял другие версии:

Ваше поле ярлыка и радио должно выглядеть следующим образом:

<%= choice_fields.radio_button :correct, true %>
<%= choice_fields.label :correct, value: true, do %>
  'True'
<% end %>
<%= choice_fields.radio_button :correct, false %>
<%= choice_fields.radio_button :correct, value: false, do %>
  'False'
<% end %>

Чтобы ярлык срабатывал при нажатии кнопки переключателя, вы должны иметь value: whatever_your_value_is in <%= choice_fields.label ... %>

...