保存到两个不同的模型 - accepts_nested_attributes_for不起作用



编辑:下面的代码反映了您答案的最后建议...

我无法从一个表单保存到两个不同的模型......我试图遵循 rails casts #196 并在 stackoverflow 上查看了其他几个示例,但我还没有弄清楚如何做到这一点,因为我的情况有点不同......

所以,我有两个模型:

class Patient < ActiveRecord::Base
  attr_accessible :date_of_birth, :patient_name
  has_many :samples
end
class Sample < ActiveRecord::Base
  attr_accessible :approved, :patientID, :result, patient_attributes: [:patient_name, :date_of_birth]
  belongs_to :patient
  accepts_nested_attributes_for :patient
end

我在我看到的大多数例子中发现的,包括railscasts,是在患者表单中创建一个新样本,而"accepts_nestes_attributes_for"在"患者"模型中......但我想做的恰恰相反,即在新样本形式中创建一个新患者。

这是我的观点,我对样本有一个正常形式,然后对患者部分有一个部分形式:

_form.html.erb

<%= form_for(@sample) do |f| %>
  <% if @sample.errors.any? %>
    <div id="error_explanation">
      <h2><%= pluralize(@sample.errors.count, "error") %> prohibited this sample from being saved:</h2>
      <ul>
      <% @sample.errors.full_messages.each do |msg| %>
        <li><%= msg %></li>
      <% end %>
      </ul>
    </div>
  <% end %>
  <div class="field">
    <%= f.label :result %><br />
    <%= f.text_area :result %>
  </div>
  <div class="field">
    <%= f.label :approved %><br />
    <%= f.check_box :approved %>
  </div>
  <div><%= render 'patient', f: f %></div>
  <div class="actions">
    <%= f.submit %>
  </div>
<% end %>

患者.html.erb

<%= f.fields_for :patient do |p| %>
<div class="field">
    <%= p.label :patient_name %><br />
    <%= p.text_field :patient_name %>
</div>
<div class="field">
    <%= p.label :date_of_birth %><br />
    <%= p.date_select :date_of_birth %>
</div>
<% end %>

当我单击提交按钮时,一切似乎都有效,但没有任何东西保存到患者表中。

这是日志:

Started POST "/samples" for 127.0.0.1 at 2013-10-12 23:32:03 +0100
Processing by SamplesController#create as HTML
  Parameters: {"utf8"=>"✓", "authenticity_token"=>"13OKZ8DaGJ4zTb35q+ymSzx7r+Ipxou1u+XrR4jtyeI=", "sample"=>{"result"=>"teste 3", "approved"=>"0"}, "patient"=>{"patient_name"=>"Joao", "date_of_birth(1i)"=>"2013", "date_of_birth(2i)"=>"10", "date_of_birth(3i)"=>"10"}, "commit"=>"Create Sample"}
   (0.1ms)  begin transaction
  SQL (0.5ms)  INSERT INTO "samples" ("approved", "created_at", "patientID", "result", "updated_at") VALUES (?, ?, ?, ?, ?)  [["approved", false], ["created_at", Sat, 12 Oct 2013 22:32:03 UTC +00:00], ["patientID", nil], ["result", "teste 3"], ["updated_at", Sat, 12 Oct 2013 22:32:03 UTC +00:00]]
   (2.4ms)  commit transaction
Redirected to http://localhost:3000/samples/3
Completed 302 Found in 6ms (ActiveRecord: 2.9ms)

正如您在日志中看到的,它仅保存到示例表中。我可以这样使用accepts_nested_attributes_for吗?有没有办法实现我想要的?还是我应该尝试不同的方法?

更新:以下是我的患者和样本控制器的代码:

patients_controller.rb

def new
    @patient = Patient.new
    respond_to do |format|
      format.html # new.html.erb
      format.json { render json: @patient }
    end
end
def create
    @patient = Patient.new(params[:patient])
    respond_to do |format|
      if @patient.save
        format.html { redirect_to @patient, notice: 'Patient was successfully created.' }
        format.json { render json: @patient, status: :created, location: @patient }
      else
        format.html { render action: "new" }
        format.json { render json: @patient.errors, status: :unprocessable_entity }
      end
    end
end

samples_controller.rb

def new
    @sample = Sample.new
    @sample.build_patient #suggested by El Key
    respond_to do |format|
      format.html # new.html.erb
      format.json { render json: @sample }
    end
end
def create
    @sample = Sample.new(params[:sample])
    respond_to do |format|
      if @sample.save
        format.html { redirect_to @sample, notice: 'Sample was successfully created.' }
        format.json { render json: @sample, status: :created, location: @sample }
      else
        format.html { render action: "new" }
        format.json { render json: @sample.errors, status: :unprocessable_entity }
      end
    end
