【问题标题】:Nested Form in Rails 4 not being rendered in viewRails 4中的嵌套表单未在视图中呈现
【发布时间】:2014-10-07 18:54:05
【问题描述】:

抱歉,如果这个问题已经得到解答,但我找不到任何可以帮助我的东西。我是 Rails 的新手,所以请温柔:D

我一直在努力让嵌套表单工作,我确信我在去年使用 Rails 3 和 railscasts 演示让嵌套表单工作,但 Rails 4 击败了我。

查看日志,正在运行查询以提取关联表的数据,但表单中没有呈现任何内容。

我已经阅读了许多网站,但到目前为止都没有任何帮助,我不知道从哪里开始。我关注的最新文章是这个http://www.createdbypete.com/articles/working-with-nested-forms-and-a-many-to-many-association-in-rails-4/

视图中仍然没有呈现任何内容。

我从哪里开始调试这个,也许我的 Rails 安装坏了?但我可能遗漏了一些重要的东西。

谢谢, 罗伊斯

编辑 - 我添加了一些控制器和有问题的视图

surveys_controller.rb

class SurveysController < ApplicationController
  before_action :set_survey, only: [:show, :edit, :update, :destroy, :answers]

  # GET /surveys
  # GET /surveys.json
  def index
    @surveys = Survey.all
  end

  # GET /surveys/1
  # GET /surveys/1.json
  def show
  end

  # GET /surveys/new
  def new
    @survey = Survey.new
  end

  # GET /surveys/1/edit
  def edit
  end

  # POST /surveys
  # POST /surveys.json
  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 :show, status: :created, location: @survey }
      else
        format.html { render :new }
        format.json { render json: @survey.errors, status: :unprocessable_entity }
      end
    end
  end

  # PATCH/PUT /surveys/1
  # PATCH/PUT /surveys/1.json
  def update
    respond_to do |format|
      if @survey.update(survey_params)
        format.html { redirect_to @survey, notice: 'Survey was successfully updated.' }
        format.json { render :show, status: :ok, location: @survey }
      else
        format.html { render :edit }
        format.json { render json: @survey.errors, status: :unprocessable_entity }
      end
    end
  end

  # DELETE /surveys/1
  # DELETE /surveys/1.json
  def destroy
    @survey.destroy
    respond_to do |format|
      format.html { redirect_to surveys_url, notice: 'Survey was successfully destroyed.' }
      format.json { head :no_content }
    end
  end

  def answers
    @participants = Participant.all
    @questions = @survey.questions
  end

  private
    # Use callbacks to share common setup or constraints between actions.
    def set_survey
      @survey = Survey.find(params[:id])
    end

    # Never trust parameters from the scary internet, only allow the white list through.
    def survey_params
      params.require(:survey).permit(:name,
      :questions_attributes => [:id, :content,
        :answers_attributes => [:id, :content, :participant_id]
      ])
    end
end

participents_controller.rb

class ParticipantsController < ApplicationController
  before_action :set_participant, only: [:show, :edit, :update, :destroy]

  # GET /participants
  # GET /participants.json
  def index
    @participants = Participant.all
  end

  # GET /participants/1
  # GET /participants/1.json
  def show
  end

  # GET /participants/new
  def new
    @participant = Participant.new
  end

  # GET /participants/1/edit
  def edit
  end

  # POST /participants
  # POST /participants.json
  def create
    @participant = Participant.new(participant_params)

    respond_to do |format|
      if @participant.save
        format.html { redirect_to @participant, notice: 'Participant was successfully created.' }
        format.json { render :show, status: :created, location: @participant }
      else
        format.html { render :new }
        format.json { render json: @participant.errors, status: :unprocessable_entity }
      end
    end
  end

  # PATCH/PUT /participants/1
  # PATCH/PUT /participants/1.json
  def update
    respond_to do |format|
      if @participant.update(participant_params)
        format.html { redirect_to @participant, notice: 'Participant was successfully updated.' }
        format.json { render :show, status: :ok, location: @participant }
      else
        format.html { render :edit }
        format.json { render json: @participant.errors, status: :unprocessable_entity }
      end
    end
  end

  # DELETE /participants/1
  # DELETE /participants/1.json
  def destroy
    @participant.destroy
    respond_to do |format|
      format.html { redirect_to participants_url, notice: 'Participant was successfully destroyed.' }
      format.json { head :no_content }
    end
  end

  private
    # Use callbacks to share common setup or constraints between actions.
    def set_participant
      @participant = Participant.find(params[:id])
    end

    # Never trust parameters from the scary internet, only allow the white list through.
    def participant_params
      params.require(:participant).permit(:name)
    end
end

application_controller.rb

