【问题标题】:Using simple forms (nested forms) in `show.html.erb` won't save data to database在 `show.html.erb` 中使用简单表单(嵌套表单)不会将数据保存到数据库
【发布时间】:2018-04-02 13:46:23
【问题描述】:

我一直在尝试在我的 Rails 应用程序中使用嵌套表单或简单表单,特别是在我的 questions/show.html.erb 中,但是当我单击提交时,它会给我一些奇怪的参数。

我的问题有很多答案。我希望能够在问题显示视图中创建答案。

这是我的代码:

问题控制器:

def new
 @question = Question.new
 @question.answers.build
end

def create
 @question = Question.new(question_params)
 if @question.save
  redirect_to question_path
 else
  render 'new'
 end
end

def show
  @question = Question.find(params[:id])
  @question.answers.build
end

def edit
  @question = Question.find(params[:id])
  @question.answers.build
end

def update
  @question = Question.find(params[:id])
  if @question.update(question_params)
    redirect_to question_path
  else
    render :edit
  end
end

def question_params
 params.require(:question).permit(:id, :question_title, :question_text, answers_attributes: [ :id, :answer_text, :question_id, :_destroy])
end

AnswersController.rb

def new
  @answer = Answer.new
end

def create
  @answer = Answer.new(@answer_params)
  @answer.question = Question.find(params[:question_id])
  @answer.save
  respond_to do |format|
    format.js
  end
end

def edit
  @answer = Answer.find(params[:id])
end

def update
  @answer = Answer.find(params[:id])
  if @answer.update(answers_params)
    redirect_to answers_path
  else
    render :edit
  end
end

问题.rb

class Question < ApplicationRecord
  belongs_to :topic
  belongs_to :user
  has_many :answers, dependent: :destroy
  accepts_nested_attributes_for :answers, allow_destroy: true
end

答案.rb

class Answer < ApplicationRecord
  belongs_to :question
end

问题/show.html.erb

<div class=question-show> 
  <div class="question-title"> <%= @question.question_title %></div>
  <div class="question_text"> <%= @question.question_text %></div>
  <div class="question-user"><%= question_show_timestamp(@question) %> </div>
  <div class="question-topic"> <strong>Category:</strong> <%= @question.topic.category.category_name %></div>
  <div class="question-topic"> <strong>Topic:</strong> <%= @question.topic.topic_name %></div>
  <div class="question-answers">
    <%= render "form" %>
    <hr>
    <% @question.answers.select(&:persisted?).each do |answer| %>
      <div> 
        <div> <%= answer.answer_text %> </div>
        <div class="small-font"> <%= answer_timestamp(answer) %> by <%= answer.user.user_name %> </div>
      </div>
      <hr>
    <% end %>
  </div>
</div>

_form.html.erb

<%= simple_form_for @question do |form| %>
  <div class="TabbedPanelsContent">
    <%= form.simple_fields_for(:answers, @question.answers.build) do |builder| %>
      <%= render "answer_fields", form: builder %>
    <% end %>
    <p><%= link_to_add_fields "Add answer", form, :answers %></p>
  </div>
  <%= form.submit "Save" %>
<% end %>

请注意我正在使用

simple_fields_for(:answers, @question.answers.build)

如果我将它写为 simple_fields_for :answers,它会为问题的每个答案呈现一个字段,我相信这是因为我在“show.html.erb”视图中使用了这个 simple_form,但我是不完全确定。任何关于它的 cmets 都会非常有帮助!

_answer_fields.html.erb

<div class="fields">
  <p>
    <%= form.input_field :_destroy, as: :hidden %>
    <%= link_to "Remove", "#", class: "remove_record" %>
  </p>
  <p class="lable">Answer</p>
  <p class="field"><%= form.text_field :answer_text %></p></br>
</div>

当我点击保存时会发生这种情况:

