ネストされた属性を取得してデータベースに保存できないようです。私はRails 4を使用しています。
これが私のモデルです:
class Answer < ActiveRecord::Base
belongs_to :question
end
class Question < ActiveRecord::Base
has_many :answers
belongs_to :survey
accepts_nested_attributes_for :answers, allow_destroy: true
end
class Survey < ActiveRecord::Base
has_many :questions
validates_presence_of :name
accepts_nested_attributes_for :questions
end
コントローラは次のとおりです。
def create
@survey = Survey.new(survey_params)
respond_to do |format|
if @survey.save
format.html { redirect_to @survey, notice: 'Survey was successfully created.' }
format.json { render action: 'show', status: :created, location: @survey }
else
format.html { render action: 'new' }
format.json { render json: @survey.errors, status: :unprocessable_entity }
end
end
end
def survey_params
params.require(:survey).permit(:name, questions_attributes:[:content, :id, :survey_id,
answers_attributes:[:content, :id, :questions_id]
])
end
最後に、これがフォーム自体です。 f.fields_forとfields_forだけを使ってみました
<%= form_for(@survey) do |f| %>
<% if @survey.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(@survey.errors.count, "error") %> prohibited this survey from being saved:</h2>
<ul>
<% @survey.errors.full_messages.each do |msg| %>
<li><%= msg %></li>
<% end %>
</ul>
</div>
<% end %>
<div class="field">
<%= f.label :name %><br>
<%= f.text_field :name %>
</div>
<%= f.fields_for :question do |builder| %>
<%= builder.label :content %>
<%= builder.text_area :content %>
<%= f.fields_for :answer do |builder| %>
<%= builder.label :content, "Answer" %>
<%= builder.text_field :content %>
<% end %>
<% end %>
<div class="actions">
<%= f.submit %>
</div>
<% end %>
調査はデータベースにうまく保存されますが、質問と回答は保存されません。私は見つけたすべてのリソースを調べましたが、これを正しく行っているように見えるので、本当に夢中になっています。
この例は簡単な足場なので、貼り付けるコードがいくつかありましたが、他の場所では機能しないようです。
編集:新しいアクションを次のようなものに変更:
def new
@survey = Survey.new
@survey.questions.build
end
動作しました!
これに対する解決策についてはTシャツの回答を参照してください
これが私が使用している新しいフォームですが、調査名のみを保存しています
<%= f.fields_for :question do |question_builder| %>
<%= form_for(@survey) do |f| %>
<% if @survey.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(@survey.errors.count, "error") %> prohibited this survey from being saved:</h2>
<ul>
<% @survey.errors.full_messages.each do |msg| %>
<li><%= msg %></li>
<% end %>
</ul>
</div>
<% end %>
<div class="field">
<%= f.label :name %><br>
<%= f.text_field :name %>
</div>
<%= f.fields_for :question do |question_builder| %>
<%= question_builder.label :content %>
<%= question_builder.text_area :content %>
<%= question_builder.fields_for :answer do |answer_builder| %>
<%= answer_builder.label :content, "Answer" %>
<%= answer_builder.text_field :content %>
<% end %>
<% end %>
<div class="actions">
<%= f.submit %>
</div>
<% end %>
間違ったフォームビルダーオブジェクトを使用しているようです。質問セクションを次のように変更します。
<%= f.fields_for :question do |question_builder| %>
<%= question_builder.label :content %>
<%= question_builder.text_area :content %>
<%= question_builder.fields_for :answer do |answer_builder| %>
<%= answer_builder.label :content, "Answer" %>
<%= answer_builder.text_field :content %>
<% end %>
<% end %>
元々はf.fields_for :answers...
行でf
フォームビルダーを使用していましたが、モデルコードを指定すると、accepts_nested_attributes_for
がQuestion
であるのはAnswer
であるため、フォームビルダーオブジェクトをquestion
セクション。
注:わかりやすくするために、ビルダーオブジェクトの名前を変更しました。
更新
このように深くネストされた関係を構築するには、「構築された」関連付け(この場合はquestions
)をループし、そのhas_many
関連付けでbuild
を再度呼び出す必要があります。したがって、gabrielhilalの答えから離れると、次のようになります。
def new
@survey = Survey.new
@survey.questions.build
@survey.questions.each do |question|
question.answers.build
end
end
注あなたの場合、明示的に1つの質問のみを作成しているため、技術的には代わりに(ループの代わりに)これを行うことができます。
@survey.questions.first.answers.build
免責事項:これを行うためのよりクリーンでより多くのRails-yの方法がある場合、私は悲しいことにそれを認識していません。
コントローラにはquestions_id
があります:
def survey_params
params.require(:survey).permit(:name,
questions_attributes: [
:content, :id, :survey_id,
answers_attributes: [:content, :id, :questions_id]
]
)
end
それはタイプミスですか?また、action_on_unpermitted_parameters
で:raise
をdevelopment.rb
に設定して、survey_params
メソッドで欠落している属性があるかどうかを確認してください。
# In case of unpermitted parameters in the controller raise error.
config.action_controller.action_on_unpermitted_parameters = :raise
new
アクションを変更して@survey.questions.build
を含める必要があります。
def new
@survey = Survey.new
@survey.questions.build
end
しかし、あなたのフォームも間違っています。 question
をquestions
に変更します
<%= f.fields_for :questions do |builder| %> #questions
<%= builder.label :content %>
<%= builder.text_area :content %>
あなたは答えのために同じことをしなければなりません。