class ApplicationController < ActionController::Base
  # Prevent CSRF attacks by raising an exception.
  # For APIs, you may want to use :null_session instead.
  protect_from_forgery with: :exception
end

answers.html.erb

<h1><%= @survey.name %> Answers</h1>

<%= form_for(@survey) do |f| %>
  <% @participants.each do |participant| -%>
  <h3><%= participant.name %></h3>
  <table>
    <thead>
      <tr>
        <td>Questions</td>
        <td>Answer</td>
      </tr>
    </thead>
    <tbody>
      <% @questions.each do |question| -%>
      <tr>
        <td><%= question.content %></td>
        <td>
        <%= f.fields_for :questions, question do |q| -%>
          <%= q.fields_for :answers, question.answers.find_or_initialize_by(participant: participant) do |a| -%>
            <%= a.text_area :content %>
            <%= a.hidden_field :participant_id, participant.id %>
          <% end -%>
        <% end -%>
        </td>
      </tr>
      <% end -%>
    </tbody>
  </table>
  <% end -%>
  <div class="actions">
    <%= f.submit %>
  </div>
<% end -%>

【问题讨论】:

  • 快速建议:在这里发布一些代码。也许是控制器方法和视图本身。
  • 干杯迈尔斯,希望对您有所帮助。
  • 请发布调查模型的内容。你可能错过了accept_nested_attributes_for :questions
  • 嵌套表单丑陋、混乱和脆弱——你需要记住在整个堆栈中正确地做很多小事情。通过使用表单对象,您可以使事情变得更容易理解并帮助隔离更改。表单对象伪装成模型,因此在处理控制器或视图时它们的工作方式与模型相同。有一个关于它的专业 Railscast,或参见:stackoverflow.com/questions/25296385/…
  • 这看起来很有趣,将不得不阅读它

标签: ruby-on-rails nested-forms


【解决方案1】:

由于您是 Rails 新手,让我解释一下嵌套表单是如何为您工作的!

--

嵌套

嵌套 表单实际上根本不是嵌套的——它们是关联 表单。

您必须记住,Rails(由于构建在 Ruby 之上)是一个object orientated 框架。 OOP(面向对象编程)不仅仅是一个流行语 - 它是您的应用程序的基本核心构造以及它如何处理输入/执行。

许多人的问题是他们没有意识到 Rails 的真正本质,因此对它的许多功能如何工作感到困惑。如果您意识到您在 Rails 中所做的一切都应该围绕对象构建,那么生活会变得更加简单!

--

表格

考虑到这一点,您可以开始欣赏objects 在整个 Rails 中的作用,以至于您需要为 Rails 应用程序的每个元素(包括表单)构建/调用对象:

#app/models/survey.rb
Class Survey < ActiveRecord::Base
   has_many :questions
   accepts_nested_attributes_for :questions
end

#app/controllers/surveys_controller.rb
Class SurveysController < ApplicationController
   def new
       @survey = Survey.new
       @survey.questions.build #-> very important
   end
end

#app/views/surveys/new.html.erb
<%= form_for @survey do |f| %>
   ...
   <%= f.fields_for :questions do |q| %>
      <%= q.text_field :title %>
   <% end %>
   <%= f.submit %>
<% end %>

这应该创建一个表单,允许您将关联数据传递给您的子模型。有几个重要的因素需要考虑:

  1. 您需要在“父”模型中包含 accepts_nested_attributes_for
  2. 你需要build你的关联对象
  3. 您需要使用相关对象填充表单

通过遵循这个简单的模式,您将能够填充您希望在视图中显示的嵌套表单

【讨论】:

  • 谢谢 Rich,我错过了@survey.questions.build 只需要弄清楚为什么我的主要项目现在不起作用!同样的问题。
  • 没问题 - 你的主要项目有什么问题?也许我们可以解决它?
  • 同样的问题 Rich,表单不呈现嵌套属性。上面的代码试图找出它为什么不起作用。在主项目中完成了完全相同的操作,但没有渲染。
【解决方案2】:

尝试使用以下代码:

<%= f.fields_for :questions do |q| -%>
      <%= q.fields_for :answers, q.object.answers.find_or_initialize_by(participant: f.object.participant) do |a| -%>
        <%= a.text_area :content %>
        <%= a.hidden_field :participant_id, participant.id %>
      <% end -%>
    <% end -%>

并确保渲染到answers.html.erbsurvey.rb 文件中有accepts_nested_attributes_for :questionsquestion.rb 文件中有accepts_nested_attributes_for :answers

【讨论】:

    【解决方案3】:

    您的调查模型中有 Accept_nested_attributes_for :question 吗?答案模型也一样?

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2016-05-13
      • 1970-01-01
      • 2014-12-05
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-08-11
      • 1970-01-01
      相关资源
      最近更新 更多