Started PATCH "/questions/19" for 172.18.0.1 at 2018-04-02 13:15:06 +0000
Cannot render console from 172.18.0.1! Allowed networks: 127.0.0.1, ::1, 127.0.0.0/127.255.255.255
Processing by QuestionsController#update as HTML
  Parameters: {"utf8"=>"✓", "authenticity_token"=>"yhLrwHi8wgPRx30ysPakqcKfb+Pjd3BhWN4F/7K5m+FaraCpi7iq6RcrT98q/ISGTv/g8ZlcrDX1ItnrRTBgfQ==", "question"=>{"answers_attributes"=>{"0"=>{"_destroy"=>"false", "answer_text"=>"wer"}}}, "commit"=>"Save", "id"=>"19"}
  Question Load (0.8ms)  SELECT  "questions".* FROM "questions" WHERE "questions"."id" = $1 LIMIT $2  [["id", 19], ["LIMIT", 1]]
   (0.4ms)  BEGIN
  Topic Load (0.8ms)  SELECT  "topics".* FROM "topics" WHERE "topics"."id" = $1 LIMIT $2  [["id", 1], ["LIMIT", 1]]
  User Load (0.6ms)  SELECT  "users".* FROM "users" WHERE "users"."id" = $1 LIMIT $2  [["id", 2], ["LIMIT", 1]]
   (0.5ms)  ROLLBACK
  Rendering questions/edit.html.erb within layouts/application
  Rendered questions/edit.html.erb within layouts/application (0.6ms)
  User Load (0.9ms)  SELECT  "users".* FROM "users" WHERE "users"."id" = $1 ORDER BY "users"."id" ASC LIMIT $2  [["id", 2], ["LIMIT", 1]]
  Category Load (0.8ms)  SELECT "categories".* FROM "categories"
  Rendered layouts/_navbar.html.erb (7.2ms)
  Rendered questions/_new.html.erb (3.2ms)
Completed 200 OK in 416ms (Views: 392.0ms | ActiveRecord: 4.8ms)

我觉得很有趣的那句话是:

Parameters: {"utf8"=>"✓", "authenticity_token"=>"yhLrwHi8wgPRx30ysPakqcKfb+Pjd3BhWN4F/7K5m+FaraCpi7iq6RcrT98q/ISGTv/g8ZlcrDX1ItnrRTBgfQ==", "question"=>{"answers_attributes"=>{"0"=>{"_destroy"=>"false", "answer_text"=>"wer"}}}, "commit"=>"Save", "id"=>"19"}

如您所见,在“answers_attributes”=> 中有 n 个额外的“0”。难道我做错了什么?任何建议或帮助将不胜感激。

【问题讨论】:

  • 你能说明params.require是如何实现的吗?
  • 一切正常。这就是accepts_nested_attributes_for 的工作原理。现在,当创建一个问题时,也会创建相关的答案。显示QuestionsController#question_params 方法。
  • 我按照您的要求在 QuestionController 上添加了问题参数。谢谢!!
  • 在答案属性上显示 0 并没有错,因为一个问题可以有 N 个答案。你在这里真正的问题是什么?答案不是保存在您的数据库中吗?
  • question_params 看起来不错。您需要找出您的记录未保存的原因。重新加载页面后,您是否在表单中看到任何验证错误?您应该在尝试使用QuestionsController#update 方法更新@answer 后对其进行调试。

标签: ruby-on-rails nested-forms


【解决方案1】:

那个参数行在你看来很奇怪,但实际上它是 has_many 关系的嵌套表单的工作方式,所以大多数情况下你都正确地实现了一切,但我认为你在这里不需要嵌套表单。

如果您想通过一个请求一次创建或更新问题以及属于该问题的一个或多个答案,则需要嵌套表单。

在这里你只想创建一个答案,你不想触及问题。所以你可以简化整个事情——只为答案创建表单。

questions_controller.rb:

def show
  @question = Question.find(params[:id])
  @answer = @question.answers.build
end

由于您在AnswersController 中回复js,我认为您的表单应该是远程的。

问题/show.html.erb:

<div class="question-answers">
  <%= simple_form_for @answer, remote: true do |f| %>
    <%= f.hidden_field @answer.question_id $>
    <%= render 'answers/form_fields', f: f %>
    <%= f.submit "Save" %>
</div>

(不要忘记将question_id 添加到AnswersController 中的允许参数中)

最好将表单字段移动到answers 视图文件夹。

answers/_form_fields.html.erb:

<div class="fields">
  <p class="lable">Answer</p>
  <p class="field">
    <%= f.text_field :answer_text %>
  </p>
  </br>
</div>

之后,您应该在提交时在日志中看到下一个(如果您的路线一切正常):

Processing by AnswersController#create

那我就改一下你的AnswersController

def create
  @answer = Answer.create(@answer_params)
end

不需要显式设置问题,因为现在您通过参数设置它。如果您只响应一种格式,则无需指定格式。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2019-01-22
    • 2023-03-24
    • 1970-01-01
    • 2020-08-29
    • 2019-08-21
    • 1970-01-01
    • 1970-01-01
    • 2016-10-06
    相关资源
    最近更新 更多