【问题标题】:How to assign strong parameters of deeply-nested attibutes in Rails4?如何在 Rails4 中分配深度嵌套属性的强参数?
【发布时间】:2015-04-14 15:34:29
【问题描述】:

我正在根据Railscast 在 Rails4 应用程序中尝试嵌套对象。模型调查has_many :questions,模型问题依次has_many :answers,模型回答belongs_to :questions 和问题belongs_to :survey。

现在,模型一开始是完全分开的,虽然我不希望这样,但效果很好。我更喜欢将它们嵌套在一起,这样我就可以同时分配和显示不同的对象。

然后我必须弄清楚如何将这些嵌套对象/属性的强参数列入白名单,并且有很好的问题here 帮助了我。

当我创建我的数据库条目时,一切正常。当我想编辑数据库中的对象时,问题就来了。在日志中,我得到“未经许可的参数:答案”,即使我已将每个属性(包括答案​​的属性)列入白名单。我就是不明白为什么。

谁能指出我正确的方向?

我的调查控制器:

class SurveysController < ApplicationController
 before_action :set_survey, only: [:show, :edit, :update, :destroy]
  def index
    @surveys = Survey.all
  end

  def show
    @survey = Survey.find(params[:id])
  end

  def new
    @survey = Survey.new
    3.times do 
      question = @survey.questions.build
      4.times { question.answers.build }
    end
  end

  def create
    @survey = Survey.new(survey_params)
    if @survey.save
      flash[:notice] = 'Survey was successfully created.' 
      redirect_to(:action => 'index')
    else
      render('new') 
    end
  end

  def edit
    @survey = Survey.find(params[:id])
  end

  def update
    #Find an existing object using form parameters
    @survey = Survey.find(params[:id])
    #Update the object
    if @survey.update_attributes(survey_params)
      flash[:notice] = "Survey updated successfully."
      #If update succeeds, redirect to 'show' action.
      redirect_to(:action => 'show', :id => @survey.id)
    else
      #Else redisplay the 'edit' form.
      render('edit')
    end
  end 

  def delete
    @survey = Survey.find(params[:id])
  end

  def destroy
     @survey = Survey.find(params[:id]).destroy
     flash[:notice] = "Survey destroyed successfully."
     redirect_to(:action => 'index')
  end

  private

   def set_survey
      @survey = Survey.find(params[:id])
   end

  def survey_params
         params.require(:survey).permit(:name, questions_attributes: [:survey_id, :id, :content, answers_attributes: [:id, :question_id, :correct_answer, :content]])
  end
end

我的survey.rb 模型:

class Survey < ActiveRecord::Base
     has_many :questions, :dependent => :destroy
     accepts_nested_attributes_for :questions, :reject_if => lambda { |a| a[:content].blank? }

     scope :sorted, lambda { order("questions.created_at DESC")}
end

编辑:我的问题.rb-model:

class Question < ActiveRecord::Base
    belongs_to :survey
    has_many :answers, :dependent => :destroy
    accepts_nested_attributes_for :answers, :reject_if => lambda { |a| a[:content].blank? }

    scope :sorted, lambda { order("questions.created_at DESC")}
end

我的 answer.rb 模型

class Answer < ActiveRecord::Base
   belongs_to :question
end

我的 /surveys/show.html.erb

<td><%= link_to('<< Back to list', {:action => 'index'}, :class =>     'action_index') %></td>

<div class="survey show">
  <h2><strong>Show survey:</strong></h2>
    <table summary="Survey detail view">
        <tr>
           <th>Survey name: </th>
             <td><%= h @survey.name %></td>
        </tr>
            <tr>
               <th>Question: </th>
                   <td><% for question in @survey.questions do %>
                        <li><%= h question.content %></li>
                        <ul>
                            <% for answer in question.answers do %>
                                <li><%= h answer.content %></li>
                            <% end %>
                        </ul>
                      <% end %>
                   </td>
         </tr>

    <tr>
        <th>Created_at: </th>
            <td><%= @survey.created_at %></td>
    </tr>

  <tr>

    <td><%= link_to('Edit', {:action => 'edit', :id => @survey.id }, :class => 'action_edit')  %></td>
    <td><%= link_to('Delete', {:action => 'destroy', :id => @survey.id }, :class => 'action_edit')  %></td>
      </tr>
    </table>
</div>

我的 _form_for.html.erb

<%= form_for @survey do |f| %>
  <%= f.error_messages %>
    <p>
       <%= f.label :name %><br />
       <%= f.text_field :name %>
    </p>
       <%= f.fields_for :questions do |ff| %>
          <%= render 'question_fields', :f => ff %>
       <% end %>
       <%= f.fields_for :answers do |fff| %>
            <%= render 'answer_fields', :f => fff %>
       <% end %>
    <p><%= f.submit "Submit" %></p>
 <% end %>

我的_question_field.html.erb

<p>
   <%= f.label :content, "Question" %><br />
   <%= f.text_area :content, :rows => 3 %><br />
</p>

我的 _answer_field.html.erb

<p>
   <%= f.label :content, "Answer" %>
   <%= f.text_field :content %>
   <%= f.radio_button :correct_answer, true %>
</p>

【问题讨论】:

    标签: ruby-on-rails strong-parameters


    【解决方案1】:

    您已经发布了两次调查模型,而不是您的问题模型。你的问题是accept_nested_attributes_for :answers吗?

    假设您有并且我正确理解了您的结构,那么您的问题很可能出在您的表单中 - 而不是 f.fields_for :answers,您应该有 ff.fields_for :answers,嵌套在 f.fields_for :questions 中,因为这是一个嵌套资源提问而不是调查。所以:

    <%= f.fields_for :questions do |ff| %>
      <%= render 'question_fields', :f => ff %>
    
      <%= ff.fields_for :answers do |fff| %>
        <%= render 'answer_fields', :f => fff %>
      <% end %>
    
    <% end %>
    

    【讨论】:

    • 就是这样。非常感谢你!我还更新了我的问题,以便它反映您对我的模型的 cmets。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-06-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多