已编辑:以下代码反映了您答案中的最后建议......
我在从一种形式保存到两个不同的模型时遇到了麻烦...我试图跟踪rails#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
我在大多数示例中找到的内容,包括railscast,都是在患者表单中创建一个新样本,“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 %>
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 %>
当我点击提交按钮时,一切似乎都有效,但没有任何内容保存在患者表中。
这是日志:
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_吗?有没有办法实现我想要的?或者我应该尝试不同的方法吗?
更新: 这是我的病人和样本控制器的代码:
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的建议和建议,我找到了解决方案
更新,最终代码 - 我的解决方案
模型/ samples.rb
class Sample < ActiveRecord::Base
attr_accessible :approved, :patient_id, :result, :patient_attributes
belongs_to :patient
accepts_nested_attributes_for :patient
end
模型/ patient.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 %>
答案 0 :(得分:2)
必须从父表单调用fields_for
方法,例如:
<强> _form.html.erb 强>
<div><%= render 'patient', f: f %></div>
<强> patient.html.erb 强>
<%= f.fields_for :patient do |p| %>
<!-- code -->
<% end %>
试试这个。如果它仍然无法正常工作,请您告诉我们您的控制器。 希望这个帮助
修改强>
好的,然后尝试将您的示例模型patient
替换为patient_attributes
:
attr_accessible patient_attributes: [:patient_name, :date_of_birth]
答案 1 :(得分:2)
如果您的patientID是不同的字段而不是样本表中的外键, 你必须通过::patient_id使它可用,或者如果patientID用于不同的目的则保留它。
您需要为
像这样更改您的样本模型
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。