end

这是我遵循El Key建议后的更新日志:

Started POST "/samples" for 127.0.0.1 at 2013-10-17 00:20:05 +0100
Processing by SamplesController#create as HTML
  Parameters: {"utf8"=>"✓", "authenticity_token"=>"NZXQUdd8tQc206LdEuYF5iO5+89wlfza0VbbvgBGNuI=", "sample"=>{"result"=>"teste 9", "patientID"=>"", "approved"=>"0", "patient_attributes"=>{"patient_name"=>"Sergio", "date_of_birth(1i)"=>"2013", "date_of_birth(2i)"=>"10", "date_of_birth(3i)"=>"2"}}, "commit"=>"Create Sample"}
Completed 500 Internal Server Error in 1ms
ActiveModel::MassAssignmentSecurity::Error - Can't mass-assign protected attributes: patient_attributes:

如您所见,现在我遇到了"无法批量分配受保护属性"的问题,但这不应该工作,因为我在示例模型上有"patient_attributes"吗?

在我解决这个问题之后,我会先尝试检查病人是否存在,然后再提交,并尝试在病人的名字上做 SAYT......但这是未来的一步!

感谢您的帮助

在遵循El-Key的建议和建议后,我找到了解决方案

更新,最终代码 - 我的解决方案

模型/样本.rb

class Sample < ActiveRecord::Base
  attr_accessible :approved, :patient_id, :result, :patient_attributes
  belongs_to :patient
  accepts_nested_attributes_for :patient
end

模型/患者.rb

class Patient < ActiveRecord::Base
  attr_accessible :date_of_birth, :patient_name 
  has_many :samples
end

控制器/samples_controller

def new
    @sample = Sample.new
    @sample.build_patient
    respond_to do |format|
      format.html # new.html.erb
      format.json { render json: @sample }
    end
end
def create
    @sample = Sample.new(params[:sample])
    respond_to do |format|
      if @sample.save
        format.html { redirect_to @sample, notice: 'Sample was successfully created.' }
        format.json { render json: @sample, status: :created, location: @sample }
      else
        format.html { render action: "new" }
        format.json { render json: @sample.errors, status: :unprocessable_entity }
      end
    end
end

视图/示例/_form.html.erb

<%= form_for(@sample) do |f| %>
  <% if @sample.errors.any? %>
    <div id="error_explanation">
      <h2><%= pluralize(@sample.errors.count, "error") %> prohibited this sample from being saved:</h2>
      <ul>
      <% @sample.errors.full_messages.each do |msg| %>
        <li><%= msg %></li>
      <% end %>
      </ul>
    </div>
  <% end %>
  <div class="field">
    <%= f.label :result %><br />
    <%= f.text_area :result %>
  </div>
    <div class="field">
        <%= f.label :patient_id, 'Patient ID' %><br />
        <%= f.text_area :patient_id %>
    </div>
  <div class="field">
    <%= f.label :approved %><br />
    <%= f.check_box :approved %>
  </div>
  <div><%= render 'patient', f: f %></div>
  <div class="actions">
    <%= f.submit %>
  </div>
<% end %>

视图/示例/_patient.html.erb

<%= f.fields_for :patient do |p| %>
<div class="field">
       <%= p.label :patient_name %><br />
       <%= p.text_field :patient_name %>
</div>
<div class="field">
       <%= p.label :date_of_birth %><br />
       <%= p.date_select :date_of_birth %>
</div>
<% end %>

fields_for 方法必须从父窗体调用,例如:

_form.html.erb

<div><%= render 'patient', f: f %></div>

患者.html.erb

<%= f.fields_for :patient do |p| %>
  <!-- code -->
<% end %>

试试这个。如果它仍然无法正常工作,您能否向我们展示您的控制器。希望这个帮助

编辑
好的,然后尝试将示例模型patient替换为patient_attributes

attr_accessible patient_attributes: [:patient_name, :date_of_birth]
  1. 如果您有 patientID,这是一个不同的字段,而不是样本表中的外键,您必须通过 :p atient_id 使其可用,或者如果 PatientID 用于其他目的,则保留它。

  2. 您需要为以下字段指定一个新对象

像这样更改示例模型

attr_accessible :approved, :patientID, :result, :patient_attributes

和样品形状线从

<div><%= render 'patient', f: f %></div>

<div>
<%= f.fields_for :patient, Patient.new do |p| %>
  <%= p.text_field :name %>
  <%= p.text_field :date_of_birth %>
<% end %>
</div>

我创建了一个示例应用,供你了解其工作原理。

https://github.com/ravensnowbird/inverse_nested

您也可以删除 @sample.build_patient。

相关内容

  • 没有找到相关文章

最新更新