使用强参数插入和更新嵌套的"belongs_to"关联

Jef*_*eff 4 activerecord ruby-on-rails ruby-on-rails-4

我有一个学生可以报名参加课程的表格.当用户提交表单时,他就会注册该课程并保存他的付款信息.换句话说,Enrollment创建一个对象并Student更新对象...除了我无法Student更新.这可能吗?如果是这样,怎么样?

我的模特......

class Student < ActiveRecord::Base
    has_many :enrollments
end

class Enrollment < ActiveRecord::Base
    belongs_to :student
    accepts_nested_attributes_for :student
end
Run Code Online (Sandbox Code Playgroud)

我的(缩写)形式......

<%= form_for :enrollment, html: { id: "enrollment_form" } do |f| %>

    <%= f.fields_for :student_attributes do |student_builder| %>
        <%= student_builder.hidden_field :payment_name %>
    <% end %>

    <%= f.hidden_field :payment_token %>

    <div class="field terms">
        <%= f.check_box :agreed_to_terms %>
        <%= f.label :agreed_to_terms, "I agree to the terms and conditions." %>
    </div>

<% end %>
Run Code Online (Sandbox Code Playgroud)

我的控制器......

class EnrollmentsController < ApplicationController

  def create
    @enrollment = Enrollment.new(enrollment_params)
    @enrollment.clazz_id = @clazz.id
    @enrollment.student_id = @student.id
    @enrollment.save
  end

  private
    def enrollment_params
      params.require(:enrollment).permit(:payment_token, :agreed_to_terms, student_attributes: [:payment_name])
    end
end
Run Code Online (Sandbox Code Playgroud)

POST参数......

{
  "enrollment"=> {
    "student_attributes"=> {
      "payment_name"=> "MasterCard ending in 9840"
    },
    "payment_token"=> "CC11ho86XxVqsUW7Cn9YjCHg?1376007969212",
    "agreed_to_terms"=> "1"
  },
  "clazz_id"=> "7"
}
Run Code Online (Sandbox Code Playgroud)

我试过的每一个排列student,students,_attributes在表单生成器,但他们都不工作.

小智 5

好的,我看到了一些事情:

  1. 嵌套的属性,如描述的API "让您保存在相关记录的属性通过." 这意味着

    class Enrollment < ActiveRecord::Base
        belongs_to :student
        accepts_nested_attributes_for :student
    end
    
    Run Code Online (Sandbox Code Playgroud)

    本质上不起作用,因为您试图接受来自父级的嵌套属性.因此,您需要首先重新考虑您的Active Record配置.

    如果我们假装全部平方,那么更多的语法错误是:

  2. 更换

    <%= f.fields_for :student_attributes do |student_builder| %>
    
    Run Code Online (Sandbox Code Playgroud)

    <%= f.fields_for :students do |student_builder| %>
    
    Run Code Online (Sandbox Code Playgroud)

    这可能会:students让人感到困惑,但是传递给fields_for帮助程序会调用嵌套的student对象,而:student_attributes后者则是来自POST参数的哈希键fields_for.

  3. 在您的强参数中,您还需要允许学生,:id以便您的更新操作有参考.否则,它只会创建一个新学生.所以改成它

    private
      def enrollment_params
        params.require(:enrollment).permit(:payment_token, :agreed_to_terms, student_attributes: [:payment_name, :id])
      end
    
    Run Code Online (Sandbox Code Playgroud)

我不确定这是否一切,但希望这是一个开始.祝好运.